[cfe-commits] r141650 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp test/CXX/special/class.copy/p11.0x.move.cpp
Sean Hunt
scshunt at csclub.uwaterloo.ca
Mon Oct 10 23:43:29 PDT 2011
Author: coppro
Date: Tue Oct 11 01:43:29 2011
New Revision: 141650
URL: http://llvm.org/viewvc/llvm-project?rev=141650&view=rev
Log:
Get rid of ShouldDeleteMoveConstructor.
Added:
cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=141650&r1=141649&r2=141650&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Oct 11 01:43:29 2011
@@ -2838,9 +2838,6 @@
/// deleted.
bool ShouldDeleteCopyAssignmentOperator(CXXMethodDecl *MD);
- /// \brief Determine if a defaulted move constructor ought to be deleted.
- bool ShouldDeleteMoveConstructor(CXXConstructorDecl *CD);
-
/// \brief Determine if a defaulted move assignment operator ought to be
/// deleted.
bool ShouldDeleteMoveAssignmentOperator(CXXMethodDecl *MD);
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=141650&r1=141649&r2=141650&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Oct 11 01:43:29 2011
@@ -3963,7 +3963,7 @@
return;
}
- if (ShouldDeleteMoveConstructor(CD)) {
+ if (ShouldDeleteSpecialMember(CD, CXXMoveConstructor)) {
if (First) {
CD->setDeletedAsWritten();
} else {
@@ -4124,6 +4124,10 @@
IsConstructor = true;
ConstArg = MD->getParamDecl(0)->getType().isConstQualified();
break;
+ case CXXMoveConstructor:
+ IsConstructor = true;
+ IsMove = true;
+ break;
default:
llvm_unreachable("function only currently implemented for default ctors");
}
@@ -4168,7 +4172,7 @@
// a destructor, we have already checked this case.
if (CSM != CXXDestructor) {
SpecialMemberOverloadResult *SMOR =
- LookupSpecialMember(BaseDecl, CSM, ConstArg, false, IsMove, false,
+ LookupSpecialMember(BaseDecl, CSM, ConstArg, false, false, false,
false);
if (!SMOR->hasSuccess())
return true;
@@ -4178,6 +4182,13 @@
if (CheckConstructorAccess(Loc, BaseCtor, BaseCtor->getAccess(),
PDiag()) != AR_accessible)
return true;
+
+ // For a move operation, the corresponding operation must actually
+ // be a move operation (and not a copy selected by overload
+ // resolution) unless we are working on a trivially copyable class.
+ if (IsMove && !BaseCtor->isMoveConstructor() &&
+ !BaseDecl->isTriviallyCopyable())
+ return true;
}
}
}
@@ -4203,7 +4214,7 @@
// unique, accessible, non-deleted function.
if (CSM != CXXDestructor) {
SpecialMemberOverloadResult *SMOR =
- LookupSpecialMember(BaseDecl, CSM, ConstArg, false, IsMove, false,
+ LookupSpecialMember(BaseDecl, CSM, ConstArg, false, false, false,
false);
if (!SMOR->hasSuccess())
return true;
@@ -4213,6 +4224,13 @@
if (CheckConstructorAccess(Loc, BaseCtor, BaseCtor->getAccess(),
PDiag()) != AR_accessible)
return true;
+
+ // For a move operation, the corresponding operation must actually
+ // be a move operation (and not a copy selected by overload
+ // resolution) unless we are working on a trivially copyable class.
+ if (IsMove && !BaseCtor->isMoveConstructor() &&
+ !BaseDecl->isTriviallyCopyable())
+ return true;
}
}
}
@@ -4284,7 +4302,7 @@
if (CSM != CXXDestructor) {
SpecialMemberOverloadResult *SMOR =
LookupSpecialMember(UnionFieldRecord, CSM, ConstArg, false,
- IsMove, false, false);
+ false, false, false);
// FIXME: Checking for accessibility and validity of this
// corresponding member is technically going beyond the
// standard, but this is believed to be a defect.
@@ -4333,7 +4351,7 @@
if (CSM != CXXDestructor &&
(CSM != CXXDefaultConstructor || !FI->hasInClassInitializer())) {
SpecialMemberOverloadResult *SMOR =
- LookupSpecialMember(FieldRecord, CSM, ConstArg, false, IsMove, false,
+ LookupSpecialMember(FieldRecord, CSM, ConstArg, false, false, false,
false);
if (!SMOR->hasSuccess())
return true;
@@ -4344,6 +4362,13 @@
if (CheckConstructorAccess(Loc, FieldCtor, FieldCtor->getAccess(),
PDiag()) != AR_accessible)
return true;
+
+ // For a move operation, the corresponding operation must actually
+ // be a move operation (and not a copy selected by overload
+ // resolution) unless we are working on a trivially copyable class.
+ if (IsMove && !FieldCtor->isMoveConstructor() &&
+ !FieldRecord->isTriviallyCopyable())
+ return true;
}
// We need the corresponding member of a union to be trivial so that
@@ -4497,177 +4522,6 @@
return false;
}
-bool Sema::ShouldDeleteMoveConstructor(CXXConstructorDecl *CD) {
- CXXRecordDecl *RD = CD->getParent();
- assert(!RD->isDependentType() && "do deletion after instantiation");
- if (!LangOpts.CPlusPlus0x || RD->isInvalidDecl())
- return false;
-
- SourceLocation Loc = CD->getLocation();
-
- // Do access control from the constructor
- ContextRAII CtorContext(*this, CD);
-
- bool Union = RD->isUnion();
-
- assert(!CD->getParamDecl(0)->getType()->getPointeeType().isNull() &&
- "copy assignment arg has no pointee type");
-
- // We do this because we should never actually use an anonymous
- // union's constructor.
- if (Union && RD->isAnonymousStructOrUnion())
- return false;
-
- // C++0x [class.copy]/11
- // A defaulted [move] constructor for class X is defined as deleted
- // if X has:
-
- for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(),
- BE = RD->bases_end();
- BI != BE; ++BI) {
- // We'll handle this one later
- if (BI->isVirtual())
- continue;
-
- QualType BaseType = BI->getType();
- CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl();
- assert(BaseDecl && "base isn't a CXXRecordDecl");
-
- // -- any [direct base class] of a type with a destructor that is deleted or
- // inaccessible from the defaulted constructor
- CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl);
- if (BaseDtor->isDeleted())
- return true;
- if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) !=
- AR_accessible)
- return true;
-
- // -- a [direct base class] B that cannot be [moved] because overload
- // resolution, as applied to B's [move] constructor, results in an
- // ambiguity or a function that is deleted or inaccessible from the
- // defaulted constructor
- CXXConstructorDecl *BaseCtor = LookupMovingConstructor(BaseDecl);
- if (!BaseCtor || BaseCtor->isDeleted())
- return true;
- if (CheckConstructorAccess(Loc, BaseCtor, BaseCtor->getAccess(), PDiag()) !=
- AR_accessible)
- return true;
-
- // -- for a move constructor, a [direct base class] with a type that
- // does not have a move constructor and is not trivially copyable.
- // If the field isn't a record, it's always trivially copyable.
- // A moving constructor could be a copy constructor instead.
- if (!BaseCtor->isMoveConstructor() &&
- !BaseDecl->isTriviallyCopyable())
- return true;
- }
-
- for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(),
- BE = RD->vbases_end();
- BI != BE; ++BI) {
- QualType BaseType = BI->getType();
- CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl();
- assert(BaseDecl && "base isn't a CXXRecordDecl");
-
- // -- any [virtual base class] of a type with a destructor that is deleted
- // or inaccessible from the defaulted constructor
- CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl);
- if (BaseDtor->isDeleted())
- return true;
- if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) !=
- AR_accessible)
- return true;
-
- // -- a [virtual base class] B that cannot be [moved] because overload
- // resolution, as applied to B's [move] constructor, results in an
- // ambiguity or a function that is deleted or inaccessible from the
- // defaulted constructor
- CXXConstructorDecl *BaseCtor = LookupMovingConstructor(BaseDecl);
- if (!BaseCtor || BaseCtor->isDeleted())
- return true;
- if (CheckConstructorAccess(Loc, BaseCtor, BaseCtor->getAccess(), PDiag()) !=
- AR_accessible)
- return true;
-
- // -- for a move constructor, a [virtual base class] with a type that
- // does not have a move constructor and is not trivially copyable.
- // If the field isn't a record, it's always trivially copyable.
- // A moving constructor could be a copy constructor instead.
- if (!BaseCtor->isMoveConstructor() &&
- !BaseDecl->isTriviallyCopyable())
- return true;
- }
-
- for (CXXRecordDecl::field_iterator FI = RD->field_begin(),
- FE = RD->field_end();
- FI != FE; ++FI) {
- if (FI->isUnnamedBitfield())
- continue;
-
- QualType FieldType = Context.getBaseElementType(FI->getType());
-
- if (CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl()) {
- // This is an anonymous union
- if (FieldRecord->isUnion() && FieldRecord->isAnonymousStructOrUnion()) {
- // Anonymous unions inside unions do not variant members create
- if (!Union) {
- for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(),
- UE = FieldRecord->field_end();
- UI != UE; ++UI) {
- QualType UnionFieldType = Context.getBaseElementType(UI->getType());
- CXXRecordDecl *UnionFieldRecord =
- UnionFieldType->getAsCXXRecordDecl();
-
- // -- a variant member with a non-trivial [move] constructor and X
- // is a union-like class
- if (UnionFieldRecord &&
- !UnionFieldRecord->hasTrivialMoveConstructor())
- return true;
- }
- }
-
- // Don't try to initalize an anonymous union
- continue;
- } else {
- // -- a variant member with a non-trivial [move] constructor and X is a
- // union-like class
- if (Union && !FieldRecord->hasTrivialMoveConstructor())
- return true;
-
- // -- any [non-static data member] of a type with a destructor that is
- // deleted or inaccessible from the defaulted constructor
- CXXDestructorDecl *FieldDtor = LookupDestructor(FieldRecord);
- if (FieldDtor->isDeleted())
- return true;
- if (CheckDestructorAccess(Loc, FieldDtor, PDiag()) !=
- AR_accessible)
- return true;
- }
-
- // -- a [non-static data member of class type (or array thereof)] B that
- // cannot be [moved] because overload resolution, as applied to B's
- // [move] constructor, results in an ambiguity or a function that is
- // deleted or inaccessible from the defaulted constructor
- CXXConstructorDecl *FieldCtor = LookupMovingConstructor(FieldRecord);
- if (!FieldCtor || FieldCtor->isDeleted())
- return true;
- if (CheckConstructorAccess(Loc, FieldCtor, FieldCtor->getAccess(),
- PDiag()) != AR_accessible)
- return true;
-
- // -- for a move constructor, a [non-static data member] with a type that
- // does not have a move constructor and is not trivially copyable.
- // If the field isn't a record, it's always trivially copyable.
- // A moving constructor could be a copy constructor instead.
- if (!FieldCtor->isMoveConstructor() &&
- !FieldRecord->isTriviallyCopyable())
- return true;
- }
- }
-
- return false;
-}
-
bool Sema::ShouldDeleteMoveAssignmentOperator(CXXMethodDecl *MD) {
CXXRecordDecl *RD = MD->getParent();
assert(!RD->isDependentType() && "do deletion after instantiation");
@@ -8775,7 +8629,7 @@
// constructor, one will be implicitly declared as defaulted if and only if:
// [...]
// - the move constructor would not be implicitly defined as deleted.
- if (ShouldDeleteMoveConstructor(MoveConstructor)) {
+ if (ShouldDeleteSpecialMember(MoveConstructor, CXXMoveConstructor)) {
// Cache this result so that we don't try to generate this over and over
// on every lookup, leaking memory and wasting time.
ClassDecl->setFailedImplicitMoveConstructor();
Added: cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp?rev=141650&view=auto
==============================================================================
--- cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp (added)
+++ cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp Tue Oct 11 01:43:29 2011
@@ -0,0 +1,85 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+struct NonTrivial {
+ NonTrivial(NonTrivial&&);
+};
+
+union DeletedNTVariant {
+ NonTrivial NT;
+ DeletedNTVariant(DeletedNTVariant&&);
+};
+DeletedNTVariant::DeletedNTVariant(DeletedNTVariant&&) = default; // expected-error{{would delete}}
+
+struct DeletedNTVariant2 {
+ union {
+ NonTrivial NT;
+ };
+ DeletedNTVariant2(DeletedNTVariant2&&);
+};
+DeletedNTVariant2::DeletedNTVariant2(DeletedNTVariant2&&) = default; // expected-error{{would delete}}
+
+struct NoAccess {
+ NoAccess() = default;
+private:
+ NoAccess(NoAccess&&);
+
+ friend struct HasAccess;
+};
+
+struct HasNoAccess {
+ NoAccess NA;
+ HasNoAccess(HasNoAccess&&);
+};
+HasNoAccess::HasNoAccess(HasNoAccess&&) = default; // expected-error{{would delete}}
+
+struct HasAccess {
+ NoAccess NA;
+ HasAccess(HasAccess&&);
+};
+HasAccess::HasAccess(HasAccess&&) = default;
+
+struct NoAccessDtor {
+ NoAccessDtor(NoAccessDtor&&);
+private:
+ ~NoAccessDtor();
+ friend struct HasAccessDtor;
+};
+
+struct HasNoAccessDtor {
+ NoAccessDtor NAD;
+ HasNoAccessDtor(HasNoAccessDtor&&);
+};
+HasNoAccessDtor::HasNoAccessDtor(HasNoAccessDtor&&) = default; // expected-error{{would delete}}
+
+struct HasAccessDtor {
+ NoAccessDtor NAD;
+ HasAccessDtor(HasAccessDtor&&);
+};
+HasAccessDtor::HasAccessDtor(HasAccessDtor&&) = default;
+
+struct RValue {
+ int &&ri = 1;
+ RValue(RValue&&);
+};
+RValue::RValue(RValue&&) = default;
+
+struct CopyOnly {
+ CopyOnly(const CopyOnly&);
+};
+
+struct NonMove {
+ CopyOnly CO;
+ NonMove(NonMove&&);
+};
+NonMove::NonMove(NonMove&&) = default; // expected-error{{would delete}}
+
+struct Moveable {
+ Moveable();
+ Moveable(Moveable&&);
+};
+
+struct HasMove {
+ Moveable M;
+ HasMove(HasMove&&);
+};
+HasMove::HasMove(HasMove&&) = default;
More information about the cfe-commits
mailing list