<html><head><meta http-equiv="Content-Type" content="text/html charset=iso-8859-1"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">Thank you!<div><br><div><div>On Nov 24, 2013, at 11:13 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk">richard@metafoo.co.uk</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div dir="ltr"><pre style="">Fixed in r195620.</pre></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Sun, Nov 24, 2013 at 4:43 PM, Richard Smith <span dir="ltr"><<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Thanks for the testcase, will fix ASAP.</div><div class="gmail_extra"><br><br><div class="gmail_quote"><div>
<div class="h5">On Sat, Nov 23, 2013 at 3:24 PM, Argyrios Kyrtzidis <span dir="ltr"><<a href="mailto:kyrtzidis@apple.com" target="_blank">kyrtzidis@apple.com</a>></span> wrote:<br>
</div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5">Hi Richard,<br>
<br>
This commit started causing the attached reduced test case to assert, could you take a look ?<br>
<br>
$ clang -cc1 -std=c++11 test.cpp<br>
Assertion failed: ((data().DefaultedMoveConstructorIsDeleted || needsOverloadResolutionForMoveConstructor()) && "move constructor should not be deleted"), function setImplicitMoveConstructorIsDeleted, file src/tools/clang/include/clang/AST/DeclCXX.h, line 874.<br>


<br>
<br><br></div></div><div><div class="h5">
On Nov 3, 2013, at 5:48 PM, Richard Smith <<a href="mailto:richard-llvm@metafoo.co.uk" target="_blank">richard-llvm@metafoo.co.uk</a>> wrote:<br>
<br>
> Author: rsmith<br>
> Date: Sun Nov  3 19:48:18 2013<br>
> New Revision: 193969<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=193969&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=193969&view=rev</a><br>
> Log:<br>
> Implement final resolution of DR1402: implicitly-declared move operators that<br>
> would be deleted are still declared, but are ignored by overload resolution.<br>
><br>
> Also, don't delete such members if a subobject has no corresponding move<br>
> operation and a non-trivial copy. This causes us to implicitly declare move<br>
> operations in more cases, but risks move-assigning virtual bases multiple<br>
> times in some circumstances (a warning for that is to follow).<br>
><br>
> Modified:<br>
>    cfe/trunk/include/clang/AST/DeclCXX.h<br>
>    cfe/trunk/lib/AST/ASTImporter.cpp<br>
>    cfe/trunk/lib/AST/DeclCXX.cpp<br>
>    cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
>    cfe/trunk/lib/Sema/SemaExprCXX.cpp<br>
>    cfe/trunk/lib/Sema/SemaOverload.cpp<br>
>    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp<br>
>    cfe/trunk/lib/Serialization/ASTWriter.cpp<br>
>    cfe/trunk/test/CXX/class.derived/class.abstract/p16.cpp<br>
>    cfe/trunk/test/CXX/drs/dr1xx.cpp<br>
>    cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp<br>
>    cfe/trunk/test/CXX/special/class.copy/p12-0x.cpp<br>
>    cfe/trunk/test/CXX/special/class.copy/p23-cxx11.cpp<br>
><br>
> Modified: cfe/trunk/include/clang/AST/DeclCXX.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=193969&r1=193968&r2=193969&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=193969&r1=193968&r2=193969&view=diff</a><br>


