зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
bc6c676448
Коммит
f6c56e2323
|
@ -765,7 +765,7 @@ CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D,
|
|||
CXXCtorType Type) {
|
||||
const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>();
|
||||
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<llvm::Function>(
|
||||
|
|
|
@ -91,6 +91,42 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXMethodDecl *MD) {
|
|||
getCallingConventionForDecl(MD));
|
||||
}
|
||||
|
||||
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXConstructorDecl *D,
|
||||
CXXCtorType Type) {
|
||||
llvm::SmallVector<QualType, 16> 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<FunctionProtoType>();
|
||||
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<QualType, 16> 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<FunctionProtoType>();
|
||||
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<CXXMethodDecl>(FD))
|
||||
if (MD->isInstance())
|
||||
|
|
|
@ -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<CXXMethodDecl>(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<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
|
||||
return true;
|
||||
|
||||
// Check if we have a base destructor.
|
||||
if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CodeGenFunction::GenerateCode(GlobalDecl GD,
|
||||
llvm::Function *Fn) {
|
||||
const FunctionDecl *FD = cast<FunctionDecl>(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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <vector>
|
||||
|
||||
#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,6 +201,10 @@ 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,
|
||||
|
|
|
@ -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() { }
|
Загрузка…
Ссылка в новой задаче