r287600 - Sema, CodeGen: Ensure that an implicit copy ctor is available more often under the Microsoft C++ ABI.

Peter Collingbourne via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 21 16:21:45 PST 2016


Author: pcc
Date: Mon Nov 21 18:21:43 2016
New Revision: 287600

URL: http://llvm.org/viewvc/llvm-project?rev=287600&view=rev
Log:
Sema, CodeGen: Ensure that an implicit copy ctor is available more often under the Microsoft C++ ABI.

This is needed because whether the constructor is deleted can control whether
we pass structs by value directly.

To fix this properly we probably want a more direct way for CodeGen to ask
whether the constructor was deleted.

Fixes PR31049.

Differential Revision: https://reviews.llvm.org/D26822

Modified:
    cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CodeGenCXX/uncopyable-args.cpp

Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=287600&r1=287599&r2=287600&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Mon Nov 21 18:21:43 2016
@@ -830,25 +830,32 @@ MicrosoftCXXABI::getRecordArgABI(const C
         getContext().getTypeSize(RD->getTypeForDecl()) > 64)
       return RAA_Indirect;
 
-    // We have a trivial copy constructor or no copy constructors, but we have
-    // to make sure it isn't deleted.
-    bool CopyDeleted = false;
+    // 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;
-        CopyDeleted = true;
       }
     }
 
     // The trivial copy constructor was deleted.  Return indirectly.
-    if (CopyDeleted)
-      return RAA_Indirect;
-
-    // There were no copy ctors.  Return in RAX.
-    return RAA_Default;
+    return RAA_Indirect;
   }
 
   llvm_unreachable("invalid enum");

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=287600&r1=287599&r2=287600&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Nov 21 18:21:43 2016
@@ -7396,6 +7396,17 @@ void Sema::AddImplicitlyDeclaredMembersT
     if (ClassDecl->needsOverloadResolutionForCopyConstructor() ||
         ClassDecl->hasInheritedConstructor())
       DeclareImplicitCopyConstructor(ClassDecl);
+    // For the MS ABI we need to know whether the copy ctor is deleted. A
+    // prerequisite for deleting the implicit copy ctor is that the class has a
+    // move ctor or move assignment that is either user-declared or whose
+    // semantics are inherited from a subobject. FIXME: We should provide a more
+    // direct way for CodeGen to ask whether the constructor was deleted.
+    else if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+             (ClassDecl->hasUserDeclaredMoveConstructor() ||
+              ClassDecl->needsOverloadResolutionForMoveConstructor() ||
+              ClassDecl->hasUserDeclaredMoveAssignment() ||
+              ClassDecl->needsOverloadResolutionForMoveAssignment()))
+      DeclareImplicitCopyConstructor(ClassDecl);
   }
 
   if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveConstructor()) {

Modified: cfe/trunk/test/CodeGenCXX/uncopyable-args.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/uncopyable-args.cpp?rev=287600&r1=287599&r2=287600&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/uncopyable-args.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/uncopyable-args.cpp Mon Nov 21 18:21:43 2016
@@ -204,3 +204,64 @@ void bar() {
 
 // WIN64-LABEL: declare void @"\01?foo at two_copy_ctors@@YAXUB at 1@@Z"(%"struct.two_copy_ctors::B"*)
 }
+
+namespace definition_only {
+struct A {
+  A();
+  A(A &&o);
+  void *p;
+};
+void *foo(A a) { return a.p; }
+// WIN64-LABEL: define i8* @"\01?foo at definition_only@@YAPEAXUA at 1@@Z"{{.*}}
+// WIN64-NEXT: :
+// WIN64-NEXT: getelementptr
+// WIN64-NEXT: load
+}
+
+namespace deleted_by_member {
+struct B {
+  B();
+  B(B &&o);
+  void *p;
+};
+struct A {
+  A();
+  B b;
+};
+void *foo(A a) { return a.b.p; }
+// WIN64-LABEL: define i8* @"\01?foo at deleted_by_member@@YAPEAXUA at 1@@Z"{{.*}}
+// WIN64-NEXT: :
+// WIN64-NEXT: getelementptr
+// WIN64-NEXT: getelementptr
+// WIN64-NEXT: load
+}
+
+namespace deleted_by_base {
+struct B {
+  B();
+  B(B &&o);
+  void *p;
+};
+struct A : B {
+  A();
+};
+void *foo(A a) { return a.p; }
+// WIN64-LABEL: define i8* @"\01?foo at deleted_by_base@@YAPEAXUA at 1@@Z"{{.*}}
+// WIN64-NEXT: :
+// WIN64-NEXT: bitcast
+// WIN64-NEXT: getelementptr
+// WIN64-NEXT: load
+}
+
+namespace explicit_delete {
+struct A {
+  A();
+  A(const A &o) = delete;
+  void *p;
+};
+// WIN64-LABEL: define i8* @"\01?foo at explicit_delete@@YAPEAXUA at 1@@Z"{{.*}}
+// WIN64-NEXT: :
+// WIN64-NEXT: getelementptr
+// WIN64-NEXT: load
+void *foo(A a) { return a.p; }
+}




More information about the cfe-commits mailing list