> ==============================================================================<br>
> --- cfe/trunk/include/clang/AST/DeclCXX.h (original)<br>
> +++ cfe/trunk/include/clang/AST/DeclCXX.h Sun Nov  3 19:48:18 2013<br>
> @@ -444,14 +444,6 @@ class CXXRecordDecl : public RecordDecl<br>
>     /// const-qualified reference parameter or a non-reference parameter.<br>
>     bool HasDeclaredCopyAssignmentWithConstParam : 1;<br>
><br>
> -    /// \brief Whether an implicit move constructor was attempted to be declared<br>
> -    /// but would have been deleted.<br>
> -    bool FailedImplicitMoveConstructor : 1;<br>
> -<br>
> -    /// \brief Whether an implicit move assignment operator was attempted to be<br>
> -    /// declared but would have been deleted.<br>
> -    bool FailedImplicitMoveAssignment : 1;<br>
> -<br>
>     /// \brief Whether this class describes a C++ lambda.<br>
>     bool IsLambda : 1;<br>
><br>
> @@ -773,12 +765,14 @@ public:<br>
>   /// \brief \c true if we know for sure that this class has a single,<br>
>   /// accessible, unambiguous move constructor that is not deleted.<br>
>   bool hasSimpleMoveConstructor() const {<br>
> -    return !hasUserDeclaredMoveConstructor() && hasMoveConstructor();<br>
> +    return !hasUserDeclaredMoveConstructor() && hasMoveConstructor() &&<br>
> +           !data().DefaultedMoveConstructorIsDeleted;<br>
>   }<br>
>   /// \brief \c true if we know for sure that this class has a single,<br>
>   /// accessible, unambiguous move assignment operator that is not deleted.<br>
>   bool hasSimpleMoveAssignment() const {<br>
> -    return !hasUserDeclaredMoveAssignment() && hasMoveAssignment();<br>
> +    return !hasUserDeclaredMoveAssignment() && hasMoveAssignment() &&<br>
> +           !data().DefaultedMoveAssignmentIsDeleted;<br>
>   }<br>
>   /// \brief \c true if we know for sure that this class has an accessible<br>
>   /// destructor that is not deleted.<br>
> @@ -870,28 +864,23 @@ public:<br>
>            needsImplicitMoveConstructor();<br>
>   }<br>
><br>
> -  /// \brief Determine whether implicit move constructor generation for this<br>
> -  /// class has failed before.<br>
> -  bool hasFailedImplicitMoveConstructor() const {<br>
> -    return data().FailedImplicitMoveConstructor;<br>
> -  }<br>
> -<br>
> -  /// \brief Set whether implicit move constructor generation for this class<br>
> -  /// has failed before.<br>
> -  void setFailedImplicitMoveConstructor(bool Failed = true) {<br>
> -    data().FailedImplicitMoveConstructor = Failed;<br>
> +  /// \brief Set that we attempted to declare an implicitly move<br>
> +  /// constructor, but overload resolution failed so we deleted it.<br>
> +  void setImplicitMoveConstructorIsDeleted() {<br>
> +    assert((data().DefaultedMoveConstructorIsDeleted ||<br>
> +            needsOverloadResolutionForMoveConstructor()) &&<br>
> +           "move constructor should not be deleted");<br>
> +    data().DefaultedMoveConstructorIsDeleted = true;<br>
>   }<br>
><br>
>   /// \brief Determine whether this class should get an implicit move<br>
>   /// constructor or if any existing special member function inhibits this.<br>
>   bool needsImplicitMoveConstructor() const {<br>
> -    return !hasFailedImplicitMoveConstructor() &&<br>
> -           !(data().DeclaredSpecialMembers & SMF_MoveConstructor) &&<br>
> +    return !(data().DeclaredSpecialMembers & SMF_MoveConstructor) &&<br>
>            !hasUserDeclaredCopyConstructor() &&<br>
>            !hasUserDeclaredCopyAssignment() &&<br>
>            !hasUserDeclaredMoveAssignment() &&<br>
> -           !hasUserDeclaredDestructor() &&<br>
> -           !data().DefaultedMoveConstructorIsDeleted;<br>
> +           !hasUserDeclaredDestructor();<br>
>   }<br>
><br>
>   /// \brief Determine whether we need to eagerly declare a defaulted move<br>
> @@ -947,29 +936,24 @@ public:<br>
>            needsImplicitMoveAssignment();<br>
>   }<br>
><br>
> -  /// \brief Determine whether implicit move assignment generation for this<br>
> -  /// class has failed before.<br>
> -  bool hasFailedImplicitMoveAssignment() const {<br>
> -    return data().FailedImplicitMoveAssignment;<br>
> -  }<br>
> -<br>
> -  /// \brief Set whether implicit move assignment generation for this class<br>
> -  /// has failed before.<br>
> -  void setFailedImplicitMoveAssignment(bool Failed = true) {<br>
> -    data().FailedImplicitMoveAssignment = Failed;<br>
> +  /// \brief Set that we attempted to declare an implicit move assignment<br>
> +  /// operator, but overload resolution failed so we deleted it.<br>
> +  void setImplicitMoveAssignmentIsDeleted() {<br>
> +    assert((data().DefaultedMoveAssignmentIsDeleted ||<br>
> +            needsOverloadResolutionForMoveAssignment()) &&<br>
> +           "move assignment should not be deleted");<br>
> +    data().DefaultedMoveAssignmentIsDeleted = true;<br>
>   }<br>
><br>
>   /// \brief Determine whether this class should get an implicit move<br>
>   /// assignment operator or if any existing special member function inhibits<br>
>   /// this.<br>
>   bool needsImplicitMoveAssignment() const {<br>
> -    return !hasFailedImplicitMoveAssignment() &&<br>
> -           !(data().DeclaredSpecialMembers & SMF_MoveAssignment) &&<br>
> +    return !(data().DeclaredSpecialMembers & SMF_MoveAssignment) &&<br>
>            !hasUserDeclaredCopyConstructor() &&<br>
>            !hasUserDeclaredCopyAssignment() &&<br>
>            !hasUserDeclaredMoveConstructor() &&<br>
> -           !hasUserDeclaredDestructor() &&<br>
> -           !data().DefaultedMoveAssignmentIsDeleted;<br>
> +           !hasUserDeclaredDestructor();<br>
>   }<br>
><br>
>   /// \brief Determine whether we need to eagerly declare a move assignment<br>
><br>
> Modified: cfe/trunk/lib/AST/ASTImporter.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=193969&r1=193968&r2=193969&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=193969&r1=193968&r2=193969&view=diff</a><br>


> ==============================================================================<br>
> --- cfe/trunk/lib/AST/ASTImporter.cpp (original)<br>
> +++ cfe/trunk/lib/AST/ASTImporter.cpp Sun Nov  3 19:48:18 2013<br>
> @@ -1983,9 +1983,6 @@ bool ASTNodeImporter::ImportDefinition(R<br>
>       = FromData.HasDeclaredCopyConstructorWithConstParam;<br>
>     ToData.HasDeclaredCopyAssignmentWithConstParam<br>
>       = FromData.HasDeclaredCopyAssignmentWithConstParam;<br>
> -    ToData.FailedImplicitMoveConstructor<br>
> -      = FromData.FailedImplicitMoveConstructor;<br>
> -    ToData.FailedImplicitMoveAssignment = FromData.FailedImplicitMoveAssignment;<br>
>     ToData.IsLambda = FromData.IsLambda;<br>
><br>
>     SmallVector<CXXBaseSpecifier *, 4> Bases;<br>
><br>
> Modified: cfe/trunk/lib/AST/DeclCXX.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=193969&r1=193968&r2=193969&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=193969&r1=193968&r2=193969&view=diff</a><br>


> ==============================================================================<br>
> --- cfe/trunk/lib/AST/DeclCXX.cpp (original)<br>
> +++ cfe/trunk/lib/AST/DeclCXX.cpp Sun Nov  3 19:48:18 2013<br>
> @@ -71,7 +71,6 @@ CXXRecordDecl::DefinitionData::Definitio<br>
>     ImplicitCopyAssignmentHasConstParam(true),<br>
>     HasDeclaredCopyConstructorWithConstParam(false),<br>
>     HasDeclaredCopyAssignmentWithConstParam(false),<br>
> -    FailedImplicitMoveConstructor(false), FailedImplicitMoveAssignment(false),<br>
>     IsLambda(false), NumBases(0), NumVBases(0), Bases(), VBases(),<br>
>     Definition(D), FirstFriend() {<br>
> }<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=193969&r1=193968&r2=193969&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=193969&r1=193968&r2=193969&view=diff</a><br>


> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Nov  3 19:48:18 2013<br>
> @@ -9231,11 +9231,6 @@ CXXMethodDecl *Sema::DeclareImplicitCopy<br>
>       ? SpecialMemberIsTrivial(CopyAssignment, CXXCopyAssignment)<br>
>       : ClassDecl->hasTrivialCopyAssignment());<br>
><br>
> -  // C++11 [class.copy]p19:<br>
> -  //   ....  If the class definition does not explicitly declare a copy<br>
> -  //   assignment operator, there is no user-declared move constructor, and<br>
> -  //   there is no user-declared move assignment operator, a copy assignment<br>
> -  //   operator is implicitly declared as defaulted.<br>
>   if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment))<br>
>     SetDeclDeleted(CopyAssignment, ClassLoc);<br>
><br>
> @@ -9572,120 +9567,13 @@ Sema::ComputeDefaultedMoveAssignmentExce<br>
>   return ExceptSpec;<br>
> }<br>
><br>
> -/// Determine whether the class type has any direct or indirect virtual base<br>
> -/// classes which have a non-trivial move assignment operator.<br>
> -static bool<br>
> -hasVirtualBaseWithNonTrivialMoveAssignment(Sema &S, CXXRecordDecl *ClassDecl) {<br>
> -  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),<br>
> -                                          BaseEnd = ClassDecl->vbases_end();<br>
> -       Base != BaseEnd; ++Base) {<br>
> -    CXXRecordDecl *BaseClass =<br>
> -        cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());<br>
> -<br>
> -    // Try to declare the move assignment. If it would be deleted, then the<br>
> -    // class does not have a non-trivial move assignment.<br>
> -    if (BaseClass->needsImplicitMoveAssignment())<br>
> -      S.DeclareImplicitMoveAssignment(BaseClass);<br>
> -<br>
> -    if (BaseClass->hasNonTrivialMoveAssignment())<br>
> -      return true;<br>
> -  }<br>
> -<br>
> -  return false;<br>
> -}<br>
> -<br>
> -/// Determine whether the given type either has a move constructor or is<br>
> -/// trivially copyable.<br>
> -static bool<br>
> -hasMoveOrIsTriviallyCopyable(Sema &S, QualType Type, bool IsConstructor) {<br>
> -  Type = S.Context.getBaseElementType(Type);<br>
> -<br>
> -  // FIXME: Technically, non-trivially-copyable non-class types, such as<br>
> -  // reference types, are supposed to return false here, but that appears<br>
> -  // to be a standard defect.<br>
> -  CXXRecordDecl *ClassDecl = Type->getAsCXXRecordDecl();<br>
> -  if (!ClassDecl || !ClassDecl->getDefinition() || ClassDecl->isInvalidDecl())<br>
> -    return true;<br>
> -<br>
> -  if (Type.isTriviallyCopyableType(S.Context))<br>
> -    return true;<br>
> -<br>
> -  if (IsConstructor) {<br>
> -    // FIXME: Need this because otherwise hasMoveConstructor isn't guaranteed to<br>
> -    // give the right answer.<br>
> -    if (ClassDecl->needsImplicitMoveConstructor())<br>
> -      S.DeclareImplicitMoveConstructor(ClassDecl);<br>
> -    return ClassDecl->hasMoveConstructor();<br>
> -  }<br>
> -<br>
> -  // FIXME: Need this because otherwise hasMoveAssignment isn't guaranteed to<br>
> -  // give the right answer.<br>
> -  if (ClassDecl->needsImplicitMoveAssignment())<br>
> -    S.DeclareImplicitMoveAssignment(ClassDecl);<br>
> -  return ClassDecl->hasMoveAssignment();<br>
> -}<br>
> -<br>
> -/// Determine whether all non-static data members and direct or virtual bases<br>
> -/// of class \p ClassDecl have either a move operation, or are trivially<br>
> -/// copyable.<br>
> -static bool subobjectsHaveMoveOrTrivialCopy(Sema &S, CXXRecordDecl *ClassDecl,<br>
> -                                            bool IsConstructor) {<br>
> -  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),<br>
> -                                          BaseEnd = ClassDecl->bases_end();<br>
> -       Base != BaseEnd; ++Base) {<br>
> -    if (Base->isVirtual())<br>
> -      continue;<br>
> -<br>
> -    if (!hasMoveOrIsTriviallyCopyable(S, Base->getType(), IsConstructor))<br>
> -      return false;<br>
> -  }<br>
> -<br>
> -  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),<br>
> -                                          BaseEnd = ClassDecl->vbases_end();<br>
> -       Base != BaseEnd; ++Base) {<br>
> -    if (!hasMoveOrIsTriviallyCopyable(S, Base->getType(), IsConstructor))<br>
> -      return false;<br>
> -  }<br>
> -<br>
> -  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),<br>
> -                                     FieldEnd = ClassDecl->field_end();<br>
> -       Field != FieldEnd; ++Field) {<br>
> -    if (!hasMoveOrIsTriviallyCopyable(S, Field->getType(), IsConstructor))<br>
> -      return false;<br>
> -  }<br>
> -<br>
> -  return true;<br>
> -}<br>
> -<br>
> CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {<br>
> -  // C++11 [class.copy]p20:<br>
> -  //   If the definition of a class X does not explicitly declare a move<br>
> -  //   assignment operator, one will be implicitly declared as defaulted<br>
> -  //   if and only if:<br>
> -  //<br>
> -  //   - [first 4 bullets]<br>
>   assert(ClassDecl->needsImplicitMoveAssignment());<br>
><br>
>   DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveAssignment);<br>
>   if (DSM.isAlreadyBeingDeclared())<br>
>     return 0;<br>
><br>
> -  // [Checked after we build the declaration]<br>
> -  //   - the move assignment operator would not be implicitly defined as<br>
> -  //     deleted,<br>
> -<br>
> -  // [DR1402]:<br>
> -  //   - X has no direct or indirect virtual base class with a non-trivial<br>
> -  //     move assignment operator, and<br>
> -  //   - each of X's non-static data members and direct or virtual base classes<br>
> -  //     has a type that either has a move assignment operator or is trivially<br>
> -  //     copyable.<br>
> -  if (hasVirtualBaseWithNonTrivialMoveAssignment(*this, ClassDecl) ||<br>
> -      !subobjectsHaveMoveOrTrivialCopy(*this, ClassDecl,/*Constructor*/false)) {<br>
> -    ClassDecl->setFailedImplicitMoveAssignment();<br>
> -    return 0;<br>
> -  }<br>
> -<br>
>   // Note: The following rules are largely analoguous to the move<br>
>   // constructor rules.<br>
><br>
> @@ -9729,18 +9617,9 @@ CXXMethodDecl *Sema::DeclareImplicitMove<br>
>       ? SpecialMemberIsTrivial(MoveAssignment, CXXMoveAssignment)<br>
>       : ClassDecl->hasTrivialMoveAssignment());<br>
><br>
> -  // C++0x [class.copy]p9:<br>
> -  //   If the definition of a class X does not explicitly declare a move<br>
> -  //   assignment operator, one will be implicitly declared as defaulted if and<br>
> -  //   only if:<br>
> -  //   [...]<br>
> -  //   - the move assignment operator would not be implicitly defined as<br>
> -  //     deleted.<br>
>   if (ShouldDeleteSpecialMember(MoveAssignment, CXXMoveAssignment)) {<br>
> -    // Cache this result so that we don't try to generate this over and over<br>
> -    // on every lookup, leaking memory and wasting time.<br>
> -    ClassDecl->setFailedImplicitMoveAssignment();<br>
> -    return 0;<br>
> +    ClassDecl->setImplicitMoveAssignmentIsDeleted();<br>
> +    SetDeclDeleted(MoveAssignment, ClassLoc);<br>
>   }<br>
><br>
>   // Note that we have added this copy-assignment operator.<br>
> @@ -9782,6 +9661,17 @@ void Sema::DefineImplicitMoveAssignment(<br>
>   //   are assigned, in the order in which they were declared in the class<br>
>   //   definition.<br>
><br>
> +  // FIXME: Issue a warning if our implicit move assignment operator will move<br>
> +  // from a virtual base more than once. For instance, given:<br>
> +  //<br>
> +  //   struct A { A &operator=(A&&); };<br>
> +  //   struct B : virtual A {};<br>
> +  //   struct C : virtual A {};<br>
> +  //   struct D : B, C {};<br>
> +  //<br>
> +  // If the move assignment operator of D is synthesized, we should warn,<br>
> +  // because the A vbase will be moved from multiple times.<br>
> +<br>
>   // The statements that form the synthesized function body.<br>
>   SmallVector<Stmt*, 8> Statements;<br>
><br>
> @@ -10071,11 +9961,6 @@ CXXConstructorDecl *Sema::DeclareImplici<br>
>       ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor)<br>
>       : ClassDecl->hasTrivialCopyConstructor());<br>
><br>
> -  // C++11 [class.copy]p8:<br>
> -  //   ... If the class definition does not explicitly declare a copy<br>
> -  //   constructor, there is no user-declared move constructor, and there is no<br>
> -  //   user-declared move assignment operator, a copy constructor is implicitly<br>
> -  //   declared as defaulted.<br>
>   if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor))<br>
>     SetDeclDeleted(CopyConstructor, ClassLoc);<br>
><br>
> @@ -10195,29 +10080,12 @@ Sema::ComputeDefaultedMoveCtorExceptionS<br>
><br>
> CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(<br>
>                                                     CXXRecordDecl *ClassDecl) {<br>
> -  // C++11 [class.copy]p9:<br>
> -  //   If the definition of a class X does not explicitly declare a move<br>
> -  //   constructor, one will be implicitly declared as defaulted if and only if:<br>
> -  //<br>
> -  //   - [first 4 bullets]<br>
>   assert(ClassDecl->needsImplicitMoveConstructor());<br>
><br>
>   DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveConstructor);<br>
>   if (DSM.isAlreadyBeingDeclared())<br>
>     return 0;<br>
><br>
> -  // [Checked after we build the declaration]<br>
> -  //   - the move assignment operator would not be implicitly defined as<br>
> -  //     deleted,<br>
> -<br>
> -  // [DR1402]:<br>
> -  //   - each of X's non-static data members and direct or virtual base classes<br>
> -  //     has a type that either has a move constructor or is trivially copyable.<br>
> -  if (!subobjectsHaveMoveOrTrivialCopy(*this, ClassDecl, /*Constructor*/true)) {<br>
> -    ClassDecl->setFailedImplicitMoveConstructor();<br>
> -    return 0;<br>
> -  }<br>
> -<br>
>   QualType ClassType = Context.getTypeDeclType(ClassDecl);<br>
>   QualType ArgType = Context.getRValueReferenceType(ClassType);<br>
><br>
> @@ -10260,16 +10128,9 @@ CXXConstructorDecl *Sema::DeclareImplici<br>
>       ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor)<br>
>       : ClassDecl->hasTrivialMoveConstructor());<br>
><br>
> -  // C++0x [class.copy]p9:<br>
> -  //   If the definition of a class X does not explicitly declare a move<br>
> -  //   constructor, one will be implicitly declared as defaulted if and only if:<br>
> -  //   [...]<br>
> -  //   - the move constructor would not be implicitly defined as deleted.<br>
>   if (ShouldDeleteSpecialMember(MoveConstructor, CXXMoveConstructor)) {<br>
> -    // Cache this result so that we don't try to generate this over and over<br>
> -    // on every lookup, leaking memory and wasting time.<br>
> -    ClassDecl->setFailedImplicitMoveConstructor();<br>
> -    return 0;<br>
> +    ClassDecl->setImplicitMoveConstructorIsDeleted();<br>
> +    SetDeclDeleted(MoveConstructor, ClassLoc);<br>
>   }<br>
><br>
>   // Note that we have declared this constructor.<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=193969&r1=193968&r2=193969&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=193969&r1=193968&r2=193969&view=diff</a><br>


> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sun Nov  3 19:48:18 2013<br>
> @@ -3602,8 +3602,8 @@ static bool evaluateTypeTrait(Sema &S, T<br>
>     //   is_trivially_constructible is defined as:<br>
>     //<br>
>     //     is_constructible<T, Args...>::value is true and the variable<br>
> -    //     definition for is_constructible, as defined below, is known to call no<br>
> -    //     operation that is not trivial.<br>
> +    //     definition for is_constructible, as defined below, is known to call<br>
> +    //     no operation that is not trivial.<br>
>     //<br>
>     //   The predicate condition for a template specialization<br>
>     //   is_constructible<T, Args...> shall be satisfied if and only if the<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaOverload.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=193969&r1=193968&r2=193969&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=193969&r1=193968&r2=193969&view=diff</a><br>


> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaOverload.cpp Sun Nov  3 19:48:18 2013<br>
> @@ -5448,10 +5448,18 @@ Sema::AddOverloadCandidate(FunctionDecl<br>
>   if (!CandidateSet.isNewCandidate(Function))<br>
>     return;<br>
><br>
> +  // C++11 [class.copy]p11: [DR1402]<br>
> +  //   A defaulted move constructor that is defined as deleted is ignored by<br>
> +  //   overload resolution.<br>
> +  CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Function);<br>
> +  if (Constructor && Constructor->isDefaulted() && Constructor->isDeleted() &&<br>
> +      Constructor->isMoveConstructor())<br>
> +    return;<br>
> +<br>
>   // Overload resolution is always an unevaluated context.<br>
>   EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);<br>
><br>
> -  if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Function)){<br>
> +  if (Constructor) {<br>
>     // C++ [class.copy]p3:<br>
>     //   A member function template is never instantiated to perform the copy<br>
>     //   of a class object to an object of its class type.<br>
> @@ -5626,6 +5634,13 @@ Sema::AddMethodCandidate(CXXMethodDecl *<br>
>   if (!CandidateSet.isNewCandidate(Method))<br>
>     return;<br>
><br>
> +  // C++11 [class.copy]p23: [DR1402]<br>
> +  //   A defaulted move assignment operator that is defined as deleted is<br>
> +  //   ignored by overload resolution.<br>
> +  if (Method->isDefaulted() && Method->isDeleted() &&<br>
> +      Method->isMoveAssignmentOperator())<br>
> +    return;<br>
> +<br>
>   // Overload resolution is always an unevaluated context.<br>
>   EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);<br>
><br>
><br>
> Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=193969&r1=193968&r2=193969&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=193969&r1=193968&r2=193969&view=diff</a><br>


> ==============================================================================<br>
> --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)<br>
> +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Sun Nov  3 19:48:18 2013<br>
> @@ -1208,8 +1208,6 @@ void ASTDeclReader::ReadCXXDefinitionDat<br>
>   Data.ImplicitCopyAssignmentHasConstParam = Record[Idx++];<br>
>   Data.HasDeclaredCopyConstructorWithConstParam = Record[Idx++];<br>
>   Data.HasDeclaredCopyAssignmentWithConstParam = Record[Idx++];<br>
> -  Data.FailedImplicitMoveConstructor = Record[Idx++];<br>
> -  Data.FailedImplicitMoveAssignment = Record[Idx++];<br>
><br>
>   Data.NumBases = Record[Idx++];<br>
>   if (Data.NumBases)<br>
><br>
> Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=193969&r1=193968&r2=193969&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=193969&r1=193968&r2=193969&view=diff</a><br>


> ==============================================================================<br>
> --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)<br>
> +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Sun Nov  3 19:48:18 2013<br>
> @@ -5106,8 +5106,6 @@ void ASTWriter::AddCXXDefinitionData(con<br>
>   Record.push_back(Data.ImplicitCopyAssignmentHasConstParam);<br>
>   Record.push_back(Data.HasDeclaredCopyConstructorWithConstParam);<br>
>   Record.push_back(Data.HasDeclaredCopyAssignmentWithConstParam);<br>
> -  Record.push_back(Data.FailedImplicitMoveConstructor);<br>
> -  Record.push_back(Data.FailedImplicitMoveAssignment);<br>
>   // IsLambda bit is already saved.<br>
><br>
>   Record.push_back(Data.NumBases);<br>
><br>
> Modified: cfe/trunk/test/CXX/class.derived/class.abstract/p16.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.derived/class.abstract/p16.cpp?rev=193969&r1=193968&r2=193969&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.derived/class.abstract/p16.cpp?rev=193969&r1=193968&r2=193969&view=diff</a><br>


> ==============================================================================<br>
> --- cfe/trunk/test/CXX/class.derived/class.abstract/p16.cpp (original)<br>
> +++ cfe/trunk/test/CXX/class.derived/class.abstract/p16.cpp Sun Nov  3 19:48:18 2013<br>
> @@ -22,7 +22,7 @@ struct H;<br>
> struct D {<br>
>   virtual E &operator=(const E &); // expected-note {{here}}<br>
>   virtual F &operator=(const F &);<br>
> -  virtual G &operator=(G&&);<br>
> +  virtual G &operator=(G&&); // expected-note {{here}}<br>
>   virtual H &operator=(H&&); // expected-note {{here}}<br>
>   friend struct F;<br>
><br>
> @@ -34,8 +34,8 @@ private:<br>
> struct E : D {}; // expected-error {{deleted function '~E' cannot override a non-deleted function}} \<br>
>                  // expected-error {{deleted function 'operator=' cannot override a non-deleted function}}<br>
> struct F : D {};<br>
> -// No move ctor here, because it would be deleted.<br>
> struct G : D {}; // expected-error {{deleted function '~G' cannot override a non-deleted function}}<br>
> +                 // expected-error@-1 {{deleted function 'operator=' cannot override a non-deleted function}}<br>
> struct H : D {<br>
>   H &operator=(H&&) = default; // expected-error {{deleted function 'operator=' cannot override a non-deleted function}}<br>
>   ~H();<br>
><br>
> Modified: cfe/trunk/test/CXX/drs/dr1xx.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr1xx.cpp?rev=193969&r1=193968&r2=193969&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr1xx.cpp?rev=193969&r1=193968&r2=193969&view=diff</a><br>


> ==============================================================================<br>
> --- cfe/trunk/test/CXX/drs/dr1xx.cpp (original)<br>
> +++ cfe/trunk/test/CXX/drs/dr1xx.cpp Sun Nov  3 19:48:18 2013<br>
> @@ -71,7 +71,7 @@ namespace dr109 { // dr109: yes<br>
><br>
> namespace dr111 { // dr111: dup 535<br>
>   struct A { A(); A(volatile A&, int = 0); A(A&, const char * = "foo"); };<br>
> -  struct B : A { B(); }; // expected-note {{would lose const qualifier}} expected-note {{requires 0 arguments}}<br>
> +  struct B : A { B(); }; // expected-note +{{would lose const qualifier}} expected-note {{requires 0 arguments}}<br>
>   const B b1;<br>
>   B b2(b1); // expected-error {{no matching constructor}}<br>
> }<br>
><br>
> Modified: cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp?rev=193969&r1=193968&r2=193969&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp?rev=193969&r1=193968&r2=193969&view=diff</a><br>


> ==============================================================================<br>
> --- cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp (original)<br>
> +++ cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp Sun Nov  3 19:48:18 2013<br>
> @@ -190,49 +190,59 @@ namespace DR1402 {<br>
>     NonTrivialMoveAssignVBase &operator=(NonTrivialMoveAssignVBase &&) = default;<br>
>   };<br>
><br>
> -  // A non-movable, non-trivially-copyable class type as a subobject inhibits<br>
> -  // the declaration of a move operation.<br>
> -  struct NoMove1 { NonTrivialCopyCtor ntcc; }; // expected-note 2{{'const DR1402::NoMove1 &'}}<br>
> -  struct NoMove2 { NonTrivialCopyAssign ntcc; }; // expected-note 2{{'const DR1402::NoMove2 &'}}<br>
> -  struct NoMove3 : NonTrivialCopyCtor {}; // expected-note 2{{'const DR1402::NoMove3 &'}}<br>
> -  struct NoMove4 : NonTrivialCopyAssign {}; // expected-note 2{{'const DR1402::NoMove4 &'}}<br>
> -  struct NoMove5 : virtual NonTrivialCopyCtor {}; // expected-note 2{{'const DR1402::NoMove5 &'}}<br>
> -  struct NoMove6 : virtual NonTrivialCopyAssign {}; // expected-note 2{{'const DR1402::NoMove6 &'}}<br>
> -  struct NoMove7 : NonTrivialCopyCtorVBase {}; // expected-note 2{{'const DR1402::NoMove7 &'}}<br>
> -  struct NoMove8 : NonTrivialCopyAssignVBase {}; // expected-note 2{{'const DR1402::NoMove8 &'}}<br>
> +  // DR1402: A non-movable, non-trivially-copyable class type as a subobject no<br>
> +  // longer inhibits the declaration of a move operation.<br>
> +  struct NoMove1 { NonTrivialCopyCtor ntcc; };<br>
> +  struct NoMove2 { NonTrivialCopyAssign ntcc; };<br>
> +  struct NoMove3 : NonTrivialCopyCtor {};<br>
> +  struct NoMove4 : NonTrivialCopyAssign {};<br>
> +  struct NoMove5 : virtual NonTrivialCopyCtor {};<br>
> +  struct NoMove6 : virtual NonTrivialCopyAssign {};<br>
> +  struct NoMove7 : NonTrivialCopyCtorVBase {};<br>
> +  struct NoMove8 : NonTrivialCopyAssignVBase {};<br>
><br>
> -  // A non-trivially-move-assignable virtual base class inhibits the declaration<br>
> -  // of a move assignment (which might move-assign the base class multiple<br>
> -  // times).<br>
> +  // DR1402: A non-trivially-move-assignable virtual base class no longer<br>
> +  // inhibits the declaration of a move assignment (even though it might<br>
> +  // move-assign the base class multiple times).<br>
>   struct NoMove9 : NonTrivialMoveAssign {};<br>
> -  struct NoMove10 : virtual NonTrivialMoveAssign {}; // expected-note {{'const DR1402::NoMove10 &'}}<br>
> -  struct NoMove11 : NonTrivialMoveAssignVBase {}; // expected-note {{'const DR1402::NoMove11 &'}}<br>
> +  struct NoMove10 : virtual NonTrivialMoveAssign {};<br>
> +  struct NoMove11 : NonTrivialMoveAssignVBase {};<br>
><br>
> -  struct Test {<br>
> -    friend NoMove1::NoMove1(NoMove1 &&); // expected-error {{does not match}}<br>
> -    friend NoMove2::NoMove2(NoMove2 &&); // expected-error {{does not match}}<br>
> -    friend NoMove3::NoMove3(NoMove3 &&); // expected-error {{does not match}}<br>
> -    friend NoMove4::NoMove4(NoMove4 &&); // expected-error {{does not match}}<br>
> -    friend NoMove5::NoMove5(NoMove5 &&); // expected-error {{does not match}}<br>
> -    friend NoMove6::NoMove6(NoMove6 &&); // expected-error {{does not match}}<br>
> -    friend NoMove7::NoMove7(NoMove7 &&); // expected-error {{does not match}}<br>
> -    friend NoMove8::NoMove8(NoMove8 &&); // expected-error {{does not match}}<br>
> -    friend NoMove9::NoMove9(NoMove9 &&);<br>
> -    friend NoMove10::NoMove10(NoMove10 &&);<br>
> -    friend NoMove11::NoMove11(NoMove11 &&);<br>
> +  template<typename T> void test(T t) {<br>
> +    (void)T(static_cast<T&&>(t)); // ok<br>
> +    t = static_cast<T&&>(t); // ok<br>
> +  }<br>
> +  template void test(NoMove1);<br>
> +  template void test(NoMove2);<br>
> +  template void test(NoMove3);<br>
> +  template void test(NoMove4);<br>
> +  template void test(NoMove5);<br>
> +  template void test(NoMove6);<br>
> +  template void test(NoMove7);<br>
> +  template void test(NoMove8);<br>
> +  template void test(NoMove9);<br>
> +  template void test(NoMove10);<br>
> +  template void test(NoMove11);<br>
><br>
> -    friend NoMove1 &NoMove1::operator=(NoMove1 &&); // expected-error {{does not match}}<br>
> -    friend NoMove2 &NoMove2::operator=(NoMove2 &&); // expected-error {{does not match}}<br>
> -    friend NoMove3 &NoMove3::operator=(NoMove3 &&); // expected-error {{does not match}}<br>
> -    friend NoMove4 &NoMove4::operator=(NoMove4 &&); // expected-error {{does not match}}<br>
> -    friend NoMove5 &NoMove5::operator=(NoMove5 &&); // expected-error {{does not match}}<br>
> -    friend NoMove6 &NoMove6::operator=(NoMove6 &&); // expected-error {{does not match}}<br>
> -    friend NoMove7 &NoMove7::operator=(NoMove7 &&); // expected-error {{does not match}}<br>
> -    friend NoMove8 &NoMove8::operator=(NoMove8 &&); // expected-error {{does not match}}<br>
> -    friend NoMove9 &NoMove9::operator=(NoMove9 &&);<br>
> -    friend NoMove10 &NoMove10::operator=(NoMove10 &&); // expected-error {{does not match}}<br>
> -    friend NoMove11 &NoMove11::operator=(NoMove11 &&); // expected-error {{does not match}}<br>
> +  struct CopyOnly {<br>
> +    CopyOnly(const CopyOnly&);<br>
> +    CopyOnly &operator=(const CopyOnly&);<br>
>   };<br>
> +  struct MoveOnly {<br>
> +    MoveOnly(MoveOnly&&); // expected-note {{user-declared move}}<br>
> +    MoveOnly &operator=(MoveOnly&&);<br>
> +  };<br>
> +  template void test(CopyOnly); // ok, copies<br>
> +  template void test(MoveOnly); // ok, moves<br>
> +  struct CopyAndMove { // expected-note {{implicitly deleted}}<br>
> +    CopyOnly co;<br>
> +    MoveOnly mo; // expected-note {{deleted copy}}<br>
> +  };<br>
> +  template void test(CopyAndMove); // ok, copies co, moves mo<br>
> +  void test2(CopyAndMove cm) {<br>
> +    (void)CopyAndMove(cm); // expected-error {{deleted}}<br>
> +    cm = cm; // expected-error {{deleted}}<br>
> +  }<br>
> }<br>
><br>
> namespace PR12625 {<br>
><br>
> Modified: cfe/trunk/test/CXX/special/class.copy/p12-0x.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/p12-0x.cpp?rev=193969&r1=193968&r2=193969&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/p12-0x.cpp?rev=193969&r1=193968&r2=193969&view=diff</a><br>


> ==============================================================================<br>
> --- cfe/trunk/test/CXX/special/class.copy/p12-0x.cpp (original)<br>
> +++ cfe/trunk/test/CXX/special/class.copy/p12-0x.cpp Sun Nov  3 19:48:18 2013<br>
> @@ -157,8 +157,8 @@ namespace TrivialityDependsOnImplicitDel<br>
><br>
>   struct NoAccess {<br>
>     PrivateMove pm;<br>
> -    // NoAccess's move would be deleted, so is suppressed,<br>
> -    // so moves of it use PrivateMove's copy ctor, which is trivial.<br>
> +    // NoAccess's move is deleted, so moves of it use PrivateMove's copy ctor,<br>
> +    // which is trivial.<br>
>   };<br>
>   static_assert(__is_trivially_constructible(NoAccess, const NoAccess &), "");<br>
>   static_assert(__is_trivially_constructible(NoAccess, NoAccess &&), "");<br>
><br>
> Modified: cfe/trunk/test/CXX/special/class.copy/p23-cxx11.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/p23-cxx11.cpp?rev=193969&r1=193968&r2=193969&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/p23-cxx11.cpp?rev=193969&r1=193968&r2=193969&view=diff</a><br>


> ==============================================================================<br>
> --- cfe/trunk/test/CXX/special/class.copy/p23-cxx11.cpp (original)<br>
> +++ cfe/trunk/test/CXX/special/class.copy/p23-cxx11.cpp Sun Nov  3 19:48:18 2013<br>
> @@ -9,7 +9,15 @@ template<typename T> struct CopyAssign {<br>
> template<typename T> struct MoveAssign {<br>
>   static T t;<br>
>   void test() {<br>
> -    t = static_cast<T&&>(t); // expected-error +{{deleted}}<br>
> +    // Overload resolution will ignore a defaulted, deleted move assignment,<br>
> +    // so check for it in a different way.<br>
> +    T &(T::*f)(T&&) = &T::operator=; // expected-error +{{deleted}}<br>
> +  }<br>
> +};<br>
> +template<typename T> struct MoveOrCopyAssign {<br>
> +  static T t;<br>
> +  void test() {<br>
> +    t = static_cast<T&&>(t); // expected-error +{{copy assignment operator is implicitly deleted}}<br>
>   }<br>
> };<br>
><br>
> @@ -89,29 +97,32 @@ struct D1 {<br>
>   AmbiguousCopyAssign a; // expected-note {{field 'a' has multiple copy}}<br>
> };<br>
> struct D2 {<br>
> -  D2 &operator=(D2 &&) = default; // expected-note {{here}}<br>
> +  D2 &operator=(D2 &&) = default; // expected-note {{here}} expected-note {{copy assignment operator is implicitly deleted}}<br>
>   AmbiguousMoveAssign a; // expected-note {{field 'a' has multiple move}}<br>
> };<br>
> struct D3 {<br>
>   DeletedCopyAssign a; // expected-note {{field 'a' has a deleted copy}}<br>
> };<br>
> struct D4 {<br>
> -  D4 &operator=(D4 &&) = default; // expected-note {{here}}<br>
> +  D4 &operator=(D4 &&) = default; // expected-note {{here}} expected-note {{copy assignment operator is implicitly deleted}}<br>
>   DeletedMoveAssign a; // expected-note {{field 'a' has a deleted move}}<br>
> };<br>
> struct D5 {<br>
>   InaccessibleCopyAssign a; // expected-note {{field 'a' has an inaccessible copy}}<br>
> };<br>
> struct D6 {<br>
> -  D6 &operator=(D6 &&) = default; // expected-note {{here}}<br>
> +  D6 &operator=(D6 &&) = default; // expected-note {{here}} expected-note {{copy assignment operator is implicitly deleted}}<br>
>   InaccessibleMoveAssign a; // expected-note {{field 'a' has an inaccessible move}}<br>
> };<br>
> template struct CopyAssign<D1>; // expected-note {{here}}<br>
> template struct MoveAssign<D2>; // expected-note {{here}}<br>
> +template struct MoveOrCopyAssign<D2>; // expected-note {{here}}<br>
> template struct CopyAssign<D3>; // expected-note {{here}}<br>
> template struct MoveAssign<D4>; // expected-note {{here}}<br>
> +template struct MoveOrCopyAssign<D4>; // expected-note {{here}}<br>
> template struct CopyAssign<D5>; // expected-note {{here}}<br>
> template struct MoveAssign<D6>; // expected-note {{here}}<br>
> +template struct MoveOrCopyAssign<D6>; // expected-note {{here}}<br>
><br>
> //   -- a direct or virtual base that cannot be copied/moved<br>
> struct E1 : AmbiguousCopyAssign {}; // expected-note {{base class 'AmbiguousCopyAssign' has multiple copy}}<br>
><br>
><br>
> _______________________________________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
<br>
<br></div></div></blockquote></div><br></div>
</blockquote></div><br></div>
</blockquote></div><br></div></body></html>