From: Anders Carlsson Date: Wed, 25 Nov 2009 03:15:49 +0000 (+0000) Subject: Add VTT parameter to base ctors/dtors with virtual bases. (They aren't used yet). X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f6c56e2323c3f973253805a2f35629f3253ebed4;p=clang Add VTT parameter to base ctors/dtors with virtual bases. (They aren't used yet). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89835 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index e1b6739339..71cdf95f48 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -765,7 +765,7 @@ CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D, CXXCtorType Type) { const FunctionProtoType *FPT = D->getType()->getAs(); const llvm::FunctionType *FTy = - getTypes().GetFunctionType(getTypes().getFunctionInfo(D), + getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type), FPT->isVariadic()); const char *Name = getMangledCXXCtorName(D, Type); @@ -803,7 +803,7 @@ llvm::Function * CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D, CXXDtorType Type) { const llvm::FunctionType *FTy = - getTypes().GetFunctionType(getTypes().getFunctionInfo(D), false); + getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type), false); const char *Name = getMangledCXXDtorName(D, Type); return cast( diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 16f4e7b533..decc73c6d4 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -91,6 +91,42 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXMethodDecl *MD) { getCallingConventionForDecl(MD)); } +const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXConstructorDecl *D, + CXXCtorType Type) { + llvm::SmallVector ArgTys; + + // Add the 'this' pointer. + ArgTys.push_back(D->getThisType(Context)); + + // Check if we need to add a VTT parameter (which has type void **). + if (Type == Ctor_Base && D->getParent()->getNumVBases() != 0) + ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy)); + + const FunctionProtoType *FTP = D->getType()->getAs(); + for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i) + ArgTys.push_back(FTP->getArgType(i)); + return getFunctionInfo(FTP->getResultType(), ArgTys, + getCallingConventionForDecl(D)); +} + +const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXDestructorDecl *D, + CXXDtorType Type) { + llvm::SmallVector ArgTys; + + // Add the 'this' pointer. + ArgTys.push_back(D->getThisType(Context)); + + // Check if we need to add a VTT parameter (which has type void **). + if (Type == Dtor_Base && D->getParent()->getNumVBases() != 0) + ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy)); + + const FunctionProtoType *FTP = D->getType()->getAs(); + for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i) + ArgTys.push_back(FTP->getArgType(i)); + return getFunctionInfo(FTP->getResultType(), ArgTys, + getCallingConventionForDecl(D)); +} + const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionDecl *FD) { if (const CXXMethodDecl *MD = dyn_cast(FD)) if (MD->isInstance()) diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index a4cbf449ef..6e0a77ca1b 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -29,7 +29,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) Builder(cgm.getModule().getContext()), DebugInfo(0), IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0), - CXXThisDecl(0), + CXXThisDecl(0), CXXVTTDecl(0), ConditionalBranchLevel(0) { LLVMIntTy = ConvertType(getContext().IntTy); LLVMPointerWidth = Target.getPointerWidth(0); @@ -217,6 +217,24 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, } } +static bool NeedsVTTParameter(GlobalDecl GD) { + const CXXMethodDecl *MD = cast(GD.getDecl()); + + // We don't have any virtual bases, just return early. + if (!MD->getParent()->getNumVBases()) + return false; + + // Check if we have a base constructor. + if (isa(MD) && GD.getCtorType() == Ctor_Base) + return true; + + // Check if we have a base destructor. + if (isa(MD) && GD.getDtorType() == Dtor_Base) + return true; + + return false; +} + void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) { const FunctionDecl *FD = cast(GD.getDecl()); @@ -236,6 +254,16 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, &getContext().Idents.get("this"), MD->getThisType(getContext())); Args.push_back(std::make_pair(CXXThisDecl, CXXThisDecl->getType())); + + // Check if we need a VTT parameter as well. + if (NeedsVTTParameter(GD)) { + // FIXME: The comment about using a fake decl above applies here too. + QualType T = getContext().getPointerType(getContext().VoidPtrTy); + CXXVTTDecl = + ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), + &getContext().Idents.get("vtt"), T); + Args.push_back(std::make_pair(CXXVTTDecl, CXXVTTDecl->getType())); + } } } @@ -318,6 +346,10 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, // Destroy the 'this' declaration. if (CXXThisDecl) CXXThisDecl->Destroy(getContext()); + + // Destroy the VTT declaration. + if (CXXVTTDecl) + CXXVTTDecl->Destroy(getContext()); } /// ContainsLabel - Return true if the statement contains a label in it. If diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 4fde0dd864..28e000a492 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -317,10 +317,15 @@ private: /// BlockScopes - Map of which "cleanup scope" scope basic blocks have. BlockScopeMap BlockScopes; - /// CXXThisDecl - When parsing an C++ function, this will hold the implicit - /// 'this' declaration. + /// CXXThisDecl - When generating code for a C++ member function, + /// this will hold the implicit 'this' declaration. ImplicitParamDecl *CXXThisDecl; + /// CXXVTTDecl - When generating code for a base object constructor or + /// base object destructor with virtual bases, this will hold the implicit + /// VTT parameter. + ImplicitParamDecl *CXXVTTDecl; + /// CXXLiveTemporaryInfo - Holds information about a live C++ temporary. struct CXXLiveTemporaryInfo { /// Temporary - The live temporary. diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h index d4adebecde..55827aac49 100644 --- a/lib/CodeGen/CodeGenTypes.h +++ b/lib/CodeGen/CodeGenTypes.h @@ -20,6 +20,7 @@ #include #include "CGCall.h" +#include "CGCXX.h" namespace llvm { class FunctionType; @@ -34,6 +35,8 @@ namespace llvm { namespace clang { class ABIInfo; class ASTContext; + class CXXConstructorDecl; + class CXXDestructorDecl; class CXXMethodDecl; class FieldDecl; class FunctionProtoType; @@ -198,7 +201,11 @@ public: const CGFunctionInfo &getFunctionInfo(const FunctionDecl *FD); const CGFunctionInfo &getFunctionInfo(const CXXMethodDecl *MD); const CGFunctionInfo &getFunctionInfo(const ObjCMethodDecl *MD); - + const CGFunctionInfo &getFunctionInfo(const CXXConstructorDecl *D, + CXXCtorType Type); + const CGFunctionInfo &getFunctionInfo(const CXXDestructorDecl *D, + CXXDtorType Type); + // getFunctionInfo - Get the function info for a member function. const CGFunctionInfo &getFunctionInfo(const CXXRecordDecl *RD, const FunctionProtoType *FTP); diff --git a/test/CodeGenCXX/virtual-bases.cpp b/test/CodeGenCXX/virtual-bases.cpp new file mode 100644 index 0000000000..4b069ead02 --- /dev/null +++ b/test/CodeGenCXX/virtual-bases.cpp @@ -0,0 +1,17 @@ +// RUN: clang-cc -emit-llvm %s -o - -triple=x86_64-apple-darwin10 | FileCheck %s + +struct A { + A(); +}; + +// CHECK: define void @_ZN1AC1Ev(%struct.A* %this) +// CHECK: define void @_ZN1AC2Ev(%struct.A* %this) +A::A() { } + +struct B : virtual A { + B(); +}; + +// CHECK: define void @_ZN1BC1Ev(%struct.B* %this) +// CHECK: define void @_ZN1BC2Ev(%struct.B* %this, i8** %vtt) +B::B() { }