r175045 - Emit virtual/deleting destructors properly with -cxx-abi microsoft, PR15058
Timur Iskhodzhanov
timurrrr at google.com
Wed Feb 13 00:37:52 PST 2013
Author: timurrrr
Date: Wed Feb 13 02:37:51 2013
New Revision: 175045
URL: http://llvm.org/viewvc/llvm-project?rev=175045&view=rev
Log:
Emit virtual/deleting destructors properly with -cxx-abi microsoft, PR15058
Modified:
cfe/trunk/lib/AST/MicrosoftMangle.cpp
cfe/trunk/lib/AST/VTableBuilder.cpp
cfe/trunk/lib/CodeGen/CGCXXABI.h
cfe/trunk/lib/CodeGen/CGClass.cpp
cfe/trunk/lib/CodeGen/CGExprCXX.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp
cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=175045&r1=175044&r2=175045&view=diff
==============================================================================
--- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
+++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Wed Feb 13 02:37:51 2013
@@ -28,12 +28,25 @@ using namespace clang;
namespace {
+static const FunctionDecl *getStructor(const FunctionDecl *fn) {
+ if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate())
+ return ftd->getTemplatedDecl();
+
+ return fn;
+}
+
/// MicrosoftCXXNameMangler - Manage the mangling of a single name for the
/// Microsoft Visual C++ ABI.
class MicrosoftCXXNameMangler {
MangleContext &Context;
raw_ostream &Out;
+ /// The "structor" is the top-level declaration being mangled, if
+ /// that's not a template specialization; otherwise it's the pattern
+ /// for that specialization.
+ const NamedDecl *Structor;
+ unsigned StructorType;
+
// FIXME: audit the performance of BackRefMap as it might do way too many
// copying of strings.
typedef std::map<std::string, unsigned> BackRefMap;
@@ -47,7 +60,15 @@ class MicrosoftCXXNameMangler {
public:
MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_)
- : Context(C), Out(Out_), UseNameBackReferences(true) { }
+ : Context(C), Out(Out_),
+ Structor(0), StructorType(-1),
+ UseNameBackReferences(true) { }
+
+ MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_,
+ const CXXDestructorDecl *D, CXXDtorType Type)
+ : Context(C), Out(Out_),
+ Structor(getStructor(D)), StructorType(Type),
+ UseNameBackReferences(true) { }
raw_ostream &getStream() const { return Out; }
@@ -68,6 +89,7 @@ private:
void mangleSourceName(const IdentifierInfo *II);
void manglePostfix(const DeclContext *DC, bool NoFunction=false);
void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc);
+ void mangleCXXDtorType(CXXDtorType T);
void mangleQualifiers(Qualifiers Quals, bool IsMember);
void manglePointerQualifiers(Qualifiers Quals);
@@ -485,7 +507,14 @@ MicrosoftCXXNameMangler::mangleUnqualifi
break;
case DeclarationName::CXXDestructorName:
- Out << "?1";
+ if (ND == Structor)
+ // If the named decl is the C++ destructor we're mangling,
+ // use the type we were given.
+ mangleCXXDtorType(static_cast<CXXDtorType>(StructorType));
+ else
+ // Otherwise, use the complete destructor name. This is relevant if a
+ // class with a destructor is declared within a destructor.
+ mangleCXXDtorType(Dtor_Complete);
break;
case DeclarationName::CXXConversionFunctionName:
@@ -543,6 +572,23 @@ void MicrosoftCXXNameMangler::manglePost
}
}
+void MicrosoftCXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
+ switch (T) {
+ case Dtor_Deleting:
+ Out << "?_G";
+ return;
+ case Dtor_Base:
+ // FIXME: We should be asked to mangle base dtors.
+ // However, fixing this would require larger changes to the CodeGenModule.
+ // Please put llvm_unreachable here when CGM is changed.
+ // For now, just mangle a base dtor the same way as a complete dtor...
+ case Dtor_Complete:
+ Out << "?1";
+ return;
+ }
+ llvm_unreachable("Unsupported dtor type?");
+}
+
void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO,
SourceLocation Loc) {
switch (OO) {
@@ -1110,9 +1156,18 @@ void MicrosoftCXXNameMangler::mangleType
// <return-type> ::= <type>
// ::= @ # structors (they have no declared return type)
- if (IsStructor)
+ if (IsStructor) {
+ if (isa<CXXDestructorDecl>(D) && D == Structor &&
+ StructorType == Dtor_Deleting) {
+ // The scalar deleting destructor takes an extra int argument.
+ // However, the FunctionType generated has 0 arguments.
+ // FIXME: This is a temporary hack.
+ // Maybe should fix the FunctionType creation instead?
+ Out << "PAXI at Z";
+ return;
+ }
Out << '@';
- else {
+ } else {
QualType Result = Proto->getResultType();
const Type* RT = Result.getTypePtr();
if (!RT->isAnyPointerType() && !RT->isReferenceType()) {
@@ -1711,7 +1766,7 @@ void MicrosoftMangleContext::mangleCXXCt
void MicrosoftMangleContext::mangleCXXDtor(const CXXDestructorDecl *D,
CXXDtorType Type,
raw_ostream & Out) {
- MicrosoftCXXNameMangler mangler(*this, Out);
+ MicrosoftCXXNameMangler mangler(*this, Out, D, Type);
mangler.mangle(D);
}
void MicrosoftMangleContext::mangleReferenceTemporary(const clang::VarDecl *VD,
Modified: cfe/trunk/lib/AST/VTableBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/VTableBuilder.cpp?rev=175045&r1=175044&r2=175045&view=diff
==============================================================================
--- cfe/trunk/lib/AST/VTableBuilder.cpp (original)
+++ cfe/trunk/lib/AST/VTableBuilder.cpp Wed Feb 13 02:37:51 2013
@@ -1160,6 +1160,8 @@ void VTableBuilder::ComputeThisAdjustmen
break;
case VTableComponent::CK_DeletingDtorPointer:
// We've already added the thunk when we saw the complete dtor pointer.
+ // FIXME: check how this works in the Microsoft ABI
+ // while working on the multiple inheritance patch.
continue;
}
@@ -1302,11 +1304,8 @@ VTableBuilder::AddMethod(const CXXMethod
Components.push_back(VTableComponent::MakeCompleteDtor(DD));
Components.push_back(VTableComponent::MakeDeletingDtor(DD));
} else {
- // Add only one destructor in MS mode.
- // FIXME: The virtual destructors are handled differently in MS ABI,
- // we should add such a support later. For now, put the complete
- // destructor into the vftable just to make its layout right.
- Components.push_back(VTableComponent::MakeCompleteDtor(DD));
+ // Add the scalar deleting destructor.
+ Components.push_back(VTableComponent::MakeDeletingDtor(DD));
}
} else {
// Add the return adjustment if necessary.
@@ -1951,6 +1950,8 @@ void VTableBuilder::dumpLayout(raw_ostre
Out << DD->getQualifiedNameAsString();
if (IsComplete)
Out << "() [complete]";
+ else if (isMicrosoftABI())
+ Out << "() [scalar deleting]";
else
Out << "() [deleting]";
@@ -2142,8 +2143,8 @@ void VTableBuilder::dumpLayout(raw_ostre
IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Deleting))]
= MethodName + " [deleting]";
} else {
- IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Complete))]
- = MethodName;
+ IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Deleting))]
+ = MethodName + " [scalar deleting]";
}
} else {
IndicesMap[VTables.getMethodVTableIndex(MD)] = MethodName;
@@ -2275,8 +2276,9 @@ void VTableContext::ComputeMethodVTableI
MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] =
getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting));
} else {
- MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] =
- getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Complete));
+ // Add the scalar deleting destructor.
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] =
+ getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting));
}
} else {
MethodVTableIndices[MD] = getMethodVTableIndex(OverriddenMD);
@@ -2302,11 +2304,8 @@ void VTableContext::ComputeMethodVTableI
// Add the deleting dtor.
MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++;
} else {
- // Add only the deleting dtor.
- // FIXME: The virtual destructors are handled differently in MS ABI,
- // we should add such a support later. For now, put the complete
- // destructor into the vftable indices.
- MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++;
+ // Add the scalar deleting dtor.
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++;
}
} else {
// Add the entry.
Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=175045&r1=175044&r2=175045&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Wed Feb 13 02:37:51 2013
@@ -54,11 +54,20 @@ protected:
return CGF.CXXABIThisValue;
}
+ // FIXME: Every place that calls getVTT{Decl,Value} is something
+ // that needs to be abstracted properly.
ImplicitParamDecl *&getVTTDecl(CodeGenFunction &CGF) {
- return CGF.CXXVTTDecl;
+ return CGF.CXXStructorImplicitParamDecl;
}
llvm::Value *&getVTTValue(CodeGenFunction &CGF) {
- return CGF.CXXVTTValue;
+ return CGF.CXXStructorImplicitParamValue;
+ }
+
+ ImplicitParamDecl *&getStructorImplicitParamDecl(CodeGenFunction &CGF) {
+ return CGF.CXXStructorImplicitParamDecl;
+ }
+ llvm::Value *&getStructorImplicitParamValue(CodeGenFunction &CGF) {
+ return CGF.CXXStructorImplicitParamValue;
}
/// Build a parameter variable suitable for 'this'.
Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=175045&r1=175044&r2=175045&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGClass.cpp Wed Feb 13 02:37:51 2013
@@ -953,6 +953,32 @@ namespace {
}
};
+ struct CallDtorDeleteConditional : EHScopeStack::Cleanup {
+ llvm::Value *ShouldDeleteCondition;
+ public:
+ CallDtorDeleteConditional(llvm::Value *ShouldDeleteCondition)
+ : ShouldDeleteCondition(ShouldDeleteCondition) {
+ assert(ShouldDeleteCondition != NULL);
+ }
+
+ void Emit(CodeGenFunction &CGF, Flags flags) {
+ llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete");
+ llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue");
+ llvm::Value *ShouldCallDelete
+ = CGF.Builder.CreateIsNull(ShouldDeleteCondition);
+ CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB);
+
+ CGF.EmitBlock(callDeleteBB);
+ const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl);
+ const CXXRecordDecl *ClassDecl = Dtor->getParent();
+ CGF.EmitDeleteCall(Dtor->getOperatorDelete(), CGF.LoadCXXThis(),
+ CGF.getContext().getTagDeclType(ClassDecl));
+ CGF.Builder.CreateBr(continueBB);
+
+ CGF.EmitBlock(continueBB);
+ }
+ };
+
class DestroyField : public EHScopeStack::Cleanup {
const FieldDecl *field;
CodeGenFunction::Destroyer *destroyer;
@@ -991,7 +1017,14 @@ void CodeGenFunction::EnterDtorCleanups(
if (DtorType == Dtor_Deleting) {
assert(DD->getOperatorDelete() &&
"operator delete missing - EmitDtorEpilogue");
- EHStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup);
+ if (CXXStructorImplicitParamValue) {
+ // If there is an implicit param to the deleting dtor, it's a boolean
+ // telling whether we should call delete at the end of the dtor.
+ EHStack.pushCleanup<CallDtorDeleteConditional>(
+ NormalAndEHCleanup, CXXStructorImplicitParamValue);
+ } else {
+ EHStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup);
+ }
return;
}
@@ -1243,7 +1276,8 @@ CodeGenFunction::EmitCXXConstructorCall(
// FIXME: Provide a source location here.
EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This,
- VTT, ArgBeg, ArgEnd);
+ VTT, getContext().getPointerType(getContext().VoidPtrTy),
+ ArgBeg, ArgEnd);
}
void
@@ -1399,7 +1433,8 @@ void CodeGenFunction::EmitCXXDestructorC
// FIXME: Provide a source location here.
EmitCXXMemberCall(DD, SourceLocation(), Callee, ReturnValueSlot(), This,
- VTT, 0, 0);
+ VTT, getContext().getPointerType(getContext().VoidPtrTy),
+ 0, 0);
}
namespace {
Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=175045&r1=175044&r2=175045&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Wed Feb 13 02:37:51 2013
@@ -28,7 +28,8 @@ RValue CodeGenFunction::EmitCXXMemberCal
llvm::Value *Callee,
ReturnValueSlot ReturnValue,
llvm::Value *This,
- llvm::Value *VTT,
+ llvm::Value *ImplicitParam,
+ QualType ImplicitParamTy,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd) {
assert(MD->isInstance() &&
@@ -46,10 +47,9 @@ RValue CodeGenFunction::EmitCXXMemberCal
// Push the this ptr.
Args.add(RValue::get(This), MD->getThisType(getContext()));
- // If there is a VTT parameter, emit it.
- if (VTT) {
- QualType T = getContext().getPointerType(getContext().VoidPtrTy);
- Args.add(RValue::get(VTT), T);
+ // If there is an implicit parameter (e.g. VTT), emit it.
+ if (ImplicitParam) {
+ Args.add(RValue::get(ImplicitParam), ImplicitParamTy);
}
const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
@@ -316,7 +316,8 @@ RValue CodeGenFunction::EmitCXXMemberCal
}
return EmitCXXMemberCall(MD, CE->getExprLoc(), Callee, ReturnValue, This,
- /*VTT=*/0, CE->arg_begin(), CE->arg_end());
+ /*ImplicitParam=*/0, QualType(),
+ CE->arg_begin(), CE->arg_end());
}
RValue
@@ -388,7 +389,8 @@ CodeGenFunction::EmitCXXOperatorMemberCa
llvm::Value *Callee = EmitCXXOperatorMemberCallee(E, MD, This);
return EmitCXXMemberCall(MD, E->getExprLoc(), Callee, ReturnValue, This,
- /*VTT=*/0, E->arg_begin() + 1, E->arg_end());
+ /*ImplicitParam=*/0, QualType(),
+ E->arg_begin() + 1, E->arg_end());
}
RValue CodeGenFunction::EmitCUDAKernelCallExpr(const CUDAKernelCallExpr *E,
@@ -1408,7 +1410,7 @@ static void EmitObjectDelete(CodeGenFunc
Ptr, Ty);
// FIXME: Provide a source location here.
CGF.EmitCXXMemberCall(Dtor, SourceLocation(), Callee, ReturnValueSlot(),
- Ptr, /*VTT=*/0, 0, 0);
+ Ptr, /*ImplicitParam=*/0, QualType(), 0, 0);
if (UseGlobalDelete) {
CGF.PopCleanupBlock();
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=175045&r1=175044&r2=175045&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Wed Feb 13 02:37:51 2013
@@ -43,8 +43,9 @@ CodeGenFunction::CodeGenFunction(CodeGen
FirstBlockInfo(0), EHResumeBlock(0), ExceptionSlot(0), EHSelectorSlot(0),
DebugInfo(0), DisableDebugInfo(false), DidCallStackSave(false),
IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0),
- CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0), CXXVTTDecl(0),
- CXXVTTValue(0), OutermostConditional(0), TerminateLandingPad(0),
+ CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0),
+ CXXStructorImplicitParamDecl(0), CXXStructorImplicitParamValue(0),
+ OutermostConditional(0), TerminateLandingPad(0),
TerminateHandler(0), TrapBB(0) {
if (!suppressNewContext)
CGM.getCXXABI().getMangleContext().startNewFunction();
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=175045&r1=175044&r2=175045&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Wed Feb 13 02:37:51 2013
@@ -1179,11 +1179,10 @@ private:
llvm::Value *CXXABIThisValue;
llvm::Value *CXXThisValue;
- /// 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;
- llvm::Value *CXXVTTValue;
+ /// CXXStructorImplicitParamDecl - When generating code for a constructor or
+ /// destructor, this will hold the implicit argument (e.g. VTT).
+ ImplicitParamDecl *CXXStructorImplicitParamDecl;
+ llvm::Value *CXXStructorImplicitParamValue;
/// OutermostConditional - Points to the outermost active
/// conditional control. This is used so that we know if a
@@ -1777,9 +1776,19 @@ public:
/// LoadCXXVTT - Load the VTT parameter to base constructors/destructors have
/// virtual bases.
+ // FIXME: Every place that calls LoadCXXVTT is something
+ // that needs to be abstracted properly.
llvm::Value *LoadCXXVTT() {
- assert(CXXVTTValue && "no VTT value for this function");
- return CXXVTTValue;
+ assert(CXXStructorImplicitParamValue && "no VTT value for this function");
+ return CXXStructorImplicitParamValue;
+ }
+
+ /// LoadCXXStructorImplicitParam - Load the implicit parameter
+ /// for a constructor/destructor.
+ llvm::Value *LoadCXXStructorImplicitParam() {
+ assert(CXXStructorImplicitParamValue &&
+ "no implicit argument value for this function");
+ return CXXStructorImplicitParamValue;
}
/// GetAddressOfBaseOfCompleteClass - Convert the given pointer to a
@@ -2294,7 +2303,8 @@ public:
llvm::Value *Callee,
ReturnValueSlot ReturnValue,
llvm::Value *This,
- llvm::Value *VTT,
+ llvm::Value *ImplicitParam,
+ QualType ImplicitParamTy,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd);
RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E,
Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=175045&r1=175044&r2=175045&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Wed Feb 13 02:37:51 2013
@@ -45,10 +45,7 @@ public:
void BuildDestructorSignature(const CXXDestructorDecl *Ctor,
CXXDtorType Type,
CanQualType &ResTy,
- SmallVectorImpl<CanQualType> &ArgTys) {
- // 'this' is already in place
- // TODO: 'for base' flag
- }
+ SmallVectorImpl<CanQualType> &ArgTys);
void BuildInstanceFunctionParams(CodeGenFunction &CGF,
QualType &ResTy,
@@ -121,6 +118,27 @@ void MicrosoftCXXABI::BuildConstructorSi
ResTy = ArgTys[0];
}
+void MicrosoftCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
+ CXXDtorType Type,
+ CanQualType &ResTy,
+ SmallVectorImpl<CanQualType> &ArgTys) {
+ // 'this' is already in place
+ // TODO: 'for base' flag
+
+ if (Type == Dtor_Deleting) {
+ // The scalar deleting destructor takes an implicit bool parameter.
+ ArgTys.push_back(CGM.getContext().BoolTy);
+ }
+}
+
+static bool IsDeletingDtor(GlobalDecl GD) {
+ const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl());
+ if (isa<CXXDestructorDecl>(MD)) {
+ return GD.getDtorType() == Dtor_Deleting;
+ }
+ return false;
+}
+
void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
QualType &ResTy,
FunctionArgList &Params) {
@@ -128,6 +146,17 @@ void MicrosoftCXXABI::BuildInstanceFunct
if (needThisReturn(CGF.CurGD)) {
ResTy = Params[0]->getType();
}
+ if (IsDeletingDtor(CGF.CurGD)) {
+ ASTContext &Context = getContext();
+
+ ImplicitParamDecl *ShouldDelete
+ = ImplicitParamDecl::Create(Context, 0,
+ CGF.CurGD.getDecl()->getLocation(),
+ &Context.Idents.get("should_call_delete"),
+ Context.BoolTy);
+ Params.push_back(ShouldDelete);
+ getStructorImplicitParamDecl(CGF) = ShouldDelete;
+ }
}
void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
@@ -135,6 +164,14 @@ void MicrosoftCXXABI::EmitInstanceFuncti
if (needThisReturn(CGF.CurGD)) {
CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
}
+ if (IsDeletingDtor(CGF.CurGD)) {
+ assert(getStructorImplicitParamDecl(CGF) &&
+ "no implicit parameter for a deleting destructor?");
+ getStructorImplicitParamValue(CGF)
+ = CGF.Builder.CreateLoad(
+ CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)),
+ "should_call_delete");
+ }
}
bool MicrosoftCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp?rev=175045&r1=175044&r2=175045&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp Wed Feb 13 02:37:51 2013
@@ -1,4 +1,8 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 -fno-rtti > %t 2>&1
+// RUN: FileCheck %s < %t
+// Using a different check prefix as the inline destructors might be placed
+// anywhere in the output.
+// RUN: FileCheck --check-prefix=DTORS %s < %t
class A {
public:
@@ -23,13 +27,60 @@ void no_constructor_destructor_infinite_
}
struct B {
- virtual ~B();
+ virtual ~B() {
+// Complete destructor first:
+// DTORS: define {{.*}} x86_thiscallcc void @"\01??1B@@UAE at XZ"(%struct.B* %this)
+//
+// Then, the scalar deleting destructor (used in the vtable):
+// DTORS: define {{.*}} x86_thiscallcc void @"\01??_GB@@UAEPAXI at Z"(%struct.B* %this, i1 zeroext %should_call_delete)
+// DTORS: %0 = icmp eq i8 %should_call_delete{{.*}}, 0
+// DTORS-NEXT: br i1 %0, label %dtor.continue, label %dtor.call_delete
+// DTORS: dtor.call_delete:
+// DTORS-NEXT: %1 = bitcast %struct.B* %this1 to i8*
+// DTORS-NEXT: call void @"\01??3 at YAXPAX@Z"(i8* %1) nounwind
+// DTORS-NEXT: br label %dtor.continue
+// DTORS: dtor.continue:
+// DTORS-NEXT: ret void
+ }
virtual void foo();
};
+// Emits the vftable in the output.
+void B::foo() {}
+
void check_vftable_offset() {
B b;
// The vftable pointer should point at the beginning of the vftable.
// CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %struct.B* {{.*}} to i8***
// CHECK: store i8** getelementptr inbounds ([2 x i8*]* @"\01??_7B@@6B@", i64 0, i64 0), i8*** [[THIS_PTR]]
}
+
+// FIXME: Enable the following block and add expectations when calls
+// to virtual complete dtor are supported.
+#if 0
+void call_complete_dtor(B *obj_ptr) {
+ obj_ptr->~B();
+}
+#endif
+
+void call_deleting_dtor(B *obj_ptr) {
+// FIXME: Add CHECKs when calls to virtual deleting dtor are generated properly.
+ delete obj_ptr;
+}
+
+struct C {
+ static int foo();
+
+ C() {
+ static int ctor_static = foo();
+ // CHECK that the static in the ctor gets mangled correctly:
+ // CHECK: @"\01?ctor_static@?1???0C@@QAE at XZ@4HA"
+ }
+ ~C() {
+ static int dtor_static = foo();
+ // CHECK that the static in the dtor gets mangled correctly:
+ // CHECK: @"\01?dtor_static@?1???1C@@QAE at XZ@4HA"
+ }
+};
+
+void use_C() { C c; }
Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp?rev=175045&r1=175044&r2=175045&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp Wed Feb 13 02:37:51 2013
@@ -37,10 +37,10 @@ void B::f() {}
struct C {
// CHECK-C: Vtable for 'C' (2 entries)
- // CHECK-C-NEXT: 0 | C::~C()
+ // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
// CHECK-C-NEXT: 1 | void C::f()
// CHECK-C: VTable indices for 'C' (2 entries).
- // CHECK-C-NEXT: 0 | C::~C()
+ // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
// CHECK-C-NEXT: 1 | void C::f()
// Never used, so doesn't emit a vtable.
virtual ~C();
@@ -52,7 +52,7 @@ void C::f() {}
struct D {
// CHECK-D: Vtable for 'D' (2 entries)
// CHECK-D-NEXT: 0 | void D::f()
- // CHECK-D-NEXT: 1 | D::~D()
+ // CHECK-D-NEXT: 1 | D::~D() [scalar deleting]
// EMITS-VTABLE: @"\01??_7D@@6B@" = unnamed_addr constant [2 x i8*]
virtual void f();
@@ -65,10 +65,10 @@ struct E : A {
// CHECK-E-NEXT: 0 | void A::f()
// CHECK-E-NEXT: 1 | void A::g()
// CHECK-E-NEXT: 2 | void A::h()
- // CHECK-E-NEXT: 3 | E::~E()
+ // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]
// CHECK-E-NEXT: 4 | void E::i()
// CHECK-E: VTable indices for 'E' (2 entries).
- // CHECK-E-NEXT: 3 | E::~E()
+ // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]
// CHECK-E-NEXT: 4 | void E::i()
// Never used, so doesn't emit a vtable.
@@ -83,10 +83,10 @@ struct F : A {
// CHECK-F-NEXT: 1 | void A::g()
// CHECK-F-NEXT: 2 | void A::h()
// CHECK-F-NEXT: 3 | void F::i()
- // CHECK-F-NEXT: 4 | F::~F()
+ // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]
// CHECK-F: VTable indices for 'F' (2 entries).
// CHECK-F-NEXT: 3 | void F::i()
- // CHECK-F-NEXT: 4 | F::~F()
+ // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]
// EMITS-VTABLE: @"\01??_7F@@6B@" = unnamed_addr constant [5 x i8*]
virtual void i();
virtual ~F();
@@ -98,12 +98,12 @@ struct G : E {
// CHECK-G-NEXT: 0 | void G::f()
// CHECK-G-NEXT: 1 | void A::g()
// CHECK-G-NEXT: 2 | void A::h()
- // CHECK-G-NEXT: 3 | G::~G()
+ // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]
// CHECK-G-NEXT: 4 | void E::i()
// CHECK-G-NEXT: 5 | void G::j()
// CHECK-G: VTable indices for 'G' (3 entries).
// CHECK-G-NEXT: 0 | void G::f()
- // CHECK-G-NEXT: 3 | G::~G()
+ // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]
// CHECK-G-NEXT: 5 | void G::j()
// Never used, so doesn't emit a vtable.
virtual void f(); // overrides A::f()
More information about the cfe-commits
mailing list