diff options
-rw-r--r-- | lib/CodeGen/CGClass.cpp | 28 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 5 | ||||
-rw-r--r-- | test/CodeGenCXX/cxx0x-delegating-ctors.cpp | 34 | ||||
-rw-r--r-- | test/SemaCXX/cxx0x-delegating-ctors.cpp | 20 |
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}} + {} +}; |