Emit the constructor for abstract classes when using -cxx-abi microsoft, fixes PR16735
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@187709 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 6023bf7..0453b73 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -172,20 +172,6 @@
return false;
}
-void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) {
- // The constructor used for constructing this as a complete class;
- // constucts the virtual bases, then calls the base constructor.
- if (!D->getParent()->isAbstract()) {
- // We don't need to emit the complete ctor if the class is abstract.
- EmitGlobal(GlobalDecl(D, Ctor_Complete));
- }
-
- // The constructor used for constructing this as a base class;
- // ignores virtual bases.
- if (getTarget().getCXXABI().hasConstructorVariants())
- EmitGlobal(GlobalDecl(D, Ctor_Base));
-}
-
void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *ctor,
CXXCtorType ctorType) {
// The complete constructor is equivalent to the base constructor
diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h
index 27792d0..c5ff024 100644
--- a/lib/CodeGen/CGCXXABI.h
+++ b/lib/CodeGen/CGCXXABI.h
@@ -234,6 +234,9 @@
virtual llvm::BasicBlock *EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
const CXXRecordDecl *RD);
+ /// Emit constructor variants required by this ABI.
+ virtual void EmitCXXConstructors(const CXXConstructorDecl *D) = 0;
+
/// Build the signature of the given destructor variant by adding
/// any required parameters. For convenience, ArgTys has been initialized
/// with the type of 'this' and ResTy has been initialized with the type of
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index fd884db..21edc7e 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -2878,7 +2878,7 @@
cast<FunctionDecl>(D)->isLateTemplateParsed())
return;
- EmitCXXConstructors(cast<CXXConstructorDecl>(D));
+ getCXXABI().EmitCXXConstructors(cast<CXXConstructorDecl>(D));
break;
case Decl::CXXDestructor:
if (cast<FunctionDecl>(D)->isLateTemplateParsed())
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index c99a0ec..8e2739e 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -1033,10 +1033,6 @@
void EmitLinkageSpec(const LinkageSpecDecl *D);
void CompleteDIClassType(const CXXMethodDecl* D);
- /// EmitCXXConstructors - Emit constructors (base, complete) from a
- /// C++ constructor Decl.
- void EmitCXXConstructors(const CXXConstructorDecl *D);
-
/// EmitCXXConstructor - Emit a single constructor with the given type from
/// a C++ constructor Decl.
void EmitCXXConstructor(const CXXConstructorDecl *D, CXXCtorType Type);
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index a1e197c..f3ac03d 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -112,6 +112,8 @@
CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys);
+ void EmitCXXConstructors(const CXXConstructorDecl *D);
+
void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
CXXDtorType T,
CanQualType &ResTy,
@@ -772,6 +774,22 @@
ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
}
+void ItaniumCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {
+ // Just make sure we're in sync with TargetCXXABI.
+ assert(CGM.getTarget().getCXXABI().hasConstructorVariants());
+
+ // The constructor used for constructing this as a complete class;
+ // constucts the virtual bases, then calls the base constructor.
+ if (!D->getParent()->isAbstract()) {
+ // We don't need to emit the complete ctor if the class is abstract.
+ CGM.EmitGlobal(GlobalDecl(D, Ctor_Complete));
+ }
+
+ // The constructor used for constructing this as a base class;
+ // ignores virtual bases.
+ CGM.EmitGlobal(GlobalDecl(D, Ctor_Base));
+}
+
/// The generic ABI passes 'this', plus a VTT if it's destroying a
/// base subobject.
void ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index 74575c3..b2c9ef0 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -66,6 +66,8 @@
llvm::BasicBlock *EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
const CXXRecordDecl *RD);
+ void EmitCXXConstructors(const CXXConstructorDecl *D);
+
// Background on MSVC destructors
// ==============================
//
@@ -376,6 +378,11 @@
return SkipVbaseCtorsBB;
}
+void MicrosoftCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {
+ // There's only one constructor type in this ABI.
+ CGM.EmitGlobal(GlobalDecl(D, Ctor_Complete));
+}
+
void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF,
const CXXRecordDecl *RD) {
llvm::Value *ThisInt8Ptr =
diff --git a/test/CodeGenCXX/microsoft-abi-structors.cpp b/test/CodeGenCXX/microsoft-abi-structors.cpp
index 24be897..9575275 100644
--- a/test/CodeGenCXX/microsoft-abi-structors.cpp
+++ b/test/CodeGenCXX/microsoft-abi-structors.cpp
@@ -221,6 +221,15 @@
// CHECK: ret
}
+// PR16735 - even abstract classes should have a constructor emitted.
+struct F {
+ F();
+ virtual void f() = 0;
+};
+
+F::F() {}
+// CHECK: define x86_thiscallcc %"struct.constructors::F"* @"\01??0F@constructors@@QAE@XZ"
+
} // end namespace constructors
namespace dtors {