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

Diana Picus via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 14 03:27:54 PDT 2017


Hi,

Strangely enough, it turns out that if I run
Asan-armhf-with-calls-Noinst-Test on the command line it fails,
although it doesn't fail when run with lit. I've attached the stack
trace from gdb. It looks like some trouble passing down va_arg
parameters, but I haven't looked into too much details. The segfault
happens when we try to do a   ldrb   r3, [r0, r1], with r1 set to 0 by
the current function and r0 passed down from the caller. I'm not sure
if this is the exact same problem as the other tests, but feel free to
have a look at that code.

Meanwhile, I've removed some clutter from Asan-armhf-with-calls-Test
(which is the original failure that we were seeing) and left only one
failing test that seemed small enough. I'll try to look at the
disassembly before/after the patch and maybe even run valgrind on it
(running it on the original binary naturally takes forever).

Let me know if there's anything else I could try. I can also send you
disassembly or even LLVM IR for the Asan-armhf-with-calls-Noinst-Test
if you think it helps.

Cheers,
Diana

On 11 August 2017 at 15:34, Diana Picus <diana.picus at linaro.org> wrote:
> Well, these are ASAN tests, I'm not sure how that would interact with Valgrind.
> Anyway, I'll try to reproduce the environment, I'm guessing it would
> be best to catch this in gdb so I can actually see what's going on.
>
> On 11 August 2017 at 15:21, Vassil Vassilev <v.g.vassilev at gmail.com> wrote:
>> 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
>>>>>
>>>>>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: clang-arm-breakage.log
Type: text/x-log
Size: 2792 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170814/12d863c8/attachment-0001.bin>


More information about the cfe-commits mailing list