Emit virtual/deleting destructors properly with -cxx-abi microsoft, PR15058
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175045 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 326b0d3..baa16b0 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -28,12 +28,25 @@
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 @@
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 @@
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 @@
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::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 @@
// <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@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::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,
diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp
index 9a03faa..f80232f 100644
--- a/lib/AST/VTableBuilder.cpp
+++ b/lib/AST/VTableBuilder.cpp
@@ -1160,6 +1160,8 @@
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 @@
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 @@
Out << DD->getQualifiedNameAsString();
if (IsComplete)
Out << "() [complete]";
+ else if (isMicrosoftABI())
+ Out << "() [scalar deleting]";
else
Out << "() [deleting]";
@@ -2142,8 +2143,8 @@
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 @@
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 @@
// 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.