On 14/08/17 15:59, Diana Picus wrote:
No, the buildbots don't build with -O0 (at least not the ones that broke).

The command line for that particular object is:
build/./bin/clang -fPIC -fvisibility-inlines-hidden -Werror=date-time
-std=c++11 -Wall -W -Wno-unused-parameter -Wwrite-strings -Wcast-qual
-Wmissing-field-initializers -pedantic -Wno-long-long
-Wcovered-switch-default -Wnon-virtual-dtor -Wdelete-non-virtual-dtor
-Wstring-conversion -fcolor-diagnostics -ffunction-sections
-fdata-sections -Wall -std=c++11 -Wno-unused-parameter
-Wno-unknown-warning-option -Wno-covered-switch-default
-DGTEST_NO_LLVM_RAW_OSTREAM=1 -DGTEST_HAS_RTTI=0
-I$LLVM_SRC/llvm/utils/unittest/googletest/include
-I/home/diana.picus/linaro-scripts/bisect/llvm/utils/unittest/googletest
-I$LLVM_SRC/llvm/projects/compiler-rt/include
-I$LLVM_SRC/llvm/projects/compiler-rt/lib
-I$LLVM_SRC/llvm/projects/compiler-rt/lib/asan
-I$LLVM_SRC/llvm/projects/compiler-rt/lib/sanitizer_common/tests
-fno-rtti -O2 -Wno-format -Werror=sign-compare -Wno-non-virtual-dtor
-Wno-variadic-macros -gline-tables-only -DASAN_HAS_BLACKLIST=1
-DASAN_HAS_EXCEPTIONS=1 -DASAN_UAR=0 -fsanitize=address
-fsanitize-blacklist=$LLVM_SRC/llvm/projects/compiler-rt/lib/asan/tests/asan_test.ignore
-mllvm -asan-instrumentation-with-call-threshold=0 -march=armv7-a
-mfloat-abi=hard -c -o
ASAN_INST_TEST_OBJECTS.asan_test.cc.armhf-with-calls.o
$LLVM_SRC/compiler-rt/lib/asan/tests/asan_test.cc
Could you try to reproduce the issue with O0? This would rule out the optimizer. Could you resend the O0 ll file, maybe I could find something out. IIUC, the gtest version is 1.8.0?

Why would it contain gtest.cc? It seems to contain gtest.h and a bunch
of other internal gtest headers...


On 14 August 2017 at 16:51, Vassil Vassilev <v.g.vassi...@gmail.com> wrote:
On 14/08/17 15:08, Vassil Vassilev wrote:
On 14/08/17 13:04, Diana Picus wrote:
See attached.
Thanks! It looks like asan_test.i doesn't have gtest.cc which appears in
the stack trace. Am I missing something?
   Could you paste the compiler invocation. Are we building with -O0 (I see
quite a lot of things inline). Could it be an optimizer problem?

On 14 August 2017 at 13:30, Vassil Vassilev <v.g.vassi...@gmail.com>
wrote:
On 14/08/17 11:27, Diana Picus wrote:
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.
    disassembly and LLVM will greatly help as well.

Cheers,
Diana

On 11 August 2017 at 15:34, Diana Picus <diana.pi...@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.vassi...@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.pi...@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.pi...@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 <rich...@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@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.vassi...@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.pi...@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.vassi...@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@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@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@move_ctor@@YAXUA@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@all_deleted@@YAXUA@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@implicitly_deleted@@YAXUA@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@implicitly_deleted@@YAXUA@1@@Z"(i64
+// WIN64-19-LABEL: declare void





@"\01?foo@implicitly_deleted@@YAXUA@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@one_deleted@@YAXUA@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@two_copy_ctors@@YAXUB@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@definition_only@@YAPEAXUA@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@deleted_by_member@@YAPEAXUA@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@deleted_by_base@@YAPEAXUA@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@deleted_by_member_copy@@YAPEAXUA@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@deleted_by_base_copy@@YAPEAXUA@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@explicit_delete@@YAPEAXUA@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@implicitly_deleted_copy_ctor@@YAAEAHUA@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@implicitly_deleted_copy_ctor@@YAAEAHUB@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@implicitly_deleted_copy_ctor@@YAHTC@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@implicitly_deleted_copy_ctor@@YAHUD@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@implicitly_deleted_copy_ctor@@YAHTE@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@implicitly_deleted_copy_ctor@@YAHUF@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@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to