r193969 - Implement final resolution of DR1402: implicitly-declared move operators that
Richard Smith
richard at metafoo.co.uk
Sun Nov 24 16:43:40 PST 2013
Thanks for the testcase, will fix ASAP.
On Sat, Nov 23, 2013 at 3:24 PM, Argyrios Kyrtzidis <kyrtzidis at apple.com>wrote:
> Hi Richard,
>
> This commit started causing the attached reduced test case to assert,
> could you take a look ?
>
> $ clang -cc1 -std=c++11 test.cpp
> Assertion failed: ((data().DefaultedMoveConstructorIsDeleted ||
> needsOverloadResolutionForMoveConstructor()) && "move constructor should
> not be deleted"), function setImplicitMoveConstructorIsDeleted, file
> src/tools/clang/include/clang/AST/DeclCXX.h, line 874.
>
>
>
> On Nov 3, 2013, at 5:48 PM, Richard Smith <richard-llvm at metafoo.co.uk>
> wrote:
>
> > Author: rsmith
> > Date: Sun Nov 3 19:48:18 2013
> > New Revision: 193969
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=193969&view=rev
> > Log:
> > Implement final resolution of DR1402: implicitly-declared move operators
> that
> > would be deleted are still declared, but are ignored by overload
> resolution.
> >
> > Also, don't delete such members if a subobject has no corresponding move
> > operation and a non-trivial copy. This causes us to implicitly declare
> move
> > operations in more cases, but risks move-assigning virtual bases multiple
> > times in some circumstances (a warning for that is to follow).
> >
> > Modified:
> > cfe/trunk/include/clang/AST/DeclCXX.h
> > cfe/trunk/lib/AST/ASTImporter.cpp
> > cfe/trunk/lib/AST/DeclCXX.cpp
> > cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> > cfe/trunk/lib/Sema/SemaExprCXX.cpp
> > cfe/trunk/lib/Sema/SemaOverload.cpp
> > cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> > cfe/trunk/lib/Serialization/ASTWriter.cpp
> > cfe/trunk/test/CXX/class.derived/class.abstract/p16.cpp
> > cfe/trunk/test/CXX/drs/dr1xx.cpp
> > cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp
> > cfe/trunk/test/CXX/special/class.copy/p12-0x.cpp
> > cfe/trunk/test/CXX/special/class.copy/p23-cxx11.cpp
> >
> > Modified: cfe/trunk/include/clang/AST/DeclCXX.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=193969&r1=193968&r2=193969&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/AST/DeclCXX.h (original)
> > +++ cfe/trunk/include/clang/AST/DeclCXX.h Sun Nov 3 19:48:18 2013
> > @@ -444,14 +444,6 @@ class CXXRecordDecl : public RecordDecl
> > /// const-qualified reference parameter or a non-reference parameter.
> > bool HasDeclaredCopyAssignmentWithConstParam : 1;
> >
> > - /// \brief Whether an implicit move constructor was attempted to be
> declared
> > - /// but would have been deleted.
> > - bool FailedImplicitMoveConstructor : 1;
> > -
> > - /// \brief Whether an implicit move assignment operator was
> attempted to be
> > - /// declared but would have been deleted.
> > - bool FailedImplicitMoveAssignment : 1;
> > -
> > /// \brief Whether this class describes a C++ lambda.
> > bool IsLambda : 1;
> >
> > @@ -773,12 +765,14 @@ public:
> > /// \brief \c true if we know for sure that this class has a single,
> > /// accessible, unambiguous move constructor that is not deleted.
> > bool hasSimpleMoveConstructor() const {
> > - return !hasUserDeclaredMoveConstructor() && hasMoveConstructor();
> > + return !hasUserDeclaredMoveConstructor() && hasMoveConstructor() &&
> > + !data().DefaultedMoveConstructorIsDeleted;
> > }
> > /// \brief \c true if we know for sure that this class has a single,
> > /// accessible, unambiguous move assignment operator that is not
> deleted.
> > bool hasSimpleMoveAssignment() const {
> > - return !hasUserDeclaredMoveAssignment() && hasMoveAssignment();
> > + return !hasUserDeclaredMoveAssignment() && hasMoveAssignment() &&
> > + !data().DefaultedMoveAssignmentIsDeleted;
> > }
> > /// \brief \c true if we know for sure that this class has an
> accessible
> > /// destructor that is not deleted.
> > @@ -870,28 +864,23 @@ public:
> > needsImplicitMoveConstructor();
> > }
> >
> > - /// \brief Determine whether implicit move constructor generation for
> this
> > - /// class has failed before.
> > - bool hasFailedImplicitMoveConstructor() const {
> > - return data().FailedImplicitMoveConstructor;
> > - }
> > -
> > - /// \brief Set whether implicit move constructor generation for this
> class
> > - /// has failed before.
> > - void setFailedImplicitMoveConstructor(bool Failed = true) {
> > - data().FailedImplicitMoveConstructor = Failed;
> > + /// \brief Set that we attempted to declare an implicitly move
> > + /// constructor, but overload resolution failed so we deleted it.
> > + void setImplicitMoveConstructorIsDeleted() {
> > + assert((data().DefaultedMoveConstructorIsDeleted ||
> > + needsOverloadResolutionForMoveConstructor()) &&
> > + "move constructor should not be deleted");
> > + data().DefaultedMoveConstructorIsDeleted = true;
> > }
> >
> > /// \brief Determine whether this class should get an implicit move
> > /// constructor or if any existing special member function inhibits
> this.
> > bool needsImplicitMoveConstructor() const {
> > - return !hasFailedImplicitMoveConstructor() &&
> > - !(data().DeclaredSpecialMembers & SMF_MoveConstructor) &&
> > + return !(data().DeclaredSpecialMembers & SMF_MoveConstructor) &&
> > !hasUserDeclaredCopyConstructor() &&
> > !hasUserDeclaredCopyAssignment() &&
> > !hasUserDeclaredMoveAssignment() &&
> > - !hasUserDeclaredDestructor() &&
> > - !data().DefaultedMoveConstructorIsDeleted;
> > + !hasUserDeclaredDestructor();
> > }
> >
> > /// \brief Determine whether we need to eagerly declare a defaulted
> move
> > @@ -947,29 +936,24 @@ public:
> > needsImplicitMoveAssignment();
> > }
> >
> > - /// \brief Determine whether implicit move assignment generation for
> this
> > - /// class has failed before.
> > - bool hasFailedImplicitMoveAssignment() const {
> > - return data().FailedImplicitMoveAssignment;
> > - }
> > -
> > - /// \brief Set whether implicit move assignment generation for this
> class
> > - /// has failed before.
> > - void setFailedImplicitMoveAssignment(bool Failed = true) {
> > - data().FailedImplicitMoveAssignment = Failed;
> > + /// \brief Set that we attempted to declare an implicit move
> assignment
> > + /// operator, but overload resolution failed so we deleted it.
> > + void setImplicitMoveAssignmentIsDeleted() {
> > + assert((data().DefaultedMoveAssignmentIsDeleted ||
> > + needsOverloadResolutionForMoveAssignment()) &&
> > + "move assignment should not be deleted");
> > + data().DefaultedMoveAssignmentIsDeleted = true;
> > }
> >
> > /// \brief Determine whether this class should get an implicit move
> > /// assignment operator or if any existing special member function
> inhibits
> > /// this.
> > bool needsImplicitMoveAssignment() const {
> > - return !hasFailedImplicitMoveAssignment() &&
> > - !(data().DeclaredSpecialMembers & SMF_MoveAssignment) &&
> > + return !(data().DeclaredSpecialMembers & SMF_MoveAssignment) &&
> > !hasUserDeclaredCopyConstructor() &&
> > !hasUserDeclaredCopyAssignment() &&
> > !hasUserDeclaredMoveConstructor() &&
> > - !hasUserDeclaredDestructor() &&
> > - !data().DefaultedMoveAssignmentIsDeleted;
> > + !hasUserDeclaredDestructor();
> > }
> >
> > /// \brief Determine whether we need to eagerly declare a move
> assignment
> >
> > Modified: cfe/trunk/lib/AST/ASTImporter.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=193969&r1=193968&r2=193969&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/AST/ASTImporter.cpp (original)
> > +++ cfe/trunk/lib/AST/ASTImporter.cpp Sun Nov 3 19:48:18 2013
> > @@ -1983,9 +1983,6 @@ bool ASTNodeImporter::ImportDefinition(R
> > = FromData.HasDeclaredCopyConstructorWithConstParam;
> > ToData.HasDeclaredCopyAssignmentWithConstParam
> > = FromData.HasDeclaredCopyAssignmentWithConstParam;
> > - ToData.FailedImplicitMoveConstructor
> > - = FromData.FailedImplicitMoveConstructor;
> > - ToData.FailedImplicitMoveAssignment =
> FromData.FailedImplicitMoveAssignment;
> > ToData.IsLambda = FromData.IsLambda;
> >
> > SmallVector<CXXBaseSpecifier *, 4> Bases;
> >
> > Modified: cfe/trunk/lib/AST/DeclCXX.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=193969&r1=193968&r2=193969&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/AST/DeclCXX.cpp (original)
> > +++ cfe/trunk/lib/AST/DeclCXX.cpp Sun Nov 3 19:48:18 2013
> > @@ -71,7 +71,6 @@ CXXRecordDecl::DefinitionData::Definitio
> > ImplicitCopyAssignmentHasConstParam(true),
> > HasDeclaredCopyConstructorWithConstParam(false),
> > HasDeclaredCopyAssignmentWithConstParam(false),
> > - FailedImplicitMoveConstructor(false),
> FailedImplicitMoveAssignment(false),
> > IsLambda(false), NumBases(0), NumVBases(0), Bases(), VBases(),
> > Definition(D), FirstFriend() {
> > }
> >
> > Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=193969&r1=193968&r2=193969&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Nov 3 19:48:18 2013
> > @@ -9231,11 +9231,6 @@ CXXMethodDecl *Sema::DeclareImplicitCopy
> > ? SpecialMemberIsTrivial(CopyAssignment, CXXCopyAssignment)
> > : ClassDecl->hasTrivialCopyAssignment());
> >
> > - // C++11 [class.copy]p19:
> > - // .... If the class definition does not explicitly declare a copy
> > - // assignment operator, there is no user-declared move constructor,
> and
> > - // there is no user-declared move assignment operator, a copy
> assignment
> > - // operator is implicitly declared as defaulted.
> > if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment))
> > SetDeclDeleted(CopyAssignment, ClassLoc);
> >
> > @@ -9572,120 +9567,13 @@ Sema::ComputeDefaultedMoveAssignmentExce
> > return ExceptSpec;
> > }
> >
> > -/// Determine whether the class type has any direct or indirect virtual
> base
> > -/// classes which have a non-trivial move assignment operator.
> > -static bool
> > -hasVirtualBaseWithNonTrivialMoveAssignment(Sema &S, CXXRecordDecl
> *ClassDecl) {
> > - for (CXXRecordDecl::base_class_iterator Base =
> ClassDecl->vbases_begin(),
> > - BaseEnd =
> ClassDecl->vbases_end();
> > - Base != BaseEnd; ++Base) {
> > - CXXRecordDecl *BaseClass =
> > -
> cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
> > -
> > - // Try to declare the move assignment. If it would be deleted, then
> the
> > - // class does not have a non-trivial move assignment.
> > - if (BaseClass->needsImplicitMoveAssignment())
> > - S.DeclareImplicitMoveAssignment(BaseClass);
> > -
> > - if (BaseClass->hasNonTrivialMoveAssignment())
> > - return true;
> > - }
> > -
> > - return false;
> > -}
> > -
> > -/// Determine whether the given type either has a move constructor or is
> > -/// trivially copyable.
> > -static bool
> > -hasMoveOrIsTriviallyCopyable(Sema &S, QualType Type, bool
> IsConstructor) {
> > - Type = S.Context.getBaseElementType(Type);
> > -
> > - // FIXME: Technically, non-trivially-copyable non-class types, such as
> > - // reference types, are supposed to return false here, but that
> appears
> > - // to be a standard defect.
> > - CXXRecordDecl *ClassDecl = Type->getAsCXXRecordDecl();
> > - if (!ClassDecl || !ClassDecl->getDefinition() ||
> ClassDecl->isInvalidDecl())
> > - return true;
> > -
> > - if (Type.isTriviallyCopyableType(S.Context))
> > - return true;
> > -
> > - if (IsConstructor) {
> > - // FIXME: Need this because otherwise hasMoveConstructor isn't
> guaranteed to
> > - // give the right answer.
> > - if (ClassDecl->needsImplicitMoveConstructor())
> > - S.DeclareImplicitMoveConstructor(ClassDecl);
> > - return ClassDecl->hasMoveConstructor();
> > - }
> > -
> > - // FIXME: Need this because otherwise hasMoveAssignment isn't
> guaranteed to
> > - // give the right answer.
> > - if (ClassDecl->needsImplicitMoveAssignment())
> > - S.DeclareImplicitMoveAssignment(ClassDecl);
> > - return ClassDecl->hasMoveAssignment();
> > -}
> > -
> > -/// Determine whether all non-static data members and direct or virtual
> bases
> > -/// of class \p ClassDecl have either a move operation, or are trivially
> > -/// copyable.
> > -static bool subobjectsHaveMoveOrTrivialCopy(Sema &S, CXXRecordDecl
> *ClassDecl,
> > - bool IsConstructor) {
> > - for (CXXRecordDecl::base_class_iterator Base =
> ClassDecl->bases_begin(),
> > - BaseEnd =
> ClassDecl->bases_end();
> > - Base != BaseEnd; ++Base) {
> > - if (Base->isVirtual())
> > - continue;
> > -
> > - if (!hasMoveOrIsTriviallyCopyable(S, Base->getType(),
> IsConstructor))
> > - return false;
> > - }
> > -
> > - for (CXXRecordDecl::base_class_iterator Base =
> ClassDecl->vbases_begin(),
> > - BaseEnd =
> ClassDecl->vbases_end();
> > - Base != BaseEnd; ++Base) {
> > - if (!hasMoveOrIsTriviallyCopyable(S, Base->getType(),
> IsConstructor))
> > - return false;
> > - }
> > -
> > - for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
> > - FieldEnd = ClassDecl->field_end();
> > - Field != FieldEnd; ++Field) {
> > - if (!hasMoveOrIsTriviallyCopyable(S, Field->getType(),
> IsConstructor))
> > - return false;
> > - }
> > -
> > - return true;
> > -}
> > -
> > CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl
> *ClassDecl) {
> > - // C++11 [class.copy]p20:
> > - // If the definition of a class X does not explicitly declare a move
> > - // assignment operator, one will be implicitly declared as defaulted
> > - // if and only if:
> > - //
> > - // - [first 4 bullets]
> > assert(ClassDecl->needsImplicitMoveAssignment());
> >
> > DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveAssignment);
> > if (DSM.isAlreadyBeingDeclared())
> > return 0;
> >
> > - // [Checked after we build the declaration]
> > - // - the move assignment operator would not be implicitly defined as
> > - // deleted,
> > -
> > - // [DR1402]:
> > - // - X has no direct or indirect virtual base class with a
> non-trivial
> > - // move assignment operator, and
> > - // - each of X's non-static data members and direct or virtual base
> classes
> > - // has a type that either has a move assignment operator or is
> trivially
> > - // copyable.
> > - if (hasVirtualBaseWithNonTrivialMoveAssignment(*this, ClassDecl) ||
> > - !subobjectsHaveMoveOrTrivialCopy(*this,
> ClassDecl,/*Constructor*/false)) {
> > - ClassDecl->setFailedImplicitMoveAssignment();
> > - return 0;
> > - }
> > -
> > // Note: The following rules are largely analoguous to the move
> > // constructor rules.
> >
> > @@ -9729,18 +9617,9 @@ CXXMethodDecl *Sema::DeclareImplicitMove
> > ? SpecialMemberIsTrivial(MoveAssignment, CXXMoveAssignment)
> > : ClassDecl->hasTrivialMoveAssignment());
> >
> > - // C++0x [class.copy]p9:
> > - // If the definition of a class X does not explicitly declare a move
> > - // assignment operator, one will be implicitly declared as
> defaulted if and
> > - // only if:
> > - // [...]
> > - // - the move assignment operator would not be implicitly defined as
> > - // deleted.
> > if (ShouldDeleteSpecialMember(MoveAssignment, CXXMoveAssignment)) {
> > - // Cache this result so that we don't try to generate this over and
> over
> > - // on every lookup, leaking memory and wasting time.
> > - ClassDecl->setFailedImplicitMoveAssignment();
> > - return 0;
> > + ClassDecl->setImplicitMoveAssignmentIsDeleted();
> > + SetDeclDeleted(MoveAssignment, ClassLoc);
> > }
> >
> > // Note that we have added this copy-assignment operator.
> > @@ -9782,6 +9661,17 @@ void Sema::DefineImplicitMoveAssignment(
> > // are assigned, in the order in which they were declared in the
> class
> > // definition.
> >
> > + // FIXME: Issue a warning if our implicit move assignment operator
> will move
> > + // from a virtual base more than once. For instance, given:
> > + //
> > + // struct A { A &operator=(A&&); };
> > + // struct B : virtual A {};
> > + // struct C : virtual A {};
> > + // struct D : B, C {};
> > + //
> > + // If the move assignment operator of D is synthesized, we should
> warn,
> > + // because the A vbase will be moved from multiple times.
> > +
> > // The statements that form the synthesized function body.
> > SmallVector<Stmt*, 8> Statements;
> >
> > @@ -10071,11 +9961,6 @@ CXXConstructorDecl *Sema::DeclareImplici
> > ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor)
> > : ClassDecl->hasTrivialCopyConstructor());
> >
> > - // C++11 [class.copy]p8:
> > - // ... If the class definition does not explicitly declare a copy
> > - // constructor, there is no user-declared move constructor, and
> there is no
> > - // user-declared move assignment operator, a copy constructor is
> implicitly
> > - // declared as defaulted.
> > if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor))
> > SetDeclDeleted(CopyConstructor, ClassLoc);
> >
> > @@ -10195,29 +10080,12 @@ Sema::ComputeDefaultedMoveCtorExceptionS
> >
> > CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
> > CXXRecordDecl
> *ClassDecl) {
> > - // C++11 [class.copy]p9:
> > - // If the definition of a class X does not explicitly declare a move
> > - // constructor, one will be implicitly declared as defaulted if and
> only if:
> > - //
> > - // - [first 4 bullets]
> > assert(ClassDecl->needsImplicitMoveConstructor());
> >
> > DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveConstructor);
> > if (DSM.isAlreadyBeingDeclared())
> > return 0;
> >
> > - // [Checked after we build the declaration]
> > - // - the move assignment operator would not be implicitly defined as
> > - // deleted,
> > -
> > - // [DR1402]:
> > - // - each of X's non-static data members and direct or virtual base
> classes
> > - // has a type that either has a move constructor or is trivially
> copyable.
> > - if (!subobjectsHaveMoveOrTrivialCopy(*this, ClassDecl,
> /*Constructor*/true)) {
> > - ClassDecl->setFailedImplicitMoveConstructor();
> > - return 0;
> > - }
> > -
> > QualType ClassType = Context.getTypeDeclType(ClassDecl);
> > QualType ArgType = Context.getRValueReferenceType(ClassType);
> >
> > @@ -10260,16 +10128,9 @@ CXXConstructorDecl *Sema::DeclareImplici
> > ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor)
> > : ClassDecl->hasTrivialMoveConstructor());
> >
> > - // C++0x [class.copy]p9:
> > - // If the definition of a class X does not explicitly declare a move
> > - // constructor, one will be implicitly declared as defaulted if and
> only if:
> > - // [...]
> > - // - the move constructor would not be implicitly defined as
> deleted.
> > 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();
> > - return 0;
> > + ClassDecl->setImplicitMoveConstructorIsDeleted();
> > + SetDeclDeleted(MoveConstructor, ClassLoc);
> > }
> >
> > // Note that we have declared this constructor.
> >
> > Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=193969&r1=193968&r2=193969&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sun Nov 3 19:48:18 2013
> > @@ -3602,8 +3602,8 @@ static bool evaluateTypeTrait(Sema &S, T
> > // is_trivially_constructible is defined as:
> > //
> > // is_constructible<T, Args...>::value is true and the variable
> > - // definition for is_constructible, as defined below, is known
> to call no
> > - // operation that is not trivial.
> > + // definition for is_constructible, as defined below, is known
> to call
> > + // no operation that is not trivial.
> > //
> > // The predicate condition for a template specialization
> > // is_constructible<T, Args...> shall be satisfied if and only if
> the
> >
> > Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=193969&r1=193968&r2=193969&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaOverload.cpp Sun Nov 3 19:48:18 2013
> > @@ -5448,10 +5448,18 @@ Sema::AddOverloadCandidate(FunctionDecl
> > if (!CandidateSet.isNewCandidate(Function))
> > return;
> >
> > + // C++11 [class.copy]p11: [DR1402]
> > + // A defaulted move constructor that is defined as deleted is
> ignored by
> > + // overload resolution.
> > + CXXConstructorDecl *Constructor =
> dyn_cast<CXXConstructorDecl>(Function);
> > + if (Constructor && Constructor->isDefaulted() &&
> Constructor->isDeleted() &&
> > + Constructor->isMoveConstructor())
> > + return;
> > +
> > // Overload resolution is always an unevaluated context.
> > EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
> >
> > - if (CXXConstructorDecl *Constructor =
> dyn_cast<CXXConstructorDecl>(Function)){
> > + if (Constructor) {
> > // C++ [class.copy]p3:
> > // A member function template is never instantiated to perform the
> copy
> > // of a class object to an object of its class type.
> > @@ -5626,6 +5634,13 @@ Sema::AddMethodCandidate(CXXMethodDecl *
> > if (!CandidateSet.isNewCandidate(Method))
> > return;
> >
> > + // C++11 [class.copy]p23: [DR1402]
> > + // A defaulted move assignment operator that is defined as deleted
> is
> > + // ignored by overload resolution.
> > + if (Method->isDefaulted() && Method->isDeleted() &&
> > + Method->isMoveAssignmentOperator())
> > + return;
> > +
> > // Overload resolution is always an unevaluated context.
> > EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
> >
> >
> > Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=193969&r1=193968&r2=193969&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
> > +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Sun Nov 3 19:48:18
> 2013
> > @@ -1208,8 +1208,6 @@ void ASTDeclReader::ReadCXXDefinitionDat
> > Data.ImplicitCopyAssignmentHasConstParam = Record[Idx++];
> > Data.HasDeclaredCopyConstructorWithConstParam = Record[Idx++];
> > Data.HasDeclaredCopyAssignmentWithConstParam = Record[Idx++];
> > - Data.FailedImplicitMoveConstructor = Record[Idx++];
> > - Data.FailedImplicitMoveAssignment = Record[Idx++];
> >
> > Data.NumBases = Record[Idx++];
> > if (Data.NumBases)
> >
> > Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=193969&r1=193968&r2=193969&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
> > +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Sun Nov 3 19:48:18 2013
> > @@ -5106,8 +5106,6 @@ void ASTWriter::AddCXXDefinitionData(con
> > Record.push_back(Data.ImplicitCopyAssignmentHasConstParam);
> > Record.push_back(Data.HasDeclaredCopyConstructorWithConstParam);
> > Record.push_back(Data.HasDeclaredCopyAssignmentWithConstParam);
> > - Record.push_back(Data.FailedImplicitMoveConstructor);
> > - Record.push_back(Data.FailedImplicitMoveAssignment);
> > // IsLambda bit is already saved.
> >
> > Record.push_back(Data.NumBases);
> >
> > Modified: cfe/trunk/test/CXX/class.derived/class.abstract/p16.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.derived/class.abstract/p16.cpp?rev=193969&r1=193968&r2=193969&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CXX/class.derived/class.abstract/p16.cpp (original)
> > +++ cfe/trunk/test/CXX/class.derived/class.abstract/p16.cpp Sun Nov 3
> 19:48:18 2013
> > @@ -22,7 +22,7 @@ struct H;
> > struct D {
> > virtual E &operator=(const E &); // expected-note {{here}}
> > virtual F &operator=(const F &);
> > - virtual G &operator=(G&&);
> > + virtual G &operator=(G&&); // expected-note {{here}}
> > virtual H &operator=(H&&); // expected-note {{here}}
> > friend struct F;
> >
> > @@ -34,8 +34,8 @@ private:
> > struct E : D {}; // expected-error {{deleted function '~E' cannot
> override a non-deleted function}} \
> > // expected-error {{deleted function 'operator=' cannot
> override a non-deleted function}}
> > struct F : D {};
> > -// No move ctor here, because it would be deleted.
> > struct G : D {}; // expected-error {{deleted function '~G' cannot
> override a non-deleted function}}
> > + // expected-error at -1 {{deleted function 'operator='
> cannot override a non-deleted function}}
> > struct H : D {
> > H &operator=(H&&) = default; // expected-error {{deleted function
> 'operator=' cannot override a non-deleted function}}
> > ~H();
> >
> > Modified: cfe/trunk/test/CXX/drs/dr1xx.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr1xx.cpp?rev=193969&r1=193968&r2=193969&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CXX/drs/dr1xx.cpp (original)
> > +++ cfe/trunk/test/CXX/drs/dr1xx.cpp Sun Nov 3 19:48:18 2013
> > @@ -71,7 +71,7 @@ namespace dr109 { // dr109: yes
> >
> > namespace dr111 { // dr111: dup 535
> > struct A { A(); A(volatile A&, int = 0); A(A&, const char * = "foo");
> };
> > - struct B : A { B(); }; // expected-note {{would lose const
> qualifier}} expected-note {{requires 0 arguments}}
> > + struct B : A { B(); }; // expected-note +{{would lose const
> qualifier}} expected-note {{requires 0 arguments}}
> > const B b1;
> > B b2(b1); // expected-error {{no matching constructor}}
> > }
> >
> > Modified: cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp?rev=193969&r1=193968&r2=193969&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp (original)
> > +++ cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp Sun Nov 3
> 19:48:18 2013
> > @@ -190,49 +190,59 @@ namespace DR1402 {
> > NonTrivialMoveAssignVBase &operator=(NonTrivialMoveAssignVBase &&) =
> default;
> > };
> >
> > - // A non-movable, non-trivially-copyable class type as a subobject
> inhibits
> > - // the declaration of a move operation.
> > - struct NoMove1 { NonTrivialCopyCtor ntcc; }; // expected-note
> 2{{'const DR1402::NoMove1 &'}}
> > - struct NoMove2 { NonTrivialCopyAssign ntcc; }; // expected-note
> 2{{'const DR1402::NoMove2 &'}}
> > - struct NoMove3 : NonTrivialCopyCtor {}; // expected-note 2{{'const
> DR1402::NoMove3 &'}}
> > - struct NoMove4 : NonTrivialCopyAssign {}; // expected-note 2{{'const
> DR1402::NoMove4 &'}}
> > - struct NoMove5 : virtual NonTrivialCopyCtor {}; // expected-note
> 2{{'const DR1402::NoMove5 &'}}
> > - struct NoMove6 : virtual NonTrivialCopyAssign {}; // expected-note
> 2{{'const DR1402::NoMove6 &'}}
> > - struct NoMove7 : NonTrivialCopyCtorVBase {}; // expected-note
> 2{{'const DR1402::NoMove7 &'}}
> > - struct NoMove8 : NonTrivialCopyAssignVBase {}; // expected-note
> 2{{'const DR1402::NoMove8 &'}}
> > + // DR1402: A non-movable, non-trivially-copyable class type as a
> subobject no
> > + // longer inhibits the declaration of a move operation.
> > + struct NoMove1 { NonTrivialCopyCtor ntcc; };
> > + struct NoMove2 { NonTrivialCopyAssign ntcc; };
> > + struct NoMove3 : NonTrivialCopyCtor {};
> > + struct NoMove4 : NonTrivialCopyAssign {};
> > + struct NoMove5 : virtual NonTrivialCopyCtor {};
> > + struct NoMove6 : virtual NonTrivialCopyAssign {};
> > + struct NoMove7 : NonTrivialCopyCtorVBase {};
> > + struct NoMove8 : NonTrivialCopyAssignVBase {};
> >
> > - // A non-trivially-move-assignable virtual base class inhibits the
> declaration
> > - // of a move assignment (which might move-assign the base class
> multiple
> > - // times).
> > + // DR1402: A non-trivially-move-assignable virtual base class no
> longer
> > + // inhibits the declaration of a move assignment (even though it might
> > + // move-assign the base class multiple times).
> > struct NoMove9 : NonTrivialMoveAssign {};
> > - struct NoMove10 : virtual NonTrivialMoveAssign {}; // expected-note
> {{'const DR1402::NoMove10 &'}}
> > - struct NoMove11 : NonTrivialMoveAssignVBase {}; // expected-note
> {{'const DR1402::NoMove11 &'}}
> > + struct NoMove10 : virtual NonTrivialMoveAssign {};
> > + struct NoMove11 : NonTrivialMoveAssignVBase {};
> >
> > - struct Test {
> > - friend NoMove1::NoMove1(NoMove1 &&); // expected-error {{does not
> match}}
> > - friend NoMove2::NoMove2(NoMove2 &&); // expected-error {{does not
> match}}
> > - friend NoMove3::NoMove3(NoMove3 &&); // expected-error {{does not
> match}}
> > - friend NoMove4::NoMove4(NoMove4 &&); // expected-error {{does not
> match}}
> > - friend NoMove5::NoMove5(NoMove5 &&); // expected-error {{does not
> match}}
> > - friend NoMove6::NoMove6(NoMove6 &&); // expected-error {{does not
> match}}
> > - friend NoMove7::NoMove7(NoMove7 &&); // expected-error {{does not
> match}}
> > - friend NoMove8::NoMove8(NoMove8 &&); // expected-error {{does not
> match}}
> > - friend NoMove9::NoMove9(NoMove9 &&);
> > - friend NoMove10::NoMove10(NoMove10 &&);
> > - friend NoMove11::NoMove11(NoMove11 &&);
> > + template<typename T> void test(T t) {
> > + (void)T(static_cast<T&&>(t)); // ok
> > + t = static_cast<T&&>(t); // ok
> > + }
> > + template void test(NoMove1);
> > + template void test(NoMove2);
> > + template void test(NoMove3);
> > + template void test(NoMove4);
> > + template void test(NoMove5);
> > + template void test(NoMove6);
> > + template void test(NoMove7);
> > + template void test(NoMove8);
> > + template void test(NoMove9);
> > + template void test(NoMove10);
> > + template void test(NoMove11);
> >
> > - friend NoMove1 &NoMove1::operator=(NoMove1 &&); // expected-error
> {{does not match}}
> > - friend NoMove2 &NoMove2::operator=(NoMove2 &&); // expected-error
> {{does not match}}
> > - friend NoMove3 &NoMove3::operator=(NoMove3 &&); // expected-error
> {{does not match}}
> > - friend NoMove4 &NoMove4::operator=(NoMove4 &&); // expected-error
> {{does not match}}
> > - friend NoMove5 &NoMove5::operator=(NoMove5 &&); // expected-error
> {{does not match}}
> > - friend NoMove6 &NoMove6::operator=(NoMove6 &&); // expected-error
> {{does not match}}
> > - friend NoMove7 &NoMove7::operator=(NoMove7 &&); // expected-error
> {{does not match}}
> > - friend NoMove8 &NoMove8::operator=(NoMove8 &&); // expected-error
> {{does not match}}
> > - friend NoMove9 &NoMove9::operator=(NoMove9 &&);
> > - friend NoMove10 &NoMove10::operator=(NoMove10 &&); //
> expected-error {{does not match}}
> > - friend NoMove11 &NoMove11::operator=(NoMove11 &&); //
> expected-error {{does not match}}
> > + struct CopyOnly {
> > + CopyOnly(const CopyOnly&);
> > + CopyOnly &operator=(const CopyOnly&);
> > };
> > + struct MoveOnly {
> > + MoveOnly(MoveOnly&&); // expected-note {{user-declared move}}
> > + MoveOnly &operator=(MoveOnly&&);
> > + };
> > + template void test(CopyOnly); // ok, copies
> > + template void test(MoveOnly); // ok, moves
> > + struct CopyAndMove { // expected-note {{implicitly deleted}}
> > + CopyOnly co;
> > + MoveOnly mo; // expected-note {{deleted copy}}
> > + };
> > + template void test(CopyAndMove); // ok, copies co, moves mo
> > + void test2(CopyAndMove cm) {
> > + (void)CopyAndMove(cm); // expected-error {{deleted}}
> > + cm = cm; // expected-error {{deleted}}
> > + }
> > }
> >
> > namespace PR12625 {
> >
> > Modified: cfe/trunk/test/CXX/special/class.copy/p12-0x.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/p12-0x.cpp?rev=193969&r1=193968&r2=193969&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CXX/special/class.copy/p12-0x.cpp (original)
> > +++ cfe/trunk/test/CXX/special/class.copy/p12-0x.cpp Sun Nov 3 19:48:18
> 2013
> > @@ -157,8 +157,8 @@ namespace TrivialityDependsOnImplicitDel
> >
> > struct NoAccess {
> > PrivateMove pm;
> > - // NoAccess's move would be deleted, so is suppressed,
> > - // so moves of it use PrivateMove's copy ctor, which is trivial.
> > + // NoAccess's move is deleted, so moves of it use PrivateMove's
> copy ctor,
> > + // which is trivial.
> > };
> > static_assert(__is_trivially_constructible(NoAccess, const NoAccess
> &), "");
> > static_assert(__is_trivially_constructible(NoAccess, NoAccess &&), "");
> >
> > Modified: cfe/trunk/test/CXX/special/class.copy/p23-cxx11.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/p23-cxx11.cpp?rev=193969&r1=193968&r2=193969&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CXX/special/class.copy/p23-cxx11.cpp (original)
> > +++ cfe/trunk/test/CXX/special/class.copy/p23-cxx11.cpp Sun Nov 3
> 19:48:18 2013
> > @@ -9,7 +9,15 @@ template<typename T> struct CopyAssign {
> > template<typename T> struct MoveAssign {
> > static T t;
> > void test() {
> > - t = static_cast<T&&>(t); // expected-error +{{deleted}}
> > + // Overload resolution will ignore a defaulted, deleted move
> assignment,
> > + // so check for it in a different way.
> > + T &(T::*f)(T&&) = &T::operator=; // expected-error +{{deleted}}
> > + }
> > +};
> > +template<typename T> struct MoveOrCopyAssign {
> > + static T t;
> > + void test() {
> > + t = static_cast<T&&>(t); // expected-error +{{copy assignment
> operator is implicitly deleted}}
> > }
> > };
> >
> > @@ -89,29 +97,32 @@ struct D1 {
> > AmbiguousCopyAssign a; // expected-note {{field 'a' has multiple copy}}
> > };
> > struct D2 {
> > - D2 &operator=(D2 &&) = default; // expected-note {{here}}
> > + D2 &operator=(D2 &&) = default; // expected-note {{here}}
> expected-note {{copy assignment operator is implicitly deleted}}
> > AmbiguousMoveAssign a; // expected-note {{field 'a' has multiple move}}
> > };
> > struct D3 {
> > DeletedCopyAssign a; // expected-note {{field 'a' has a deleted copy}}
> > };
> > struct D4 {
> > - D4 &operator=(D4 &&) = default; // expected-note {{here}}
> > + D4 &operator=(D4 &&) = default; // expected-note {{here}}
> expected-note {{copy assignment operator is implicitly deleted}}
> > DeletedMoveAssign a; // expected-note {{field 'a' has a deleted move}}
> > };
> > struct D5 {
> > InaccessibleCopyAssign a; // expected-note {{field 'a' has an
> inaccessible copy}}
> > };
> > struct D6 {
> > - D6 &operator=(D6 &&) = default; // expected-note {{here}}
> > + D6 &operator=(D6 &&) = default; // expected-note {{here}}
> expected-note {{copy assignment operator is implicitly deleted}}
> > InaccessibleMoveAssign a; // expected-note {{field 'a' has an
> inaccessible move}}
> > };
> > template struct CopyAssign<D1>; // expected-note {{here}}
> > template struct MoveAssign<D2>; // expected-note {{here}}
> > +template struct MoveOrCopyAssign<D2>; // expected-note {{here}}
> > template struct CopyAssign<D3>; // expected-note {{here}}
> > template struct MoveAssign<D4>; // expected-note {{here}}
> > +template struct MoveOrCopyAssign<D4>; // expected-note {{here}}
> > template struct CopyAssign<D5>; // expected-note {{here}}
> > template struct MoveAssign<D6>; // expected-note {{here}}
> > +template struct MoveOrCopyAssign<D6>; // expected-note {{here}}
> >
> > // -- a direct or virtual base that cannot be copied/moved
> > struct E1 : AmbiguousCopyAssign {}; // expected-note {{base class
> 'AmbiguousCopyAssign' has multiple copy}}
> >
> >
> > _______________________________________________
> > cfe-commits mailing list
> > cfe-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131124/70bb3c10/attachment.html>
More information about the cfe-commits
mailing list