From 40f2fa9a45a6f16187a706401512a56e403868bf Mon Sep 17 00:00:00 2001 From: Timur Iskhodzhanov Date: Sun, 4 Aug 2013 17:30:04 +0000 Subject: [PATCH] Emit the constructor for abstract classes when using -cxx-abi microsoft, fixes PR16735 llvm-svn: 187709 --- clang/lib/CodeGen/CGCXX.cpp | 14 -------------- clang/lib/CodeGen/CGCXXABI.h | 3 +++ clang/lib/CodeGen/CodeGenModule.cpp | 2 +- clang/lib/CodeGen/CodeGenModule.h | 4 ---- clang/lib/CodeGen/ItaniumCXXABI.cpp | 18 ++++++++++++++++++ clang/lib/CodeGen/MicrosoftCXXABI.cpp | 7 +++++++ clang/test/CodeGenCXX/microsoft-abi-structors.cpp | 9 +++++++++ 7 files changed, 38 insertions(+), 19 deletions(-) diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 6023bf7..0453b73 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -172,20 +172,6 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl, 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/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index 27792d0..c5ff024 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -234,6 +234,9 @@ public: 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/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index fd884db..21edc7e 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2878,7 +2878,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { cast(D)->isLateTemplateParsed()) return; - EmitCXXConstructors(cast(D)); + getCXXABI().EmitCXXConstructors(cast(D)); break; case Decl::CXXDestructor: if (cast(D)->isLateTemplateParsed()) diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index c99a0ec..8e2739e 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -1033,10 +1033,6 @@ private: 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/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index a1e197c..f3ac03d 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -112,6 +112,8 @@ public: CanQualType &ResTy, SmallVectorImpl &ArgTys); + void EmitCXXConstructors(const CXXConstructorDecl *D); + void BuildDestructorSignature(const CXXDestructorDecl *Dtor, CXXDtorType T, CanQualType &ResTy, @@ -772,6 +774,22 @@ void ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, 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/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 74575c3..b2c9ef0 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -66,6 +66,8 @@ public: llvm::BasicBlock *EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, const CXXRecordDecl *RD); + void EmitCXXConstructors(const CXXConstructorDecl *D); + // Background on MSVC destructors // ============================== // @@ -376,6 +378,11 @@ MicrosoftCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, 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/clang/test/CodeGenCXX/microsoft-abi-structors.cpp b/clang/test/CodeGenCXX/microsoft-abi-structors.cpp index 24be897..9575275 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-structors.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-structors.cpp @@ -221,6 +221,15 @@ E::E() { // 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 { -- 2.7.4