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

Vassil Vassilev via cfe-commits cfe-commits at lists.llvm.org
Fri Aug 11 06:21:47 PDT 2017


That's really strange. It looks like some random behavior. Did you run some memory checker like valgrind?

Do the environment provided by the test runner and yours match?

Sent from my phone. Please excuse my brevity.

> On 11 Aug 2017, at 15:58, Diana Picus <diana.picus at linaro.org> wrote:
> 
> Hi again,
> 
> I finally got the debug build, but unfortunately the stack traces that
> the tests print look the same. My suspicion is that this is because
> the addresses printed by the tests are funny (i.e. odd numbers instead
> of divisible by 4). I tried to follow those addresses in an objdump of
> the executable, but I didn't have much success since most of them
> weren't really pointing to call instructions.
> 
> When I try to run the tests manually in the shell or in gdb, they pass.
> 
> I'm not sure what else to try. Thoughts?
> 
> Thanks,
> Diana
> 
>> On 11 August 2017 at 11:14, Diana Picus <diana.picus at linaro.org> wrote:
>> Hi guys,
>> 
>> I'm SO sorry about the delays. I've been having all sorts of trouble
>> getting that debug build on the board (from ld running out of memory
>> to the board just crashing on me, in which case I need to ask someone
>> else to reboot it because I can't power cycle it remotely). I can
>> assure you this is one of my top priorities, I'll get those stack
>> traces as soon as I can.
>> 
>> Thanks for your patience and sorry again,
>> Diana
>> 
>>> On 10 August 2017 at 22:55, Richard Smith <richard at metafoo.co.uk> wrote:
>>> Any news on this? We want this change in Clang 5, so the sooner we can
>>> understand and fix this regression the better...
>>> 
>>> On 10 August 2017 at 01:28, Diana Picus via cfe-commits
>>> <cfe-commits at lists.llvm.org> 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
>>>>>>>> 
>>>>>>>> 
>>>>>>>> 
>>>>> 
>>>> _______________________________________________
>>>> 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