aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CGCXX.cpp11
-rw-r--r--test/CodeGenCXX/abstract-class-ctors-dtors.cpp16
2 files changed, 25 insertions, 2 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 184147cb72..4390f3a3e3 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -187,7 +187,10 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
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.
- EmitGlobal(GlobalDecl(D, Ctor_Complete));
+ 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.
@@ -244,7 +247,11 @@ void CodeGenModule::EmitCXXDestructors(const CXXDestructorDecl *D) {
// The destructor used for destructing this as a most-derived class;
// call the base destructor and then destructs any virtual bases.
- EmitGlobal(GlobalDecl(D, Dtor_Complete));
+ if (!D->getParent()->isAbstract() || D->isVirtual()) {
+ // We don't need to emit the complete ctor if the class is abstract,
+ // unless the destructor is virtual and needs to be in the vtable.
+ EmitGlobal(GlobalDecl(D, Dtor_Complete));
+ }
// The destructor used for destructing this as a base class; ignores
// virtual bases.
diff --git a/test/CodeGenCXX/abstract-class-ctors-dtors.cpp b/test/CodeGenCXX/abstract-class-ctors-dtors.cpp
new file mode 100644
index 0000000000..e1c1a75e47
--- /dev/null
+++ b/test/CodeGenCXX/abstract-class-ctors-dtors.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+
+// Check that we dont emit the complete constructor/destructor for this class.
+struct A {
+ virtual void f() = 0;
+ A();
+ ~A();
+};
+
+// CHECK-NOT: define void @_ZN1AC1Ev
+// CHECK: define void @_ZN1AC2Ev
+// CHECK-NOT: define void @_ZN1AD1Ev
+// CHECK: define void @_ZN1AD2Ev
+A::A() { }
+
+A::~A() { }