[PATCH] D35056: GCC ABI incompatibility when passing object with trivial copy ctor, trivial dtor, and non-trivial move ctor

Reid Kleckner via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 8 10:20:15 PDT 2017


rnk accepted this revision.
rnk added a comment.
This revision is now accepted and ready to land.

In https://reviews.llvm.org/D35056#834705, @rnk wrote:

> In https://reviews.llvm.org/D35056#834689, @rsmith wrote:
>
> > I also removed some incorrect assumptions from the Win64 ABI code; this changed the behavior of one testcase from uncopyable-args.cpp (`implicitly_deleted_copy_ctor::A` is now passed indirect).
>
>
> That's probably not correct, let me take a look... I remember breaking the rules for small types here.


Nevermind, everything looks good there. Thanks for untangling the mess. I only have comments on comments.



================
Comment at: include/clang/AST/DeclCXX.h:420
 
+    /// \brief True if this class has at least one non-deleted copy or move
+    /// constructor. That would allow passing it by registers.
----------------
Isn't this "... at least one *trivial*, non-deleted copy or move constructor..."?


================
Comment at: lib/CodeGen/MicrosoftCXXABI.cpp:836
 
-    // 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;
+    // Win64 passes objects with non-deleted, non-trivial copy ctors indirectly.
+    //
----------------
This doesn't seem to match what we've computing, and it doesn't seem quite right. MSVC will pass a class with deleted, trivial copy ctors indirectly. Would it be correct to rephrase like this?
"If RD has at least one trivial, non-deleted copy constructor, it is passed directly. Otherwise, it is passed indirectly."


================
Comment at: test/CodeGenCXX/uncopyable-args.cpp:101
+
+// 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
----------------
Oh dear. :(


Repository:
  rL LLVM

https://reviews.llvm.org/D35056





More information about the cfe-commits mailing list