r310401 - PR19668, PR23034: Fix handling of move constructors and deleted copy

Vassil Vassilev via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 10 01:30:01 PDT 2017


Hi Diana,

   Thanks for helping us out!

Cheers, Vassil
On 10/08/17 11:28, Diana Picus wrote:
> Hi Vassil,
>
> My build is in progress, but since it's a full build it's probably
> going to take another couple of hours to complete. I'll let you know
> when it's done.
>
> Thanks,
> Diana
>
> On 10 August 2017 at 10:09, Vassil Vassilev <v.g.vassilev at gmail.com> wrote:
>> It looks like I can not reproduce it on osx (non-arm)... :(
>> On 09/08/17 22:54, Diana Picus wrote:
>>> Reverting this also fixed the selfhost bots:
>>>
>>> http://lab.llvm.org:8011/builders/clang-cmake-thumbv7-a15-full-sh/builds/2142
>>>
>>> http://lab.llvm.org:8011/builders/clang-cmake-armv7-a15-selfhost/builds/2309
>>>
>>> http://lab.llvm.org:8011/builders/clang-cmake-armv7-a15-selfhost-neon/builds/1819
>>>
>>> I'm afraid the logs for those look even less helpful.
>>>
>>> On 9 August 2017 at 16:17, Diana Picus <diana.picus at linaro.org> wrote:
>>>> Hi,
>>>>
>>>> See attached. FWIW, when I ran this on a very similar machine, I got
>>>> 194 failures, all of which went away after reverting. So there might
>>>> be something fishy going on.
>>>>
>>>> Regards,
>>>> Diana
>>>>
>>>> On 9 August 2017 at 15:02, Vassil Vassilev <v.g.vassilev at gmail.com>
>>>> wrote:
>>>>> Hi Diana,
>>>>>
>>>>>     It seems the service is down. Could you send us the details of the
>>>>> failures (incl stack traces if any)
>>>>>
>>>>> Many thanks,
>>>>> Vassil
>>>>>
>>>>> On 09/08/17 15:27, Diana Picus via cfe-commits wrote:
>>>>>> Hi Richard,
>>>>>>
>>>>>> I'm sorry but I've reverted this in r310464 because it was breaking
>>>>>> some ASAN tests on this bot:
>>>>>>
>>>>>> http://lab.llvm.org:8011/builders/clang-cmake-armv7-a15-full/builds/9452
>>>>>>
>>>>>> Please let me know if I can help debug this.
>>>>>>
>>>>>> Cheers,
>>>>>> Diana
>>>>>>
>>>>>> On 8 August 2017 at 21:14, Richard Smith via cfe-commits
>>>>>> <cfe-commits at lists.llvm.org> wrote:
>>>>>>> I forgot to say:
>>>>>>>
>>>>>>> Based on a patch by Vassil Vassilev, which was based on a patch by
>>>>>>> Bernd
>>>>>>> Schmidt, which was based on a patch by Reid Kleckner.
>>>>>>>
>>>>>>> On 8 August 2017 at 12:12, Richard Smith via cfe-commits
>>>>>>> <cfe-commits at lists.llvm.org> wrote:
>>>>>>>> Author: rsmith
>>>>>>>> Date: Tue Aug  8 12:12:28 2017
>>>>>>>> New Revision: 310401
>>>>>>>>
>>>>>>>> URL: http://llvm.org/viewvc/llvm-project?rev=310401&view=rev
>>>>>>>> Log:
>>>>>>>> PR19668, PR23034: Fix handling of move constructors and deleted copy
>>>>>>>> constructors when deciding whether classes should be passed
>>>>>>>> indirectly.
>>>>>>>>
>>>>>>>> This fixes ABI differences between Clang and GCC:
>>>>>>>>
>>>>>>>>     * Previously, Clang ignored the move constructor when making this
>>>>>>>>       determination. It now takes the move constructor into account,
>>>>>>>> per
>>>>>>>>       https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change
>>>>>>>> may
>>>>>>>>       seem recent, but the ABI change was agreed on the Itanium C++
>>>>>>>> ABI
>>>>>>>>       list a long time ago).
>>>>>>>>
>>>>>>>>     * Previously, Clang's behavior when the copy constructor was
>>>>>>>> deleted
>>>>>>>>       was unstable -- depending on whether the lazy declaration of the
>>>>>>>>       copy constructor had been triggered, you might get different
>>>>>>>> behavior.
>>>>>>>>       We now eagerly declare the copy constructor whenever its
>>>>>>>> deletedness
>>>>>>>>       is unclear, and ignore deleted copy/move constructors when
>>>>>>>> looking
>>>>>>>> for
>>>>>>>>       a trivial such constructor.
>>>>>>>>
>>>>>>>> This also fixes an ABI difference between Clang and MSVC:
>>>>>>>>
>>>>>>>>     * If the copy constructor would be implicitly deleted (but has not
>>>>>>>> been
>>>>>>>>       lazily declared yet), for instance because the class has an
>>>>>>>> rvalue
>>>>>>>>       reference member, we would pass it directly. We now pass such a
>>>>>>>> class
>>>>>>>>       indirectly, matching MSVC.
>>>>>>>>
>>>>>>>> Modified:
>>>>>>>>        cfe/trunk/include/clang/AST/DeclCXX.h
>>>>>>>>        cfe/trunk/lib/AST/ASTImporter.cpp
>>>>>>>>        cfe/trunk/lib/AST/DeclCXX.cpp
>>>>>>>>        cfe/trunk/lib/CodeGen/CGCXXABI.cpp
>>>>>>>>        cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
>>>>>>>>        cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
>>>>>>>>        cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>>>>>>>>        cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
>>>>>>>>        cfe/trunk/lib/Serialization/ASTWriter.cpp
>>>>>>>>        cfe/trunk/test/CodeGenCXX/uncopyable-args.cpp
>>>>>>>>        cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
>>>>>>>>
>>>>>>>> Modified: cfe/trunk/include/clang/AST/DeclCXX.h
>>>>>>>> URL:
>>>>>>>>
>>>>>>>>
>>>>>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=310401&r1=310400&r2=310401&view=diff
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- cfe/trunk/include/clang/AST/DeclCXX.h (original)
>>>>>>>> +++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Aug  8 12:12:28 2017
>>>>>>>> @@ -375,6 +375,7 @@ class CXXRecordDecl : public RecordDecl
>>>>>>>>         /// \brief These flags are \c true if a defaulted
>>>>>>>> corresponding
>>>>>>>> special
>>>>>>>>         /// member can't be fully analyzed without performing overload
>>>>>>>> resolution.
>>>>>>>>         /// @{
>>>>>>>> +    unsigned NeedOverloadResolutionForCopyConstructor : 1;
>>>>>>>>         unsigned NeedOverloadResolutionForMoveConstructor : 1;
>>>>>>>>         unsigned NeedOverloadResolutionForMoveAssignment : 1;
>>>>>>>>         unsigned NeedOverloadResolutionForDestructor : 1;
>>>>>>>> @@ -383,6 +384,7 @@ class CXXRecordDecl : public RecordDecl
>>>>>>>>         /// \brief These flags are \c true if an implicit defaulted
>>>>>>>> corresponding
>>>>>>>>         /// special member would be defined as deleted.
>>>>>>>>         /// @{
>>>>>>>> +    unsigned DefaultedCopyConstructorIsDeleted : 1;
>>>>>>>>         unsigned DefaultedMoveConstructorIsDeleted : 1;
>>>>>>>>         unsigned DefaultedMoveAssignmentIsDeleted : 1;
>>>>>>>>         unsigned DefaultedDestructorIsDeleted : 1;
>>>>>>>> @@ -415,6 +417,12 @@ class CXXRecordDecl : public RecordDecl
>>>>>>>>         /// constructor.
>>>>>>>>         unsigned HasDefaultedDefaultConstructor : 1;
>>>>>>>>
>>>>>>>> +    /// \brief True if this class can be passed in a
>>>>>>>> non-address-preserving
>>>>>>>> +    /// fashion (such as in registers) according to the C++ language
>>>>>>>> rules.
>>>>>>>> +    /// This does not imply anything about how the ABI in use will
>>>>>>>> actually
>>>>>>>> +    /// pass an object of this class.
>>>>>>>> +    unsigned CanPassInRegisters : 1;
>>>>>>>> +
>>>>>>>>         /// \brief True if a defaulted default constructor for this
>>>>>>>> class
>>>>>>>> would
>>>>>>>>         /// be constexpr.
>>>>>>>>         unsigned DefaultedDefaultConstructorIsConstexpr : 1;
>>>>>>>> @@ -811,18 +819,50 @@ public:
>>>>>>>>         return data().FirstFriend.isValid();
>>>>>>>>       }
>>>>>>>>
>>>>>>>> +  /// \brief \c true if a defaulted copy constructor for this class
>>>>>>>> would
>>>>>>>> be
>>>>>>>> +  /// deleted.
>>>>>>>> +  bool defaultedCopyConstructorIsDeleted() const {
>>>>>>>> +    assert((!needsOverloadResolutionForCopyConstructor() ||
>>>>>>>> +            (data().DeclaredSpecialMembers & SMF_CopyConstructor))
>>>>>>>> &&
>>>>>>>> +           "this property has not yet been computed by Sema");
>>>>>>>> +    return data().DefaultedCopyConstructorIsDeleted;
>>>>>>>> +  }
>>>>>>>> +
>>>>>>>> +  /// \brief \c true if a defaulted move constructor for this class
>>>>>>>> would
>>>>>>>> be
>>>>>>>> +  /// deleted.
>>>>>>>> +  bool defaultedMoveConstructorIsDeleted() const {
>>>>>>>> +    assert((!needsOverloadResolutionForMoveConstructor() ||
>>>>>>>> +            (data().DeclaredSpecialMembers & SMF_MoveConstructor))
>>>>>>>> &&
>>>>>>>> +           "this property has not yet been computed by Sema");
>>>>>>>> +    return data().DefaultedMoveConstructorIsDeleted;
>>>>>>>> +  }
>>>>>>>> +
>>>>>>>> +  /// \brief \c true if a defaulted destructor for this class would
>>>>>>>> be
>>>>>>>> deleted.
>>>>>>>> +  bool defaultedDestructorIsDeleted() const {
>>>>>>>> +    return !data().DefaultedDestructorIsDeleted;
>>>>>>>> +  }
>>>>>>>> +
>>>>>>>> +  /// \brief \c true if we know for sure that this class has a
>>>>>>>> single,
>>>>>>>> +  /// accessible, unambiguous copy constructor that is not deleted.
>>>>>>>> +  bool hasSimpleCopyConstructor() const {
>>>>>>>> +    return !hasUserDeclaredCopyConstructor() &&
>>>>>>>> +           !data().DefaultedCopyConstructorIsDeleted;
>>>>>>>> +  }
>>>>>>>> +
>>>>>>>>       /// \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()
>>>>>>>> &&
>>>>>>>>                !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()
>>>>>>>> &&
>>>>>>>>                !data().DefaultedMoveAssignmentIsDeleted;
>>>>>>>>       }
>>>>>>>> +
>>>>>>>>       /// \brief \c true if we know for sure that this class has an
>>>>>>>> accessible
>>>>>>>>       /// destructor that is not deleted.
>>>>>>>>       bool hasSimpleDestructor() const {
>>>>>>>> @@ -878,7 +918,16 @@ public:
>>>>>>>>       /// \brief Determine whether we need to eagerly declare a
>>>>>>>> defaulted
>>>>>>>> copy
>>>>>>>>       /// constructor for this class.
>>>>>>>>       bool needsOverloadResolutionForCopyConstructor() const {
>>>>>>>> -    return data().HasMutableFields;
>>>>>>>> +    // C++17 [class.copy.ctor]p6:
>>>>>>>> +    //   If the class definition declares a move constructor or move
>>>>>>>> assignment
>>>>>>>> +    //   operator, the implicitly declared copy constructor is
>>>>>>>> defined
>>>>>>>> as
>>>>>>>> +    //   deleted.
>>>>>>>> +    // In MSVC mode, sometimes a declared move assignment does not
>>>>>>>> delete
>>>>>>>> an
>>>>>>>> +    // implicit copy constructor, so defer this choice to Sema.
>>>>>>>> +    if (data().UserDeclaredSpecialMembers &
>>>>>>>> +        (SMF_MoveConstructor | SMF_MoveAssignment))
>>>>>>>> +      return true;
>>>>>>>> +    return data().NeedOverloadResolutionForCopyConstructor;
>>>>>>>>       }
>>>>>>>>
>>>>>>>>       /// \brief Determine whether an implicit copy constructor for
>>>>>>>> this
>>>>>>>> type
>>>>>>>> @@ -919,7 +968,16 @@ public:
>>>>>>>>                needsImplicitMoveConstructor();
>>>>>>>>       }
>>>>>>>>
>>>>>>>> -  /// \brief Set that we attempted to declare an implicitly move
>>>>>>>> +  /// \brief Set that we attempted to declare an implicit copy
>>>>>>>> +  /// constructor, but overload resolution failed so we deleted it.
>>>>>>>> +  void setImplicitCopyConstructorIsDeleted() {
>>>>>>>> +    assert((data().DefaultedCopyConstructorIsDeleted ||
>>>>>>>> +            needsOverloadResolutionForCopyConstructor()) &&
>>>>>>>> +           "Copy constructor should not be deleted");
>>>>>>>> +    data().DefaultedCopyConstructorIsDeleted = true;
>>>>>>>> +  }
>>>>>>>> +
>>>>>>>> +  /// \brief Set that we attempted to declare an implicit move
>>>>>>>>       /// constructor, but overload resolution failed so we deleted
>>>>>>>> it.
>>>>>>>>       void setImplicitMoveConstructorIsDeleted() {
>>>>>>>>         assert((data().DefaultedMoveConstructorIsDeleted ||
>>>>>>>> @@ -1316,6 +1374,18 @@ public:
>>>>>>>>         return data().HasIrrelevantDestructor;
>>>>>>>>       }
>>>>>>>>
>>>>>>>> +  /// \brief Determine whether this class has at least one trivial,
>>>>>>>> non-deleted
>>>>>>>> +  /// copy or move constructor.
>>>>>>>> +  bool canPassInRegisters() const {
>>>>>>>> +    return data().CanPassInRegisters;
>>>>>>>> +  }
>>>>>>>> +
>>>>>>>> +  /// \brief Set that we can pass this RecordDecl in registers.
>>>>>>>> +  // FIXME: This should be set as part of completeDefinition.
>>>>>>>> +  void setCanPassInRegisters(bool CanPass) {
>>>>>>>> +    data().CanPassInRegisters = CanPass;
>>>>>>>> +  }
>>>>>>>> +
>>>>>>>>       /// \brief Determine whether this class has a non-literal or/
>>>>>>>> volatile
>>>>>>>> type
>>>>>>>>       /// non-static data member or base class.
>>>>>>>>       bool hasNonLiteralTypeFieldsOrBases() const {
>>>>>>>>
>>>>>>>> Modified: cfe/trunk/lib/AST/ASTImporter.cpp
>>>>>>>> URL:
>>>>>>>>
>>>>>>>>
>>>>>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=310401&r1=310400&r2=310401&view=diff
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- cfe/trunk/lib/AST/ASTImporter.cpp (original)
>>>>>>>> +++ cfe/trunk/lib/AST/ASTImporter.cpp Tue Aug  8 12:12:28 2017
>>>>>>>> @@ -956,12 +956,16 @@ bool ASTNodeImporter::ImportDefinition(R
>>>>>>>>         ToData.HasUninitializedFields =
>>>>>>>> FromData.HasUninitializedFields;
>>>>>>>>         ToData.HasInheritedConstructor =
>>>>>>>> FromData.HasInheritedConstructor;
>>>>>>>>         ToData.HasInheritedAssignment =
>>>>>>>> FromData.HasInheritedAssignment;
>>>>>>>> +    ToData.NeedOverloadResolutionForCopyConstructor
>>>>>>>> +      = FromData.NeedOverloadResolutionForCopyConstructor;
>>>>>>>>         ToData.NeedOverloadResolutionForMoveConstructor
>>>>>>>>           = FromData.NeedOverloadResolutionForMoveConstructor;
>>>>>>>>         ToData.NeedOverloadResolutionForMoveAssignment
>>>>>>>>           = FromData.NeedOverloadResolutionForMoveAssignment;
>>>>>>>>         ToData.NeedOverloadResolutionForDestructor
>>>>>>>>           = FromData.NeedOverloadResolutionForDestructor;
>>>>>>>> +    ToData.DefaultedCopyConstructorIsDeleted
>>>>>>>> +      = FromData.DefaultedCopyConstructorIsDeleted;
>>>>>>>>         ToData.DefaultedMoveConstructorIsDeleted
>>>>>>>>           = FromData.DefaultedMoveConstructorIsDeleted;
>>>>>>>>         ToData.DefaultedMoveAssignmentIsDeleted
>>>>>>>> @@ -973,6 +977,7 @@ bool ASTNodeImporter::ImportDefinition(R
>>>>>>>>           = FromData.HasConstexprNonCopyMoveConstructor;
>>>>>>>>         ToData.HasDefaultedDefaultConstructor
>>>>>>>>           = FromData.HasDefaultedDefaultConstructor;
>>>>>>>> +    ToData.CanPassInRegisters = FromData.CanPassInRegisters;
>>>>>>>>         ToData.DefaultedDefaultConstructorIsConstexpr
>>>>>>>>           = FromData.DefaultedDefaultConstructorIsConstexpr;
>>>>>>>>         ToData.HasConstexprDefaultConstructor
>>>>>>>>
>>>>>>>> Modified: cfe/trunk/lib/AST/DeclCXX.cpp
>>>>>>>> URL:
>>>>>>>>
>>>>>>>>
>>>>>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=310401&r1=310400&r2=310401&view=diff
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- cfe/trunk/lib/AST/DeclCXX.cpp (original)
>>>>>>>> +++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Aug  8 12:12:28 2017
>>>>>>>> @@ -55,15 +55,18 @@ CXXRecordDecl::DefinitionData::Definitio
>>>>>>>>           HasOnlyCMembers(true), HasInClassInitializer(false),
>>>>>>>>           HasUninitializedReferenceMember(false),
>>>>>>>> HasUninitializedFields(false),
>>>>>>>>           HasInheritedConstructor(false),
>>>>>>>> HasInheritedAssignment(false),
>>>>>>>> +      NeedOverloadResolutionForCopyConstructor(false),
>>>>>>>>           NeedOverloadResolutionForMoveConstructor(false),
>>>>>>>>           NeedOverloadResolutionForMoveAssignment(false),
>>>>>>>>           NeedOverloadResolutionForDestructor(false),
>>>>>>>> +      DefaultedCopyConstructorIsDeleted(false),
>>>>>>>>           DefaultedMoveConstructorIsDeleted(false),
>>>>>>>>           DefaultedMoveAssignmentIsDeleted(false),
>>>>>>>>           DefaultedDestructorIsDeleted(false),
>>>>>>>> HasTrivialSpecialMembers(SMF_All),
>>>>>>>>           DeclaredNonTrivialSpecialMembers(0),
>>>>>>>> HasIrrelevantDestructor(true),
>>>>>>>>           HasConstexprNonCopyMoveConstructor(false),
>>>>>>>>           HasDefaultedDefaultConstructor(false),
>>>>>>>> +      CanPassInRegisters(false),
>>>>>>>>           DefaultedDefaultConstructorIsConstexpr(true),
>>>>>>>>           HasConstexprDefaultConstructor(false),
>>>>>>>>           HasNonLiteralTypeFieldsOrBases(false),
>>>>>>>> ComputedVisibleConversions(false),
>>>>>>>> @@ -352,8 +355,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier
>>>>>>>>           setHasVolatileMember(true);
>>>>>>>>
>>>>>>>>         // Keep track of the presence of mutable fields.
>>>>>>>> -    if (BaseClassDecl->hasMutableFields())
>>>>>>>> +    if (BaseClassDecl->hasMutableFields()) {
>>>>>>>>           data().HasMutableFields = true;
>>>>>>>> +      data().NeedOverloadResolutionForCopyConstructor = true;
>>>>>>>> +    }
>>>>>>>>
>>>>>>>>         if (BaseClassDecl->hasUninitializedReferenceMember())
>>>>>>>>           data().HasUninitializedReferenceMember = true;
>>>>>>>> @@ -406,6 +411,8 @@ void CXXRecordDecl::addedClassSubobject(
>>>>>>>>       //    -- a direct or virtual base class B that cannot be
>>>>>>>> copied/moved
>>>>>>>> [...]
>>>>>>>>       //    -- a non-static data member of class type M (or array
>>>>>>>> thereof)
>>>>>>>>       //       that cannot be copied or moved [...]
>>>>>>>> +  if (!Subobj->hasSimpleCopyConstructor())
>>>>>>>> +    data().NeedOverloadResolutionForCopyConstructor = true;
>>>>>>>>       if (!Subobj->hasSimpleMoveConstructor())
>>>>>>>>         data().NeedOverloadResolutionForMoveConstructor = true;
>>>>>>>>
>>>>>>>> @@ -426,6 +433,7 @@ void CXXRecordDecl::addedClassSubobject(
>>>>>>>>       //    -- any non-static data member has a type with a destructor
>>>>>>>>       //       that is deleted or inaccessible from the defaulted
>>>>>>>> [ctor or
>>>>>>>> dtor].
>>>>>>>>       if (!Subobj->hasSimpleDestructor()) {
>>>>>>>> +    data().NeedOverloadResolutionForCopyConstructor = true;
>>>>>>>>         data().NeedOverloadResolutionForMoveConstructor = true;
>>>>>>>>         data().NeedOverloadResolutionForDestructor = true;
>>>>>>>>       }
>>>>>>>> @@ -711,8 +719,10 @@ void CXXRecordDecl::addedMember(Decl *D)
>>>>>>>>           data().IsStandardLayout = false;
>>>>>>>>
>>>>>>>>         // Keep track of the presence of mutable fields.
>>>>>>>> -    if (Field->isMutable())
>>>>>>>> +    if (Field->isMutable()) {
>>>>>>>>           data().HasMutableFields = true;
>>>>>>>> +      data().NeedOverloadResolutionForCopyConstructor = true;
>>>>>>>> +    }
>>>>>>>>
>>>>>>>>         // C++11 [class.union]p8, DR1460:
>>>>>>>>         //   If X is a union, a non-static data member of X that is
>>>>>>>> not an
>>>>>>>> anonymous
>>>>>>>> @@ -756,6 +766,12 @@ void CXXRecordDecl::addedMember(Decl *D)
>>>>>>>>           //   A standard-layout class is a class that:
>>>>>>>>           //    -- has no non-static data members of type [...]
>>>>>>>> reference,
>>>>>>>>           data().IsStandardLayout = false;
>>>>>>>> +
>>>>>>>> +      // C++1z [class.copy.ctor]p10:
>>>>>>>> +      //   A defaulted copy constructor for a class X is defined as
>>>>>>>> deleted if X has:
>>>>>>>> +      //    -- a non-static data member of rvalue reference type
>>>>>>>> +      if (T->isRValueReferenceType())
>>>>>>>> +        data().DefaultedCopyConstructorIsDeleted = true;
>>>>>>>>         }
>>>>>>>>
>>>>>>>>         if (!Field->hasInClassInitializer() && !Field->isMutable()) {
>>>>>>>> @@ -809,6 +825,10 @@ void CXXRecordDecl::addedMember(Decl *D)
>>>>>>>>             // We may need to perform overload resolution to determine
>>>>>>>> whether a
>>>>>>>>             // field can be moved if it's const or volatile qualified.
>>>>>>>>             if (T.getCVRQualifiers() & (Qualifiers::Const |
>>>>>>>> Qualifiers::Volatile)) {
>>>>>>>> +          // We need to care about 'const' for the copy constructor
>>>>>>>> because an
>>>>>>>> +          // implicit copy constructor might be declared with a
>>>>>>>> non-const
>>>>>>>> +          // parameter.
>>>>>>>> +          data().NeedOverloadResolutionForCopyConstructor = true;
>>>>>>>>               data().NeedOverloadResolutionForMoveConstructor = true;
>>>>>>>>               data().NeedOverloadResolutionForMoveAssignment = true;
>>>>>>>>             }
>>>>>>>> @@ -819,6 +839,8 @@ void CXXRecordDecl::addedMember(Decl *D)
>>>>>>>>             //    -- X is a union-like class that has a variant member
>>>>>>>> with a
>>>>>>>>             //       non-trivial [corresponding special member]
>>>>>>>>             if (isUnion()) {
>>>>>>>> +          if (FieldRec->hasNonTrivialCopyConstructor())
>>>>>>>> +            data().DefaultedCopyConstructorIsDeleted = true;
>>>>>>>>               if (FieldRec->hasNonTrivialMoveConstructor())
>>>>>>>>                 data().DefaultedMoveConstructorIsDeleted = true;
>>>>>>>>               if (FieldRec->hasNonTrivialMoveAssignment())
>>>>>>>> @@ -830,6 +852,8 @@ void CXXRecordDecl::addedMember(Decl *D)
>>>>>>>>             // For an anonymous union member, our overload resolution
>>>>>>>> will
>>>>>>>> perform
>>>>>>>>             // overload resolution for its members.
>>>>>>>>             if (Field->isAnonymousStructOrUnion()) {
>>>>>>>> +          data().NeedOverloadResolutionForCopyConstructor |=
>>>>>>>> +
>>>>>>>> FieldRec->data().NeedOverloadResolutionForCopyConstructor;
>>>>>>>>               data().NeedOverloadResolutionForMoveConstructor |=
>>>>>>>>
>>>>>>>> FieldRec->data().NeedOverloadResolutionForMoveConstructor;
>>>>>>>>               data().NeedOverloadResolutionForMoveAssignment |=
>>>>>>>> @@ -915,8 +939,10 @@ void CXXRecordDecl::addedMember(Decl *D)
>>>>>>>>             }
>>>>>>>>
>>>>>>>>             // Keep track of the presence of mutable fields.
>>>>>>>> -        if (FieldRec->hasMutableFields())
>>>>>>>> +        if (FieldRec->hasMutableFields()) {
>>>>>>>>               data().HasMutableFields = true;
>>>>>>>> +          data().NeedOverloadResolutionForCopyConstructor = true;
>>>>>>>> +        }
>>>>>>>>
>>>>>>>>             // C++11 [class.copy]p13:
>>>>>>>>             //   If the implicitly-defined constructor would satisfy
>>>>>>>> the
>>>>>>>> @@ -1450,7 +1476,7 @@ void CXXRecordDecl::completeDefinition()
>>>>>>>>
>>>>>>>>     void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap
>>>>>>>> *FinalOverriders) {
>>>>>>>>       RecordDecl::completeDefinition();
>>>>>>>> -
>>>>>>>> +
>>>>>>>>       // If the class may be abstract (but hasn't been marked as
>>>>>>>> such),
>>>>>>>> check
>>>>>>>> for
>>>>>>>>       // any pure final overriders.
>>>>>>>>       if (mayBeAbstract()) {
>>>>>>>>
>>>>>>>> Modified: cfe/trunk/lib/CodeGen/CGCXXABI.cpp
>>>>>>>> URL:
>>>>>>>>
>>>>>>>>
>>>>>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.cpp?rev=310401&r1=310400&r2=310401&view=diff
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- cfe/trunk/lib/CodeGen/CGCXXABI.cpp (original)
>>>>>>>> +++ cfe/trunk/lib/CodeGen/CGCXXABI.cpp Tue Aug  8 12:12:28 2017
>>>>>>>> @@ -30,38 +30,9 @@ void CGCXXABI::ErrorUnsupportedABI(CodeG
>>>>>>>>     }
>>>>>>>>
>>>>>>>>     bool CGCXXABI::canCopyArgument(const CXXRecordDecl *RD) const {
>>>>>>>> -  // If RD has a non-trivial move or copy constructor, we cannot
>>>>>>>> copy
>>>>>>>> the
>>>>>>>> -  // argument.
>>>>>>>> -  if (RD->hasNonTrivialCopyConstructor() ||
>>>>>>>> RD->hasNonTrivialMoveConstructor())
>>>>>>>> -    return false;
>>>>>>>> -
>>>>>>>> -  // If RD has a non-trivial destructor, we cannot copy the
>>>>>>>> argument.
>>>>>>>> -  if (RD->hasNonTrivialDestructor())
>>>>>>>> -    return false;
>>>>>>>> -
>>>>>>>>       // We can only copy the argument if there exists at least one
>>>>>>>> trivial,
>>>>>>>>       // non-deleted copy or move constructor.
>>>>>>>> -  // FIXME: This assumes that all lazily declared copy and move
>>>>>>>> constructors are
>>>>>>>> -  // not deleted.  This assumption might not be true in some corner
>>>>>>>> cases.
>>>>>>>> -  bool CopyDeleted = false;
>>>>>>>> -  bool MoveDeleted = false;
>>>>>>>> -  for (const CXXConstructorDecl *CD : RD->ctors()) {
>>>>>>>> -    if (CD->isCopyConstructor() || CD->isMoveConstructor()) {
>>>>>>>> -      assert(CD->isTrivial());
>>>>>>>> -      // We had at least one undeleted trivial copy or move ctor.
>>>>>>>> Return
>>>>>>>> -      // directly.
>>>>>>>> -      if (!CD->isDeleted())
>>>>>>>> -        return true;
>>>>>>>> -      if (CD->isCopyConstructor())
>>>>>>>> -        CopyDeleted = true;
>>>>>>>> -      else
>>>>>>>> -        MoveDeleted = true;
>>>>>>>> -    }
>>>>>>>> -  }
>>>>>>>> -
>>>>>>>> -  // If all trivial copy and move constructors are deleted, we
>>>>>>>> cannot
>>>>>>>> copy the
>>>>>>>> -  // argument.
>>>>>>>> -  return !(CopyDeleted && MoveDeleted);
>>>>>>>> +  return RD->canPassInRegisters();
>>>>>>>>     }
>>>>>>>>
>>>>>>>>     llvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) {
>>>>>>>>
>>>>>>>> Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
>>>>>>>> URL:
>>>>>>>>
>>>>>>>>
>>>>>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=310401&r1=310400&r2=310401&view=diff
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
>>>>>>>> +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Tue Aug  8 12:12:28 2017
>>>>>>>> @@ -63,11 +63,8 @@ public:
>>>>>>>>       bool classifyReturnType(CGFunctionInfo &FI) const override;
>>>>>>>>
>>>>>>>>       RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const
>>>>>>>> override
>>>>>>>> {
>>>>>>>> -    // Structures with either a non-trivial destructor or a
>>>>>>>> non-trivial
>>>>>>>> -    // copy constructor are always indirect.
>>>>>>>> -    // FIXME: Use canCopyArgument() when it is fixed to handle
>>>>>>>> lazily
>>>>>>>> declared
>>>>>>>> -    // special members.
>>>>>>>> -    if (RD->hasNonTrivialDestructor() ||
>>>>>>>> RD->hasNonTrivialCopyConstructor())
>>>>>>>> +    // If C++ prohibits us from making a copy, pass by address.
>>>>>>>> +    if (!canCopyArgument(RD))
>>>>>>>>           return RAA_Indirect;
>>>>>>>>         return RAA_Default;
>>>>>>>>       }
>>>>>>>> @@ -1014,10 +1011,8 @@ bool ItaniumCXXABI::classifyReturnType(C
>>>>>>>>       if (!RD)
>>>>>>>>         return false;
>>>>>>>>
>>>>>>>> -  // Return indirectly if we have a non-trivial copy ctor or
>>>>>>>> non-trivial
>>>>>>>> dtor.
>>>>>>>> -  // FIXME: Use canCopyArgument() when it is fixed to handle lazily
>>>>>>>> declared
>>>>>>>> -  // special members.
>>>>>>>> -  if (RD->hasNonTrivialDestructor() ||
>>>>>>>> RD->hasNonTrivialCopyConstructor()) {
>>>>>>>> +  // If C++ prohibits us from making a copy, return by address.
>>>>>>>> +  if (!canCopyArgument(RD)) {
>>>>>>>>         auto Align =
>>>>>>>> CGM.getContext().getTypeAlignInChars(FI.getReturnType());
>>>>>>>>         FI.getReturnInfo() = ABIArgInfo::getIndirect(Align,
>>>>>>>> /*ByVal=*/false);
>>>>>>>>         return true;
>>>>>>>>
>>>>>>>> Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
>>>>>>>> URL:
>>>>>>>>
>>>>>>>>
>>>>>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=310401&r1=310400&r2=310401&view=diff
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
>>>>>>>> +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Tue Aug  8 12:12:28
>>>>>>>> 2017
>>>>>>>> @@ -819,46 +819,44 @@ MicrosoftCXXABI::getRecordArgABI(const C
>>>>>>>>         return RAA_Default;
>>>>>>>>
>>>>>>>>       case llvm::Triple::x86_64:
>>>>>>>> -    // Win64 passes objects with non-trivial copy ctors indirectly.
>>>>>>>> -    if (RD->hasNonTrivialCopyConstructor())
>>>>>>>> -      return RAA_Indirect;
>>>>>>>> -
>>>>>>>> -    // If an object has a destructor, we'd really like to pass it
>>>>>>>> indirectly
>>>>>>>> +    // If a class has a destructor, we'd really like to pass it
>>>>>>>> indirectly
>>>>>>>>         // because it allows us to elide copies.  Unfortunately, MSVC
>>>>>>>> makes
>>>>>>>> that
>>>>>>>>         // impossible for small types, which it will pass in a single
>>>>>>>> register or
>>>>>>>>         // stack slot. Most objects with dtors are large-ish, so
>>>>>>>> handle
>>>>>>>> that
>>>>>>>> early.
>>>>>>>>         // We can't call out all large objects as being indirect
>>>>>>>> because
>>>>>>>> there are
>>>>>>>>         // multiple x64 calling conventions and the C++ ABI code
>>>>>>>> shouldn't
>>>>>>>> dictate
>>>>>>>>         // how we pass large POD types.
>>>>>>>> +    //
>>>>>>>> +    // Note: This permits small classes with nontrivial destructors
>>>>>>>> to
>>>>>>>> be
>>>>>>>> +    // passed in registers, which is non-conforming.
>>>>>>>>         if (RD->hasNonTrivialDestructor() &&
>>>>>>>>             getContext().getTypeSize(RD->getTypeForDecl()) > 64)
>>>>>>>>           return RAA_Indirect;
>>>>>>>>
>>>>>>>> -    // If this is true, the implicit copy constructor that Sema
>>>>>>>> would
>>>>>>>> have
>>>>>>>> -    // created would not be deleted. FIXME: We should provide a more
>>>>>>>> direct way
>>>>>>>> -    // for CodeGen to ask whether the constructor was deleted.
>>>>>>>> -    if (!RD->hasUserDeclaredCopyConstructor() &&
>>>>>>>> -        !RD->hasUserDeclaredMoveConstructor() &&
>>>>>>>> -        !RD->needsOverloadResolutionForMoveConstructor() &&
>>>>>>>> -        !RD->hasUserDeclaredMoveAssignment() &&
>>>>>>>> -        !RD->needsOverloadResolutionForMoveAssignment())
>>>>>>>> -      return RAA_Default;
>>>>>>>> -
>>>>>>>> -    // Otherwise, Sema should have created an implicit copy
>>>>>>>> constructor
>>>>>>>> if
>>>>>>>> -    // needed.
>>>>>>>> -    assert(!RD->needsImplicitCopyConstructor());
>>>>>>>> -
>>>>>>>> -    // We have to make sure the trivial copy constructor isn't
>>>>>>>> deleted.
>>>>>>>> -    for (const CXXConstructorDecl *CD : RD->ctors()) {
>>>>>>>> -      if (CD->isCopyConstructor()) {
>>>>>>>> -        assert(CD->isTrivial());
>>>>>>>> -        // We had at least one undeleted trivial copy ctor.  Return
>>>>>>>> directly.
>>>>>>>> -        if (!CD->isDeleted())
>>>>>>>> -          return RAA_Default;
>>>>>>>> +    // If a class has at least one non-deleted, trivial copy
>>>>>>>> constructor,
>>>>>>>> it
>>>>>>>> +    // is passed according to the C ABI. Otherwise, it is passed
>>>>>>>> indirectly.
>>>>>>>> +    //
>>>>>>>> +    // Note: This permits classes with non-trivial copy or move
>>>>>>>> ctors
>>>>>>>> to
>>>>>>>> be
>>>>>>>> +    // passed in registers, so long as they *also* have a trivial
>>>>>>>> copy
>>>>>>>> ctor,
>>>>>>>> +    // which is non-conforming.
>>>>>>>> +    if (RD->needsImplicitCopyConstructor()) {
>>>>>>>> +      // If the copy ctor has not yet been declared, we can read its
>>>>>>>> triviality
>>>>>>>> +      // off the AST.
>>>>>>>> +      if (!RD->defaultedCopyConstructorIsDeleted() &&
>>>>>>>> +          RD->hasTrivialCopyConstructor())
>>>>>>>> +        return RAA_Default;
>>>>>>>> +    } else {
>>>>>>>> +      // Otherwise, we need to find the copy constructor(s) and ask.
>>>>>>>> +      for (const CXXConstructorDecl *CD : RD->ctors()) {
>>>>>>>> +        if (CD->isCopyConstructor()) {
>>>>>>>> +          // We had at least one nondeleted trivial copy ctor.
>>>>>>>> Return
>>>>>>>> directly.
>>>>>>>> +          if (!CD->isDeleted() && CD->isTrivial())
>>>>>>>> +            return RAA_Default;
>>>>>>>> +        }
>>>>>>>>           }
>>>>>>>>         }
>>>>>>>>
>>>>>>>> -    // The trivial copy constructor was deleted.  Return indirectly.
>>>>>>>> +    // We have no trivial, non-deleted copy constructor.
>>>>>>>>         return RAA_Indirect;
>>>>>>>>       }
>>>>>>>>
>>>>>>>>
>>>>>>>> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>>>>>>>> URL:
>>>>>>>>
>>>>>>>>
>>>>>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=310401&r1=310400&r2=310401&view=diff
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
>>>>>>>> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Aug  8 12:12:28 2017
>>>>>>>> @@ -5726,6 +5726,53 @@ static void DefineImplicitSpecialMember(
>>>>>>>>       }
>>>>>>>>     }
>>>>>>>>
>>>>>>>> +/// Determine whether a type is permitted to be passed or returned
>>>>>>>> in
>>>>>>>> +/// registers, per C++ [class.temporary]p3.
>>>>>>>> +static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) {
>>>>>>>> +  if (D->isDependentType() || D->isInvalidDecl())
>>>>>>>> +    return false;
>>>>>>>> +
>>>>>>>> +  // Per C++ [class.temporary]p3, the relevant condition is:
>>>>>>>> +  //   each copy constructor, move constructor, and destructor of X
>>>>>>>> is
>>>>>>>> +  //   either trivial or deleted, and X has at least one non-deleted
>>>>>>>> copy
>>>>>>>> +  //   or move constructor
>>>>>>>> +  bool HasNonDeletedCopyOrMove = false;
>>>>>>>> +
>>>>>>>> +  if (D->needsImplicitCopyConstructor() &&
>>>>>>>> +      !D->defaultedCopyConstructorIsDeleted()) {
>>>>>>>> +    if (!D->hasTrivialCopyConstructor())
>>>>>>>> +      return false;
>>>>>>>> +    HasNonDeletedCopyOrMove = true;
>>>>>>>> +  }
>>>>>>>> +
>>>>>>>> +  if (S.getLangOpts().CPlusPlus11 &&
>>>>>>>> D->needsImplicitMoveConstructor()
>>>>>>>> &&
>>>>>>>> +      !D->defaultedMoveConstructorIsDeleted()) {
>>>>>>>> +    if (!D->hasTrivialMoveConstructor())
>>>>>>>> +      return false;
>>>>>>>> +    HasNonDeletedCopyOrMove = true;
>>>>>>>> +  }
>>>>>>>> +
>>>>>>>> +  if (D->needsImplicitDestructor() &&
>>>>>>>> !D->defaultedDestructorIsDeleted()
>>>>>>>> &&
>>>>>>>> +      !D->hasTrivialDestructor())
>>>>>>>> +    return false;
>>>>>>>> +
>>>>>>>> +  for (const CXXMethodDecl *MD : D->methods()) {
>>>>>>>> +    if (MD->isDeleted())
>>>>>>>> +      continue;
>>>>>>>> +
>>>>>>>> +    auto *CD = dyn_cast<CXXConstructorDecl>(MD);
>>>>>>>> +    if (CD && CD->isCopyOrMoveConstructor())
>>>>>>>> +      HasNonDeletedCopyOrMove = true;
>>>>>>>> +    else if (!isa<CXXDestructorDecl>(MD))
>>>>>>>> +      continue;
>>>>>>>> +
>>>>>>>> +    if (!MD->isTrivial())
>>>>>>>> +      return false;
>>>>>>>> +  }
>>>>>>>> +
>>>>>>>> +  return HasNonDeletedCopyOrMove;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>>     /// \brief Perform semantic checks on a class definition that has
>>>>>>>> been
>>>>>>>>     /// completing, introducing implicitly-declared members, checking
>>>>>>>> for
>>>>>>>>     /// abstract types, etc.
>>>>>>>> @@ -5870,6 +5917,8 @@ void Sema::CheckCompletedCXXClass(CXXRec
>>>>>>>>       }
>>>>>>>>
>>>>>>>>       checkClassLevelDLLAttribute(Record);
>>>>>>>> +
>>>>>>>> +  Record->setCanPassInRegisters(computeCanPassInRegisters(*this,
>>>>>>>> Record));
>>>>>>>>     }
>>>>>>>>
>>>>>>>>     /// Look up the special member function that would be called by a
>>>>>>>> special
>>>>>>>> @@ -7496,8 +7545,7 @@ void Sema::ActOnFinishCXXMemberSpecifica
>>>>>>>>
>>>>>>>> reinterpret_cast<Decl**>(FieldCollector->getCurFields()),
>>>>>>>>                   FieldCollector->getCurNumFields()), LBrac, RBrac,
>>>>>>>> AttrList);
>>>>>>>>
>>>>>>>> -  CheckCompletedCXXClass(
>>>>>>>> -                        dyn_cast_or_null<CXXRecordDecl>(TagDecl));
>>>>>>>> +  CheckCompletedCXXClass(dyn_cast_or_null<CXXRecordDecl>(TagDecl));
>>>>>>>>     }
>>>>>>>>
>>>>>>>>     /// AddImplicitlyDeclaredMembersToClass - Adds any
>>>>>>>> implicitly-declared
>>>>>>>> @@ -11929,8 +11977,10 @@ CXXConstructorDecl *Sema::DeclareImplici
>>>>>>>>       Scope *S = getScopeForContext(ClassDecl);
>>>>>>>>       CheckImplicitSpecialMemberDeclaration(S, CopyConstructor);
>>>>>>>>
>>>>>>>> -  if (ShouldDeleteSpecialMember(CopyConstructor,
>>>>>>>> CXXCopyConstructor))
>>>>>>>> +  if (ShouldDeleteSpecialMember(CopyConstructor,
>>>>>>>> CXXCopyConstructor)) {
>>>>>>>> +    ClassDecl->setImplicitCopyConstructorIsDeleted();
>>>>>>>>         SetDeclDeleted(CopyConstructor, ClassLoc);
>>>>>>>> +  }
>>>>>>>>
>>>>>>>>       if (S)
>>>>>>>>         PushOnScopeChains(CopyConstructor, S, false);
>>>>>>>>
>>>>>>>> Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
>>>>>>>> URL:
>>>>>>>>
>>>>>>>>
>>>>>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=310401&r1=310400&r2=310401&view=diff
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
>>>>>>>> +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Aug  8 12:12:28
>>>>>>>> 2017
>>>>>>>> @@ -1559,9 +1559,11 @@ void ASTDeclReader::ReadCXXDefinitionDat
>>>>>>>>       Data.HasUninitializedFields = Record.readInt();
>>>>>>>>       Data.HasInheritedConstructor = Record.readInt();
>>>>>>>>       Data.HasInheritedAssignment = Record.readInt();
>>>>>>>> +  Data.NeedOverloadResolutionForCopyConstructor = Record.readInt();
>>>>>>>>       Data.NeedOverloadResolutionForMoveConstructor =
>>>>>>>> Record.readInt();
>>>>>>>>       Data.NeedOverloadResolutionForMoveAssignment = Record.readInt();
>>>>>>>>       Data.NeedOverloadResolutionForDestructor = Record.readInt();
>>>>>>>> +  Data.DefaultedCopyConstructorIsDeleted = Record.readInt();
>>>>>>>>       Data.DefaultedMoveConstructorIsDeleted = Record.readInt();
>>>>>>>>       Data.DefaultedMoveAssignmentIsDeleted = Record.readInt();
>>>>>>>>       Data.DefaultedDestructorIsDeleted = Record.readInt();
>>>>>>>> @@ -1570,6 +1572,7 @@ void ASTDeclReader::ReadCXXDefinitionDat
>>>>>>>>       Data.HasIrrelevantDestructor = Record.readInt();
>>>>>>>>       Data.HasConstexprNonCopyMoveConstructor = Record.readInt();
>>>>>>>>       Data.HasDefaultedDefaultConstructor = Record.readInt();
>>>>>>>> +  Data.CanPassInRegisters = Record.readInt();
>>>>>>>>       Data.DefaultedDefaultConstructorIsConstexpr = Record.readInt();
>>>>>>>>       Data.HasConstexprDefaultConstructor = Record.readInt();
>>>>>>>>       Data.HasNonLiteralTypeFieldsOrBases = Record.readInt();
>>>>>>>> @@ -1697,9 +1700,11 @@ void ASTDeclReader::MergeDefinitionData(
>>>>>>>>       MATCH_FIELD(HasUninitializedFields)
>>>>>>>>       MATCH_FIELD(HasInheritedConstructor)
>>>>>>>>       MATCH_FIELD(HasInheritedAssignment)
>>>>>>>> +  MATCH_FIELD(NeedOverloadResolutionForCopyConstructor)
>>>>>>>>       MATCH_FIELD(NeedOverloadResolutionForMoveConstructor)
>>>>>>>>       MATCH_FIELD(NeedOverloadResolutionForMoveAssignment)
>>>>>>>>       MATCH_FIELD(NeedOverloadResolutionForDestructor)
>>>>>>>> +  MATCH_FIELD(DefaultedCopyConstructorIsDeleted)
>>>>>>>>       MATCH_FIELD(DefaultedMoveConstructorIsDeleted)
>>>>>>>>       MATCH_FIELD(DefaultedMoveAssignmentIsDeleted)
>>>>>>>>       MATCH_FIELD(DefaultedDestructorIsDeleted)
>>>>>>>> @@ -1708,6 +1713,7 @@ void ASTDeclReader::MergeDefinitionData(
>>>>>>>>       MATCH_FIELD(HasIrrelevantDestructor)
>>>>>>>>       OR_FIELD(HasConstexprNonCopyMoveConstructor)
>>>>>>>>       OR_FIELD(HasDefaultedDefaultConstructor)
>>>>>>>> +  MATCH_FIELD(CanPassInRegisters)
>>>>>>>>       MATCH_FIELD(DefaultedDefaultConstructorIsConstexpr)
>>>>>>>>       OR_FIELD(HasConstexprDefaultConstructor)
>>>>>>>>       MATCH_FIELD(HasNonLiteralTypeFieldsOrBases)
>>>>>>>>
>>>>>>>> Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
>>>>>>>> URL:
>>>>>>>>
>>>>>>>>
>>>>>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=310401&r1=310400&r2=310401&view=diff
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
>>>>>>>> +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Aug  8 12:12:28
>>>>>>>> 2017
>>>>>>>> @@ -5875,9 +5875,11 @@ void ASTRecordWriter::AddCXXDefinitionDa
>>>>>>>>       Record->push_back(Data.HasUninitializedFields);
>>>>>>>>       Record->push_back(Data.HasInheritedConstructor);
>>>>>>>>       Record->push_back(Data.HasInheritedAssignment);
>>>>>>>> +  Record->push_back(Data.NeedOverloadResolutionForCopyConstructor);
>>>>>>>>
>>>>>>>> Record->push_back(Data.NeedOverloadResolutionForMoveConstructor);
>>>>>>>>       Record->push_back(Data.NeedOverloadResolutionForMoveAssignment);
>>>>>>>>       Record->push_back(Data.NeedOverloadResolutionForDestructor);
>>>>>>>> +  Record->push_back(Data.DefaultedCopyConstructorIsDeleted);
>>>>>>>>       Record->push_back(Data.DefaultedMoveConstructorIsDeleted);
>>>>>>>>       Record->push_back(Data.DefaultedMoveAssignmentIsDeleted);
>>>>>>>>       Record->push_back(Data.DefaultedDestructorIsDeleted);
>>>>>>>> @@ -5886,6 +5888,7 @@ void ASTRecordWriter::AddCXXDefinitionDa
>>>>>>>>       Record->push_back(Data.HasIrrelevantDestructor);
>>>>>>>>       Record->push_back(Data.HasConstexprNonCopyMoveConstructor);
>>>>>>>>       Record->push_back(Data.HasDefaultedDefaultConstructor);
>>>>>>>> +  Record->push_back(Data.CanPassInRegisters);
>>>>>>>>       Record->push_back(Data.DefaultedDefaultConstructorIsConstexpr);
>>>>>>>>       Record->push_back(Data.HasConstexprDefaultConstructor);
>>>>>>>>       Record->push_back(Data.HasNonLiteralTypeFieldsOrBases);
>>>>>>>>
>>>>>>>> Modified: cfe/trunk/test/CodeGenCXX/uncopyable-args.cpp
>>>>>>>> URL:
>>>>>>>>
>>>>>>>>
>>>>>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/uncopyable-args.cpp?rev=310401&r1=310400&r2=310401&view=diff
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- cfe/trunk/test/CodeGenCXX/uncopyable-args.cpp (original)
>>>>>>>> +++ cfe/trunk/test/CodeGenCXX/uncopyable-args.cpp Tue Aug  8 12:12:28
>>>>>>>> 2017
>>>>>>>> @@ -1,5 +1,6 @@
>>>>>>>>     // RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown
>>>>>>>> -emit-llvm
>>>>>>>> -o - %s | FileCheck %s
>>>>>>>> -// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm
>>>>>>>> -o
>>>>>>>> -
>>>>>>>> %s | FileCheck %s -check-prefix=WIN64
>>>>>>>> +// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm
>>>>>>>> -o
>>>>>>>> -
>>>>>>>> %s -fms-compatibility -fms-compatibility-version=18 | FileCheck %s
>>>>>>>> -check-prefix=WIN64 -check-prefix=WIN64-18
>>>>>>>> +// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm
>>>>>>>> -o
>>>>>>>> -
>>>>>>>> %s -fms-compatibility -fms-compatibility-version=19 | FileCheck %s
>>>>>>>> -check-prefix=WIN64 -check-prefix=WIN64-19
>>>>>>>>
>>>>>>>>     namespace trivial {
>>>>>>>>     // Trivial structs should be passed directly.
>>>>>>>> @@ -52,12 +53,11 @@ void foo(A);
>>>>>>>>     void bar() {
>>>>>>>>       foo({});
>>>>>>>>     }
>>>>>>>> -// FIXME: The copy ctor is implicitly deleted.
>>>>>>>> -// CHECK-DISABLED-LABEL: define void @_ZN9move_ctor3barEv()
>>>>>>>> -// CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
>>>>>>>> -// CHECK-DISABLED-NOT: call
>>>>>>>> -// CHECK-DISABLED: call void
>>>>>>>> @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"* %{{.*}})
>>>>>>>> -// CHECK-DISABLED-LABEL: declare void
>>>>>>>> @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"*)
>>>>>>>> +// CHECK-LABEL: define void @_ZN9move_ctor3barEv()
>>>>>>>> +// CHECK: call void @_Z{{.*}}C1Ev(
>>>>>>>> +// CHECK-NOT: call
>>>>>>>> +// CHECK: call void
>>>>>>>> @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"*
>>>>>>>> %{{.*}})
>>>>>>>> +// CHECK-LABEL: declare void
>>>>>>>> @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"*)
>>>>>>>>
>>>>>>>>     // WIN64-LABEL: declare void
>>>>>>>> @"\01?foo at move_ctor@@YAXUA at 1@@Z"(%"struct.move_ctor::A"*)
>>>>>>>>     }
>>>>>>>> @@ -73,12 +73,11 @@ void foo(A);
>>>>>>>>     void bar() {
>>>>>>>>       foo({});
>>>>>>>>     }
>>>>>>>> -// FIXME: The copy ctor is deleted.
>>>>>>>> -// CHECK-DISABLED-LABEL: define void @_ZN11all_deleted3barEv()
>>>>>>>> -// CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
>>>>>>>> -// CHECK-DISABLED-NOT: call
>>>>>>>> -// CHECK-DISABLED: call void
>>>>>>>> @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"* %{{.*}})
>>>>>>>> -// CHECK-DISABLED-LABEL: declare void
>>>>>>>> @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"*)
>>>>>>>> +// CHECK-LABEL: define void @_ZN11all_deleted3barEv()
>>>>>>>> +// CHECK: call void @_Z{{.*}}C1Ev(
>>>>>>>> +// CHECK-NOT: call
>>>>>>>> +// CHECK: call void
>>>>>>>> @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"* %{{.*}})
>>>>>>>> +// CHECK-LABEL: declare void
>>>>>>>> @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"*)
>>>>>>>>
>>>>>>>>     // WIN64-LABEL: declare void
>>>>>>>> @"\01?foo at all_deleted@@YAXUA at 1@@Z"(%"struct.all_deleted::A"*)
>>>>>>>>     }
>>>>>>>> @@ -93,14 +92,15 @@ void foo(A);
>>>>>>>>     void bar() {
>>>>>>>>       foo({});
>>>>>>>>     }
>>>>>>>> -// FIXME: The copy and move ctors are implicitly deleted.
>>>>>>>> -// CHECK-DISABLED-LABEL: define void
>>>>>>>> @_ZN18implicitly_deleted3barEv()
>>>>>>>> -// CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
>>>>>>>> -// CHECK-DISABLED-NOT: call
>>>>>>>> -// CHECK-DISABLED: call void
>>>>>>>> @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"*
>>>>>>>> %{{.*}})
>>>>>>>> -// CHECK-DISABLED-LABEL: declare void
>>>>>>>> @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"*)
>>>>>>>> -
>>>>>>>> -// WIN64-LABEL: declare void
>>>>>>>>
>>>>>>>>
>>>>>>>> @"\01?foo at implicitly_deleted@@YAXUA at 1@@Z"(%"struct.implicitly_deleted::A"*)
>>>>>>>> +// CHECK-LABEL: define void @_ZN18implicitly_deleted3barEv()
>>>>>>>> +// CHECK: call void @_Z{{.*}}C1Ev(
>>>>>>>> +// CHECK-NOT: call
>>>>>>>> +// CHECK: call void
>>>>>>>> @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"*
>>>>>>>> %{{.*}})
>>>>>>>> +// CHECK-LABEL: declare void
>>>>>>>> @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"*)
>>>>>>>> +
>>>>>>>> +// In MSVC 2013, the copy ctor is not deleted by a move assignment.
>>>>>>>> In
>>>>>>>> MSVC 2015, it is.
>>>>>>>> +// WIN64-18-LABEL: declare void
>>>>>>>> @"\01?foo at implicitly_deleted@@YAXUA at 1@@Z"(i64
>>>>>>>> +// WIN64-19-LABEL: declare void
>>>>>>>>
>>>>>>>>
>>>>>>>> @"\01?foo at implicitly_deleted@@YAXUA at 1@@Z"(%"struct.implicitly_deleted::A"*)
>>>>>>>>     }
>>>>>>>>
>>>>>>>>     namespace one_deleted {
>>>>>>>> @@ -113,12 +113,11 @@ void foo(A);
>>>>>>>>     void bar() {
>>>>>>>>       foo({});
>>>>>>>>     }
>>>>>>>> -// FIXME: The copy constructor is implicitly deleted.
>>>>>>>> -// CHECK-DISABLED-LABEL: define void @_ZN11one_deleted3barEv()
>>>>>>>> -// CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
>>>>>>>> -// CHECK-DISABLED-NOT: call
>>>>>>>> -// CHECK-DISABLED: call void
>>>>>>>> @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"* %{{.*}})
>>>>>>>> -// CHECK-DISABLED-LABEL: declare void
>>>>>>>> @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"*)
>>>>>>>> +// CHECK-LABEL: define void @_ZN11one_deleted3barEv()
>>>>>>>> +// CHECK: call void @_Z{{.*}}C1Ev(
>>>>>>>> +// CHECK-NOT: call
>>>>>>>> +// CHECK: call void
>>>>>>>> @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"* %{{.*}})
>>>>>>>> +// CHECK-LABEL: declare void
>>>>>>>> @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"*)
>>>>>>>>
>>>>>>>>     // WIN64-LABEL: declare void
>>>>>>>> @"\01?foo at one_deleted@@YAXUA at 1@@Z"(%"struct.one_deleted::A"*)
>>>>>>>>     }
>>>>>>>> @@ -195,12 +194,10 @@ void foo(B);
>>>>>>>>     void bar() {
>>>>>>>>       foo({});
>>>>>>>>     }
>>>>>>>> -// FIXME: This class has a non-trivial copy ctor and a trivial copy
>>>>>>>> ctor.
>>>>>>>> It's
>>>>>>>> -// not clear whether we should pass by address or in registers.
>>>>>>>> -// CHECK-DISABLED-LABEL: define void @_ZN14two_copy_ctors3barEv()
>>>>>>>> -// CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
>>>>>>>> -// CHECK-DISABLED: call void
>>>>>>>> @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"* %{{.*}})
>>>>>>>> -// CHECK-DISABLED-LABEL: declare void
>>>>>>>> @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"*)
>>>>>>>> +// CHECK-LABEL: define void @_ZN14two_copy_ctors3barEv()
>>>>>>>> +// CHECK: call void @_Z{{.*}}C1Ev(
>>>>>>>> +// CHECK: call void
>>>>>>>> @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"* %{{.*}})
>>>>>>>> +// CHECK-LABEL: declare void
>>>>>>>> @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"*)
>>>>>>>>
>>>>>>>>     // WIN64-LABEL: declare void
>>>>>>>> @"\01?foo at two_copy_ctors@@YAXUB at 1@@Z"(%"struct.two_copy_ctors::B"*)
>>>>>>>>     }
>>>>>>>> @@ -212,6 +209,7 @@ struct A {
>>>>>>>>       void *p;
>>>>>>>>     };
>>>>>>>>     void *foo(A a) { return a.p; }
>>>>>>>> +// CHECK-LABEL: define i8*
>>>>>>>> @_ZN15definition_only3fooENS_1AE(%"struct.definition_only::A"*
>>>>>>>>     // WIN64-LABEL: define i8*
>>>>>>>>
>>>>>>>> @"\01?foo at definition_only@@YAPEAXUA at 1@@Z"(%"struct.definition_only::A"*
>>>>>>>>     }
>>>>>>>>
>>>>>>>> @@ -226,6 +224,7 @@ struct A {
>>>>>>>>       B b;
>>>>>>>>     };
>>>>>>>>     void *foo(A a) { return a.b.p; }
>>>>>>>> +// CHECK-LABEL: define i8*
>>>>>>>> @_ZN17deleted_by_member3fooENS_1AE(%"struct.deleted_by_member::A"*
>>>>>>>>     // WIN64-LABEL: define i8*
>>>>>>>>
>>>>>>>>
>>>>>>>> @"\01?foo at deleted_by_member@@YAPEAXUA at 1@@Z"(%"struct.deleted_by_member::A"*
>>>>>>>>     }
>>>>>>>>
>>>>>>>> @@ -239,6 +238,7 @@ struct A : B {
>>>>>>>>       A();
>>>>>>>>     };
>>>>>>>>     void *foo(A a) { return a.p; }
>>>>>>>> +// CHECK-LABEL: define i8*
>>>>>>>> @_ZN15deleted_by_base3fooENS_1AE(%"struct.deleted_by_base::A"*
>>>>>>>>     // WIN64-LABEL: define i8*
>>>>>>>>
>>>>>>>> @"\01?foo at deleted_by_base@@YAPEAXUA at 1@@Z"(%"struct.deleted_by_base::A"*
>>>>>>>>     }
>>>>>>>>
>>>>>>>> @@ -253,6 +253,7 @@ struct A {
>>>>>>>>       B b;
>>>>>>>>     };
>>>>>>>>     void *foo(A a) { return a.b.p; }
>>>>>>>> +// CHECK-LABEL: define i8*
>>>>>>>>
>>>>>>>>
>>>>>>>> @_ZN22deleted_by_member_copy3fooENS_1AE(%"struct.deleted_by_member_copy::A"*
>>>>>>>>     // WIN64-LABEL: define i8*
>>>>>>>>
>>>>>>>>
>>>>>>>> @"\01?foo at deleted_by_member_copy@@YAPEAXUA at 1@@Z"(%"struct.deleted_by_member_copy::A"*
>>>>>>>>     }
>>>>>>>>
>>>>>>>> @@ -266,6 +267,7 @@ struct A : B {
>>>>>>>>       A();
>>>>>>>>     };
>>>>>>>>     void *foo(A a) { return a.p; }
>>>>>>>> +// CHECK-LABEL: define i8*
>>>>>>>>
>>>>>>>> @_ZN20deleted_by_base_copy3fooENS_1AE(%"struct.deleted_by_base_copy::A"*
>>>>>>>>     // WIN64-LABEL: define i8*
>>>>>>>>
>>>>>>>>
>>>>>>>> @"\01?foo at deleted_by_base_copy@@YAPEAXUA at 1@@Z"(%"struct.deleted_by_base_copy::A"*
>>>>>>>>     }
>>>>>>>>
>>>>>>>> @@ -275,6 +277,75 @@ struct A {
>>>>>>>>       A(const A &o) = delete;
>>>>>>>>       void *p;
>>>>>>>>     };
>>>>>>>> +// CHECK-LABEL: define i8*
>>>>>>>> @_ZN15explicit_delete3fooENS_1AE(%"struct.explicit_delete::A"*
>>>>>>>>     // WIN64-LABEL: define i8*
>>>>>>>>
>>>>>>>> @"\01?foo at explicit_delete@@YAPEAXUA at 1@@Z"(%"struct.explicit_delete::A"*
>>>>>>>>     void *foo(A a) { return a.p; }
>>>>>>>>     }
>>>>>>>> +
>>>>>>>> +namespace implicitly_deleted_copy_ctor {
>>>>>>>> +struct A {
>>>>>>>> +  // No move ctor due to copy assignment.
>>>>>>>> +  A &operator=(const A&);
>>>>>>>> +  // Deleted copy ctor due to rvalue ref member.
>>>>>>>> +  int &&ref;
>>>>>>>> +};
>>>>>>>> +// CHECK-LABEL: define {{.*}}
>>>>>>>>
>>>>>>>>
>>>>>>>> @_ZN28implicitly_deleted_copy_ctor3fooENS_1AE(%"struct.implicitly_deleted_copy_ctor::A"*
>>>>>>>> +// WIN64-LABEL: define {{.*}}
>>>>>>>>
>>>>>>>>
>>>>>>>> @"\01?foo at implicitly_deleted_copy_ctor@@YAAEAHUA at 1@@Z"(%"struct.implicitly_deleted_copy_ctor::A"*
>>>>>>>> +int &foo(A a) { return a.ref; }
>>>>>>>> +
>>>>>>>> +struct B {
>>>>>>>> +  // Passed direct: has non-deleted trivial copy ctor.
>>>>>>>> +  B &operator=(const B&);
>>>>>>>> +  int &ref;
>>>>>>>> +};
>>>>>>>> +int &foo(B b) { return b.ref; }
>>>>>>>> +// CHECK-LABEL: define {{.*}}
>>>>>>>> @_ZN28implicitly_deleted_copy_ctor3fooENS_1BE(i32*
>>>>>>>> +// WIN64-LABEL: define {{.*}}
>>>>>>>> @"\01?foo at implicitly_deleted_copy_ctor@@YAAEAHUB at 1@@Z"(i64
>>>>>>>> +
>>>>>>>> +struct X { X(const X&); };
>>>>>>>> +struct Y { Y(const Y&) = default; };
>>>>>>>> +
>>>>>>>> +union C {
>>>>>>>> +  C &operator=(const C&);
>>>>>>>> +  // Passed indirect: copy ctor deleted due to variant member with
>>>>>>>> nontrivial copy ctor.
>>>>>>>> +  X x;
>>>>>>>> +  int n;
>>>>>>>> +};
>>>>>>>> +int foo(C c) { return c.n; }
>>>>>>>> +// CHECK-LABEL: define {{.*}}
>>>>>>>>
>>>>>>>>
>>>>>>>> @_ZN28implicitly_deleted_copy_ctor3fooENS_1CE(%"union.implicitly_deleted_copy_ctor::C"*
>>>>>>>> +// WIN64-LABEL: define {{.*}}
>>>>>>>>
>>>>>>>>
>>>>>>>> @"\01?foo at implicitly_deleted_copy_ctor@@YAHTC at 1@@Z"(%"union.implicitly_deleted_copy_ctor::C"*
>>>>>>>> +
>>>>>>>> +struct D {
>>>>>>>> +  D &operator=(const D&);
>>>>>>>> +  // Passed indirect: copy ctor deleted due to variant member with
>>>>>>>> nontrivial copy ctor.
>>>>>>>> +  union {
>>>>>>>> +    X x;
>>>>>>>> +    int n;
>>>>>>>> +  };
>>>>>>>> +};
>>>>>>>> +int foo(D d) { return d.n; }
>>>>>>>> +// CHECK-LABEL: define {{.*}}
>>>>>>>>
>>>>>>>>
>>>>>>>> @_ZN28implicitly_deleted_copy_ctor3fooENS_1DE(%"struct.implicitly_deleted_copy_ctor::D"*
>>>>>>>> +// WIN64-LABEL: define {{.*}}
>>>>>>>>
>>>>>>>>
>>>>>>>> @"\01?foo at implicitly_deleted_copy_ctor@@YAHUD at 1@@Z"(%"struct.implicitly_deleted_copy_ctor::D"*
>>>>>>>> +
>>>>>>>> +union E {
>>>>>>>> +  // Passed direct: has non-deleted trivial copy ctor.
>>>>>>>> +  E &operator=(const E&);
>>>>>>>> +  Y y;
>>>>>>>> +  int n;
>>>>>>>> +};
>>>>>>>> +int foo(E e) { return e.n; }
>>>>>>>> +// CHECK-LABEL: define {{.*}}
>>>>>>>> @_ZN28implicitly_deleted_copy_ctor3fooENS_1EE(i32
>>>>>>>> +// WIN64-LABEL: define {{.*}}
>>>>>>>> @"\01?foo at implicitly_deleted_copy_ctor@@YAHTE at 1@@Z"(i32
>>>>>>>> +
>>>>>>>> +struct F {
>>>>>>>> +  // Passed direct: has non-deleted trivial copy ctor.
>>>>>>>> +  F &operator=(const F&);
>>>>>>>> +  union {
>>>>>>>> +    Y y;
>>>>>>>> +    int n;
>>>>>>>> +  };
>>>>>>>> +};
>>>>>>>> +int foo(F f) { return f.n; }
>>>>>>>> +// CHECK-LABEL: define {{.*}}
>>>>>>>> @_ZN28implicitly_deleted_copy_ctor3fooENS_1FE(i32
>>>>>>>> +// WIN64-LABEL: define {{.*}}
>>>>>>>> @"\01?foo at implicitly_deleted_copy_ctor@@YAHUF at 1@@Z"(i32
>>>>>>>> +}
>>>>>>>>
>>>>>>>> Modified:
>>>>>>>> cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
>>>>>>>> URL:
>>>>>>>>
>>>>>>>>
>>>>>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp?rev=310401&r1=310400&r2=310401&view=diff
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
>>>>>>>> (original)
>>>>>>>> +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp Tue
>>>>>>>> Aug
>>>>>>>> 8 12:12:28 2017
>>>>>>>> @@ -1108,26 +1108,35 @@ TEST(ConstructorDeclaration, IsExplicit)
>>>>>>>>     }
>>>>>>>>
>>>>>>>>     TEST(ConstructorDeclaration, Kinds) {
>>>>>>>> -  EXPECT_TRUE(matches("struct S { S(); };",
>>>>>>>> -                      cxxConstructorDecl(isDefaultConstructor())));
>>>>>>>> -  EXPECT_TRUE(notMatches("struct S { S(); };",
>>>>>>>> -                         cxxConstructorDecl(isCopyConstructor())));
>>>>>>>> -  EXPECT_TRUE(notMatches("struct S { S(); };",
>>>>>>>> -                         cxxConstructorDecl(isMoveConstructor())));
>>>>>>>> +  EXPECT_TRUE(matches(
>>>>>>>> +      "struct S { S(); };",
>>>>>>>> +      cxxConstructorDecl(isDefaultConstructor(),
>>>>>>>> unless(isImplicit()))));
>>>>>>>> +  EXPECT_TRUE(notMatches(
>>>>>>>> +      "struct S { S(); };",
>>>>>>>> +      cxxConstructorDecl(isCopyConstructor(),
>>>>>>>> unless(isImplicit()))));
>>>>>>>> +  EXPECT_TRUE(notMatches(
>>>>>>>> +      "struct S { S(); };",
>>>>>>>> +      cxxConstructorDecl(isMoveConstructor(),
>>>>>>>> unless(isImplicit()))));
>>>>>>>>
>>>>>>>> -  EXPECT_TRUE(notMatches("struct S { S(const S&); };",
>>>>>>>> -
>>>>>>>> cxxConstructorDecl(isDefaultConstructor())));
>>>>>>>> -  EXPECT_TRUE(matches("struct S { S(const S&); };",
>>>>>>>> -                      cxxConstructorDecl(isCopyConstructor())));
>>>>>>>> -  EXPECT_TRUE(notMatches("struct S { S(const S&); };",
>>>>>>>> -                         cxxConstructorDecl(isMoveConstructor())));
>>>>>>>> +  EXPECT_TRUE(notMatches(
>>>>>>>> +      "struct S { S(const S&); };",
>>>>>>>> +      cxxConstructorDecl(isDefaultConstructor(),
>>>>>>>> unless(isImplicit()))));
>>>>>>>> +  EXPECT_TRUE(matches(
>>>>>>>> +      "struct S { S(const S&); };",
>>>>>>>> +      cxxConstructorDecl(isCopyConstructor(),
>>>>>>>> unless(isImplicit()))));
>>>>>>>> +  EXPECT_TRUE(notMatches(
>>>>>>>> +      "struct S { S(const S&); };",
>>>>>>>> +      cxxConstructorDecl(isMoveConstructor(),
>>>>>>>> unless(isImplicit()))));
>>>>>>>>
>>>>>>>> -  EXPECT_TRUE(notMatches("struct S { S(S&&); };",
>>>>>>>> -
>>>>>>>> cxxConstructorDecl(isDefaultConstructor())));
>>>>>>>> -  EXPECT_TRUE(notMatches("struct S { S(S&&); };",
>>>>>>>> -                         cxxConstructorDecl(isCopyConstructor())));
>>>>>>>> -  EXPECT_TRUE(matches("struct S { S(S&&); };",
>>>>>>>> -                      cxxConstructorDecl(isMoveConstructor())));
>>>>>>>> +  EXPECT_TRUE(notMatches(
>>>>>>>> +      "struct S { S(S&&); };",
>>>>>>>> +      cxxConstructorDecl(isDefaultConstructor(),
>>>>>>>> unless(isImplicit()))));
>>>>>>>> +  EXPECT_TRUE(notMatches(
>>>>>>>> +      "struct S { S(S&&); };",
>>>>>>>> +      cxxConstructorDecl(isCopyConstructor(),
>>>>>>>> unless(isImplicit()))));
>>>>>>>> +  EXPECT_TRUE(matches(
>>>>>>>> +      "struct S { S(S&&); };",
>>>>>>>> +      cxxConstructorDecl(isMoveConstructor(),
>>>>>>>> unless(isImplicit()))));
>>>>>>>>     }
>>>>>>>>
>>>>>>>>     TEST(ConstructorDeclaration, IsUserProvided) {
>>>>>>>>
>>>>>>>>
>>>>>>>> _______________________________________________
>>>>>>>> cfe-commits mailing list
>>>>>>>> cfe-commits at lists.llvm.org
>>>>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>>>>>>
>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> cfe-commits mailing list
>>>>>>> cfe-commits at lists.llvm.org
>>>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>>>>>>
>>>>>> _______________________________________________
>>>>>> cfe-commits mailing list
>>>>>> cfe-commits at lists.llvm.org
>>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>>>>
>>>>>



More information about the cfe-commits mailing list