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

Diana Picus via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 10 01:28:55 PDT 2017


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