aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CGClass.cpp28
-rw-r--r--lib/Sema/SemaDeclCXX.cpp5
-rw-r--r--test/CodeGenCXX/cxx0x-delegating-ctors.cpp34
-rw-r--r--test/SemaCXX/cxx0x-delegating-ctors.cpp20
4 files changed, 69 insertions, 18 deletions
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 12946423ad..cb41008713 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -1270,6 +1270,23 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
ReturnValueSlot(), DelegateArgs, Ctor);
}
+namespace {
+ struct CallDelegatingCtorDtor : EHScopeStack::Cleanup {
+ const CXXDestructorDecl *Dtor;
+ llvm::Value *Addr;
+ CXXDtorType Type;
+
+ CallDelegatingCtorDtor(const CXXDestructorDecl *D, llvm::Value *Addr,
+ CXXDtorType Type)
+ : Dtor(D), Addr(Addr), Type(Type) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ CGF.EmitCXXDestructorCall(Dtor, Type, /*ForVirtualBase=*/false,
+ Addr);
+ }
+ };
+}
+
void
CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor,
const FunctionArgList &Args) {
@@ -1280,8 +1297,17 @@ CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor
AggValueSlot AggSlot = AggValueSlot::forAddr(ThisPtr, false, /*Lifetime*/ true);
EmitAggExpr(Ctor->init_begin()[0]->getInit(), AggSlot);
-}
+ const CXXRecordDecl *ClassDecl = Ctor->getParent();
+ if (CGM.getLangOptions().Exceptions && !ClassDecl->hasTrivialDestructor()) {
+ CXXDtorType Type =
+ CurGD.getCtorType() == Ctor_Complete ? Dtor_Complete : Dtor_Base;
+
+ EHStack.pushCleanup<CallDelegatingCtorDtor>(EHCleanup,
+ ClassDecl->getDestructor(),
+ ThisPtr, Type);
+ }
+}
void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,
CXXDtorType Type,
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 94177b1d12..6cd5e43241 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2095,6 +2095,11 @@ Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor,
memcpy(initializer, &Initializer, sizeof (CXXCtorInitializer*));
Constructor->setCtorInitializers(initializer);
+ if (CXXDestructorDecl *Dtor = LookupDestructor(Constructor->getParent())) {
+ MarkDeclarationReferenced(Initializer->getSourceLocation(), Dtor);
+ DiagnoseUseOfDecl(Dtor, Initializer->getSourceLocation());
+ }
+
return false;
}
diff --git a/test/CodeGenCXX/cxx0x-delegating-ctors.cpp b/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
index 5b432c7690..68f492fb97 100644
--- a/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
+++ b/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
@@ -22,27 +22,35 @@ delegator::delegator() {
throw 0;
}
+
+delegator::delegator(bool)
+{}
+
+// CHECK: define void @_ZN9delegatorC1Ec
+// CHECK: void @_ZN9delegatorC1Eb
+// CHECK: void @__cxa_throw
+// CHECK: lpad
+// CHECK: void @_ZN9delegatorD1Ev
+// CHECK: define void @_ZN9delegatorC2Ec
+// CHECK: void @_ZN9delegatorC2Eb
+// CHECK: void @__cxa_throw
+// CHECK: lpad
+// CHECK: invoke void @_ZN9delegatorD2Ev
+delegator::delegator(char)
+ : delegator(true) {
+ throw 0;
+}
+
// CHECK: define void @_ZN9delegatorC1Ei
-// CHECK: call void @_ZN9delegatorC1Ev
+// CHECK: void @_ZN9delegatorC1Ev
// CHECK-NOT: lpad
// CHECK: ret
// CHECK-NOT: lpad
// CHECK: define void @_ZN9delegatorC2Ei
-// CHECK: call void @_ZN9delegatorC2Ev
+// CHECK: void @_ZN9delegatorC2Ev
// CHECK-NOT: lpad
// CHECK: ret
// CHECK-NOT: lpad
delegator::delegator(int)
: delegator()
{}
-
-delegator::delegator(bool)
-{}
-
-// CHECK: define void @_ZN9delegatorC2Ec
-// CHECK: call void @_ZN9delegatorC2Eb
-// CHECK: call void @__cxa_throw
-delegator::delegator(char)
- : delegator(true) {
- throw 0;
-}
diff --git a/test/SemaCXX/cxx0x-delegating-ctors.cpp b/test/SemaCXX/cxx0x-delegating-ctors.cpp
index b211cb1fe0..6d0695dfa1 100644
--- a/test/SemaCXX/cxx0x-delegating-ctors.cpp
+++ b/test/SemaCXX/cxx0x-delegating-ctors.cpp
@@ -7,8 +7,9 @@ struct foo {
foo(int, int);
foo(bool);
foo(char);
- foo(float*);
- foo(float&);
+ foo(const float*);
+ foo(const float&);
+ foo(void*);
};
// Good
@@ -25,12 +26,23 @@ foo::foo (bool) : foo(true) { // expected-error{{delegates to itself}}
}
// Good
-foo::foo (float* f) : foo(*f) {
+foo::foo (const float* f) : foo(*f) {
}
// FIXME: This should error
-foo::foo (float &f) : foo(&f) {
+foo::foo (const float &f) : foo(&f) {
}
foo::foo (char) : i(3), foo(3) { // expected-error{{must appear alone}}
}
+
+// This should not cause an infinite loop
+foo::foo (void*) : foo(4.0f) {
+}
+
+struct deleted_dtor {
+ ~deleted_dtor() = delete; // expected-note{{function has been explicitly marked deleted here}}
+ deleted_dtor();
+ deleted_dtor(int) : deleted_dtor() // expected-error{{attempt to use a deleted function}}
+ {}
+};