From 378e1e739aed97e9b278beeb20e9f5bbe34c0232 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 31 Jan 2013 05:50:40 +0000 Subject: [PATCH] When we're emitting a constructor or destructor call from a delegating constructor, retrieve our VTT parameter directly. Fixes PR14588 / . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174042 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGClass.cpp | 40 ++++++++++++++-------- lib/CodeGen/CGDecl.cpp | 4 ++- lib/CodeGen/CGExprCXX.cpp | 10 ++++-- lib/CodeGen/CodeGenFunction.h | 6 ++-- test/CodeGenCXX/cxx0x-delegating-ctors.cpp | 34 ++++++++++++++++++ 5 files changed, 73 insertions(+), 21 deletions(-) diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 5d1e30fef6..0611ed7834 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -282,7 +282,8 @@ CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value, /// GetVTTParameter - Return the VTT parameter that should be passed to a /// base constructor/destructor with virtual bases. static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD, - bool ForVirtualBase) { + bool ForVirtualBase, + bool Delegating) { if (!CodeGenVTables::needsVTTParameter(GD)) { // This constructor/destructor does not need a VTT parameter. return 0; @@ -295,9 +296,12 @@ static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD, uint64_t SubVTTIndex; - // If the record matches the base, this is the complete ctor/dtor - // variant calling the base variant in a class with virtual bases. - if (RD == Base) { + if (Delegating) { + // If this is a delegating constructor call, just load the VTT. + return CGF.LoadCXXVTT(); + } else if (RD == Base) { + // If the record matches the base, this is the complete ctor/dtor + // variant calling the base variant in a class with virtual bases. assert(!CodeGenVTables::needsVTTParameter(CGF.CurGD) && "doing no-op VTT offset in base dtor/ctor?"); assert(!ForVirtualBase && "Can't have same class as virtual base!"); @@ -344,7 +348,8 @@ namespace { CGF.GetAddressOfDirectBaseInCompleteClass(CGF.LoadCXXThis(), DerivedClass, BaseClass, BaseIsVirtual); - CGF.EmitCXXDestructorCall(D, Dtor_Base, BaseIsVirtual, Addr); + CGF.EmitCXXDestructorCall(D, Dtor_Base, BaseIsVirtual, + /*Delegating=*/false, Addr); } }; @@ -537,7 +542,7 @@ namespace { void Emit(CodeGenFunction &CGF, Flags flags) { CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, - V); + /*Delegating=*/false, V); } }; } @@ -893,7 +898,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { if (DtorType == Dtor_Deleting) { EnterDtorCleanups(Dtor, Dtor_Deleting); EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, - LoadCXXThis()); + /*Delegating=*/false, LoadCXXThis()); PopCleanupBlock(); return; } @@ -923,7 +928,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { if (!isTryBody && CGM.getContext().getTargetInfo().getCXXABI().hasDestructorVariants()) { EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false, - LoadCXXThis()); + /*Delegating=*/false, LoadCXXThis()); break; } // Fallthrough: act like we're in the base variant. @@ -1188,7 +1193,7 @@ CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor, } EmitCXXConstructorCall(ctor, Ctor_Complete, /*ForVirtualBase=*/ false, - cur, argBegin, argEnd); + /*Delegating=*/false, cur, argBegin, argEnd); } // Go to the next element. @@ -1216,12 +1221,13 @@ void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF, const CXXDestructorDecl *dtor = record->getDestructor(); assert(!dtor->isTrivial()); CGF.EmitCXXDestructorCall(dtor, Dtor_Complete, /*for vbase*/ false, - addr); + /*Delegating=*/false, addr); } void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase, + bool Delegating, llvm::Value *This, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd) { @@ -1255,7 +1261,8 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, return; } - llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(D, Type), ForVirtualBase); + llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(D, Type), ForVirtualBase, + Delegating); llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type); // FIXME: Provide a source location here. @@ -1331,7 +1338,8 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, // vtt if (llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(Ctor, CtorType), - /*ForVirtualBase=*/false)) { + /*ForVirtualBase=*/false, + /*Delegating=*/true)) { QualType VoidPP = getContext().getPointerType(getContext().VoidPtrTy); DelegateArgs.add(RValue::get(VTT), VoidPP); @@ -1365,7 +1373,7 @@ namespace { void Emit(CodeGenFunction &CGF, Flags flags) { CGF.EmitCXXDestructorCall(Dtor, Type, /*ForVirtualBase=*/false, - Addr); + /*Delegating=*/true, Addr); } }; } @@ -1401,9 +1409,10 @@ CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, + bool Delegating, llvm::Value *This) { llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(DD, Type), - ForVirtualBase); + ForVirtualBase, Delegating); llvm::Value *Callee = 0; if (getLangOpts().AppleKext) Callee = BuildAppleKextVirtualDestructorCall(DD, Type, @@ -1427,7 +1436,8 @@ namespace { void Emit(CodeGenFunction &CGF, Flags flags) { CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, - /*ForVirtualBase=*/false, Addr); + /*ForVirtualBase=*/false, + /*Delegating=*/false, Addr); } }; } diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 26babea047..ac45339515 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -386,7 +386,9 @@ namespace { } CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, - /*ForVirtualBase=*/false, Loc); + /*ForVirtualBase=*/false, + /*Delegating=*/false, + Loc); if (NRVO) CGF.EmitBlock(SkipDtorBB); } diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 3674facde0..8b7f2342c4 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -485,11 +485,13 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E, } else { CXXCtorType Type = Ctor_Complete; bool ForVirtualBase = false; - + bool Delegating = false; + switch (E->getConstructionKind()) { case CXXConstructExpr::CK_Delegating: // We should be emitting a constructor; GlobalDecl will assert this Type = CurGD.getCtorType(); + Delegating = true; break; case CXXConstructExpr::CK_Complete: @@ -505,7 +507,7 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E, } // Call the constructor. - EmitCXXConstructorCall(CD, Type, ForVirtualBase, Dest.getAddr(), + EmitCXXConstructorCall(CD, Type, ForVirtualBase, Delegating, Dest.getAddr(), E->arg_begin(), E->arg_end()); } } @@ -1425,7 +1427,9 @@ static void EmitObjectDelete(CodeGenFunction &CGF, if (Dtor) CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, - /*ForVirtualBase=*/false, Ptr); + /*ForVirtualBase=*/false, + /*Delegating=*/false, + Ptr); else if (CGF.getLangOpts().ObjCAutoRefCount && ElementType->isObjCLifetimeType()) { switch (ElementType.getObjCLifetime()) { diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index ce3db3f4ec..99bb8e37f4 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1816,7 +1816,8 @@ public: void EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor, const FunctionArgList &Args); void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, - bool ForVirtualBase, llvm::Value *This, + bool ForVirtualBase, bool Delegating, + llvm::Value *This, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd); @@ -1842,7 +1843,8 @@ public: static Destroyer destroyCXXObject; void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type, - bool ForVirtualBase, llvm::Value *This); + bool ForVirtualBase, bool Delegating, + llvm::Value *This); void EmitNewArrayInitializer(const CXXNewExpr *E, QualType elementType, llvm::Value *NewPtr, llvm::Value *NumElements); diff --git a/test/CodeGenCXX/cxx0x-delegating-ctors.cpp b/test/CodeGenCXX/cxx0x-delegating-ctors.cpp index 338159cd82..de739d0ad8 100644 --- a/test/CodeGenCXX/cxx0x-delegating-ctors.cpp +++ b/test/CodeGenCXX/cxx0x-delegating-ctors.cpp @@ -65,3 +65,37 @@ namespace PR12890 { } // CHECK: define {{.*}} @_ZN7PR128901XC1Ei(%"class.PR12890::X"* %this, i32) // CHECK: call void @llvm.memset.p0i8.{{i32|i64}}(i8* {{.*}}, i8 0, {{i32|i64}} 4, i32 4, i1 false) + +namespace PR14588 { + void other(); + + class Base { + public: + Base() { squawk(); } + virtual ~Base() {} + + virtual void squawk() { other(); } + }; + + + class Foo : public virtual Base { + public: + Foo(); + Foo(const void * inVoid); + virtual ~Foo() {} + + virtual void squawk() { other(); } + }; + + // CHECK: define void @_ZN7PR145883FooC1Ev(%"class.PR14588::Foo"* + // CHECK: call void @_ZN7PR145883FooC1EPKv( + // CHECK: invoke void @_ZN7PR145885otherEv() + // CHECK: call void @_ZN7PR145883FooD1Ev + // CHECK: resume + + Foo::Foo() : Foo(__null) { other(); } + Foo::Foo(const void *inVoid) { + squawk(); + } + +} -- 2.40.0