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