summaryrefslogtreecommitdiff
path: root/lib/AST/MicrosoftMangle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST/MicrosoftMangle.cpp')
-rw-r--r--lib/AST/MicrosoftMangle.cpp302
1 files changed, 235 insertions, 67 deletions
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 5db51b5cb3841..92e9679e49aa3 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -29,6 +29,7 @@
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/JamCRC.h"
+#include "llvm/Support/xxhash.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/MathExtras.h"
@@ -127,10 +128,10 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
llvm::DenseMap<const CXXRecordDecl *, unsigned> LambdaIds;
llvm::DenseMap<const NamedDecl *, unsigned> SEHFilterIds;
llvm::DenseMap<const NamedDecl *, unsigned> SEHFinallyIds;
+ SmallString<16> AnonymousNamespaceHash;
public:
- MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags)
- : MicrosoftMangleContext(Context, Diags) {}
+ MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags);
bool shouldMangleCXXName(const NamedDecl *D) override;
bool shouldMangleStringLiteral(const StringLiteral *SL) override;
void mangleCXXName(const NamedDecl *D, raw_ostream &Out) override;
@@ -238,6 +239,12 @@ public:
return Result.first->second;
}
+ /// Return a character sequence that is (somewhat) unique to the TU suitable
+ /// for mangling anonymous namespaces.
+ StringRef getAnonymousNamespaceHash() const {
+ return AnonymousNamespaceHash;
+ }
+
private:
void mangleInitFiniStub(const VarDecl *D, char CharCode, raw_ostream &Out);
};
@@ -302,13 +309,15 @@ public:
const MethodVFTableLocation &ML);
void mangleNumber(int64_t Number);
void mangleTagTypeKind(TagTypeKind TK);
- void mangleArtificalTagType(TagTypeKind TK, StringRef UnqualifiedName,
+ void mangleArtificialTagType(TagTypeKind TK, StringRef UnqualifiedName,
ArrayRef<StringRef> NestedNames = None);
+ void mangleAddressSpaceType(QualType T, Qualifiers Quals, SourceRange Range);
void mangleType(QualType T, SourceRange Range,
QualifierMangleMode QMM = QMM_Mangle);
void mangleFunctionType(const FunctionType *T,
const FunctionDecl *D = nullptr,
- bool ForceThisQuals = false);
+ bool ForceThisQuals = false,
+ bool MangleExceptionSpec = true);
void mangleNestedName(const NamedDecl *ND);
private:
@@ -368,9 +377,39 @@ private:
void mangleObjCProtocol(const ObjCProtocolDecl *PD);
void mangleObjCLifetime(const QualType T, Qualifiers Quals,
SourceRange Range);
+ void mangleObjCKindOfType(const ObjCObjectType *T, Qualifiers Quals,
+ SourceRange Range);
};
}
+MicrosoftMangleContextImpl::MicrosoftMangleContextImpl(ASTContext &Context,
+ DiagnosticsEngine &Diags)
+ : MicrosoftMangleContext(Context, Diags) {
+ // To mangle anonymous namespaces, hash the path to the main source file. The
+ // path should be whatever (probably relative) path was passed on the command
+ // line. The goal is for the compiler to produce the same output regardless of
+ // working directory, so use the uncanonicalized relative path.
+ //
+ // It's important to make the mangled names unique because, when CodeView
+ // debug info is in use, the debugger uses mangled type names to distinguish
+ // between otherwise identically named types in anonymous namespaces.
+ //
+ // These symbols are always internal, so there is no need for the hash to
+ // match what MSVC produces. For the same reason, clang is free to change the
+ // hash at any time without breaking compatibility with old versions of clang.
+ // The generated names are intended to look similar to what MSVC generates,
+ // which are something like "?A0x01234567@".
+ SourceManager &SM = Context.getSourceManager();
+ if (const FileEntry *FE = SM.getFileEntryForID(SM.getMainFileID())) {
+ // Truncate the hash so we get 8 characters of hexadecimal.
+ uint32_t TruncatedHash = uint32_t(xxHash64(FE->getName()));
+ AnonymousNamespaceHash = llvm::utohexstr(TruncatedHash);
+ } else {
+ // If we don't have a path to the main file, we'll just use 0.
+ AnonymousNamespaceHash = "0";
+ }
+}
+
bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
LanguageLinkage L = FD->getLanguageLinkage();
@@ -475,7 +514,7 @@ void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD,
mangleFunctionClass(FD);
- mangleFunctionType(FT, FD);
+ mangleFunctionType(FT, FD, false, false);
} else {
Out << '9';
}
@@ -785,7 +824,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
if (NS->isAnonymousNamespace()) {
- Out << "?A@";
+ Out << "?A0x" << Context.getAnonymousNamespaceHash() << '@';
break;
}
}
@@ -905,8 +944,14 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
- case DeclarationName::ObjCMultiArgSelector:
- llvm_unreachable("Can't mangle Objective-C selector names here!");
+ case DeclarationName::ObjCMultiArgSelector: {
+ // This is reachable only when constructing an outlined SEH finally
+ // block. Nothing depends on this mangling and it's used only with
+ // functinos with internal linkage.
+ llvm::SmallString<64> Name;
+ mangleSourceName(Name.str());
+ break;
+ }
case DeclarationName::CXXConstructorName:
if (isStructorDecl(ND)) {
@@ -1027,7 +1072,7 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) {
if (PointersAre64Bit)
Out << 'E';
Out << 'A';
- mangleArtificalTagType(TTK_Struct,
+ mangleArtificialTagType(TTK_Struct,
Discriminate("__block_literal", Discriminator,
ParameterDiscriminator));
Out << "@Z";
@@ -1322,7 +1367,7 @@ void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
// It's a global variable.
Out << '3';
// It's a struct called __s_GUID.
- mangleArtificalTagType(TTK_Struct, "__s_GUID");
+ mangleArtificialTagType(TTK_Struct, "__s_GUID");
// It's const.
Out << 'B';
return;
@@ -1343,9 +1388,16 @@ void MicrosoftCXXNameMangler::mangleTemplateArgs(
assert(TPL->size() == TemplateArgs.size() &&
"size mismatch between args and parms!");
- unsigned Idx = 0;
- for (const TemplateArgument &TA : TemplateArgs.asArray())
- mangleTemplateArg(TD, TA, TPL->getParam(Idx++));
+ for (size_t i = 0; i < TemplateArgs.size(); ++i) {
+ const TemplateArgument &TA = TemplateArgs[i];
+
+ // Separate consecutive packs by $$Z.
+ if (i > 0 && TA.getKind() == TemplateArgument::Pack &&
+ TemplateArgs[i - 1].getKind() == TemplateArgument::Pack)
+ Out << "$$Z";
+
+ mangleTemplateArg(TD, TA, TPL->getParam(i));
+ }
}
void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
@@ -1471,9 +1523,9 @@ void MicrosoftCXXNameMangler::mangleObjCProtocol(const ObjCProtocolDecl *PD) {
Stream << "?$";
Extra.mangleSourceName("Protocol");
- Extra.mangleArtificalTagType(TTK_Struct, PD->getName());
+ Extra.mangleArtificialTagType(TTK_Struct, PD->getName());
- mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__ObjC"});
+ mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__ObjC"});
}
void MicrosoftCXXNameMangler::mangleObjCLifetime(const QualType Type,
@@ -1502,7 +1554,24 @@ void MicrosoftCXXNameMangler::mangleObjCLifetime(const QualType Type,
Extra.manglePointerExtQualifiers(Quals, Type);
Extra.mangleType(Type, Range);
- mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__ObjC"});
+ mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__ObjC"});
+}
+
+void MicrosoftCXXNameMangler::mangleObjCKindOfType(const ObjCObjectType *T,
+ Qualifiers Quals,
+ SourceRange Range) {
+ llvm::SmallString<64> TemplateMangling;
+ llvm::raw_svector_ostream Stream(TemplateMangling);
+ MicrosoftCXXNameMangler Extra(Context, Stream);
+
+ Stream << "?$";
+ Extra.mangleSourceName("KindOf");
+ Extra.mangleType(QualType(T, 0)
+ .stripObjCKindOfType(getASTContext())
+ ->getAs<ObjCObjectType>(),
+ Quals, Range);
+
+ mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__ObjC"});
}
void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals,
@@ -1698,7 +1767,7 @@ void MicrosoftCXXNameMangler::manglePassObjectSizeArg(
ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr);
if (Found == TypeBackReferences.end()) {
- mangleArtificalTagType(TTK_Enum, "__pass_object_size" + llvm::utostr(Type),
+ mangleArtificialTagType(TTK_Enum, "__pass_object_size" + llvm::utostr(Type),
{"__clang"});
if (TypeBackReferences.size() < 10) {
@@ -1710,12 +1779,77 @@ void MicrosoftCXXNameMangler::manglePassObjectSizeArg(
}
}
+void MicrosoftCXXNameMangler::mangleAddressSpaceType(QualType T,
+ Qualifiers Quals,
+ SourceRange Range) {
+ // Address space is mangled as an unqualified templated type in the __clang
+ // namespace. The demangled version of this is:
+ // In the case of a language specific address space:
+ // __clang::struct _AS[language_addr_space]<Type>
+ // where:
+ // <language_addr_space> ::= <OpenCL-addrspace> | <CUDA-addrspace>
+ // <OpenCL-addrspace> ::= "CL" [ "global" | "local" | "constant" |
+ // "private"| "generic" ]
+ // <CUDA-addrspace> ::= "CU" [ "device" | "constant" | "shared" ]
+ // Note that the above were chosen to match the Itanium mangling for this.
+ //
+ // In the case of a non-language specific address space:
+ // __clang::struct _AS<TargetAS, Type>
+ assert(Quals.hasAddressSpace() && "Not valid without address space");
+ llvm::SmallString<32> ASMangling;
+ llvm::raw_svector_ostream Stream(ASMangling);
+ MicrosoftCXXNameMangler Extra(Context, Stream);
+ Stream << "?$";
+
+ LangAS AS = Quals.getAddressSpace();
+ if (Context.getASTContext().addressSpaceMapManglingFor(AS)) {
+ unsigned TargetAS = Context.getASTContext().getTargetAddressSpace(AS);
+ Extra.mangleSourceName("_AS");
+ Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(TargetAS),
+ /*IsBoolean*/ false);
+ } else {
+ switch (AS) {
+ default:
+ llvm_unreachable("Not a language specific address space");
+ case LangAS::opencl_global:
+ Extra.mangleSourceName("_ASCLglobal");
+ break;
+ case LangAS::opencl_local:
+ Extra.mangleSourceName("_ASCLlocal");
+ break;
+ case LangAS::opencl_constant:
+ Extra.mangleSourceName("_ASCLconstant");
+ break;
+ case LangAS::opencl_private:
+ Extra.mangleSourceName("_ASCLprivate");
+ break;
+ case LangAS::opencl_generic:
+ Extra.mangleSourceName("_ASCLgeneric");
+ break;
+ case LangAS::cuda_device:
+ Extra.mangleSourceName("_ASCUdevice");
+ break;
+ case LangAS::cuda_constant:
+ Extra.mangleSourceName("_ASCUconstant");
+ break;
+ case LangAS::cuda_shared:
+ Extra.mangleSourceName("_ASCUshared");
+ break;
+ }
+ }
+
+ Extra.mangleType(T, Range, QMM_Escape);
+ mangleQualifiers(Qualifiers(), false);
+ mangleArtificialTagType(TTK_Struct, ASMangling, {"__clang"});
+}
+
void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
QualifierMangleMode QMM) {
// Don't use the canonical types. MSVC includes things like 'const' on
// pointer arguments to function pointers that canonicalization strips away.
T = T.getDesugaredType(getASTContext());
Qualifiers Quals = T.getLocalQualifiers();
+
if (const ArrayType *AT = getASTContext().getAsArrayType(T)) {
// If there were any Quals, getAsArrayType() pushed them onto the array
// element type.
@@ -1884,13 +2018,13 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
llvm_unreachable("placeholder types shouldn't get to name mangling");
case BuiltinType::ObjCId:
- mangleArtificalTagType(TTK_Struct, "objc_object");
+ mangleArtificialTagType(TTK_Struct, "objc_object");
break;
case BuiltinType::ObjCClass:
- mangleArtificalTagType(TTK_Struct, "objc_class");
+ mangleArtificialTagType(TTK_Struct, "objc_class");
break;
case BuiltinType::ObjCSel:
- mangleArtificalTagType(TTK_Struct, "objc_selector");
+ mangleArtificialTagType(TTK_Struct, "objc_selector");
break;
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
@@ -1900,35 +2034,40 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
#include "clang/Basic/OpenCLImageTypes.def"
case BuiltinType::OCLSampler:
Out << "PA";
- mangleArtificalTagType(TTK_Struct, "ocl_sampler");
+ mangleArtificialTagType(TTK_Struct, "ocl_sampler");
break;
case BuiltinType::OCLEvent:
Out << "PA";
- mangleArtificalTagType(TTK_Struct, "ocl_event");
+ mangleArtificialTagType(TTK_Struct, "ocl_event");
break;
case BuiltinType::OCLClkEvent:
Out << "PA";
- mangleArtificalTagType(TTK_Struct, "ocl_clkevent");
+ mangleArtificialTagType(TTK_Struct, "ocl_clkevent");
break;
case BuiltinType::OCLQueue:
Out << "PA";
- mangleArtificalTagType(TTK_Struct, "ocl_queue");
+ mangleArtificialTagType(TTK_Struct, "ocl_queue");
break;
case BuiltinType::OCLReserveID:
Out << "PA";
- mangleArtificalTagType(TTK_Struct, "ocl_reserveid");
+ mangleArtificialTagType(TTK_Struct, "ocl_reserveid");
+ break;
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id: \
+ mangleArtificialTagType(TTK_Struct, "ocl_" #ExtType); \
break;
+#include "clang/Basic/OpenCLExtensionTypes.def"
case BuiltinType::NullPtr:
Out << "$$T";
break;
case BuiltinType::Float16:
- mangleArtificalTagType(TTK_Struct, "_Float16", {"__clang"});
+ mangleArtificialTagType(TTK_Struct, "_Float16", {"__clang"});
break;
case BuiltinType::Half:
- mangleArtificalTagType(TTK_Struct, "_Half", {"__clang"});
+ mangleArtificialTagType(TTK_Struct, "_Half", {"__clang"});
break;
case BuiltinType::ShortAccum:
@@ -1989,7 +2128,8 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T,
void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
const FunctionDecl *D,
- bool ForceThisQuals) {
+ bool ForceThisQuals,
+ bool MangleExceptionSpec) {
// <function-type> ::= <this-cvr-qualifiers> <calling-convention>
// <return-type> <argument-list> <throw-spec>
const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(T);
@@ -2021,7 +2161,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
// If this is a C++ instance method, mangle the CVR qualifiers for the
// this pointer.
if (HasThisQuals) {
- Qualifiers Quals = Qualifiers::fromCVRUMask(Proto->getTypeQuals());
+ Qualifiers Quals = Proto->getTypeQuals();
manglePointerExtQualifiers(Quals, /*PointeeType=*/QualType());
mangleRefQualifier(Proto->getRefQualifier());
mangleQualifiers(Quals, /*IsMember=*/false);
@@ -2122,7 +2262,12 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
Out << '@';
}
- mangleThrowSpecification(Proto);
+ if (MangleExceptionSpec && getASTContext().getLangOpts().CPlusPlus17 &&
+ getASTContext().getLangOpts().isCompatibleWithMSVC(
+ LangOptions::MSVC2017_5))
+ mangleThrowSpecification(Proto);
+ else
+ Out << 'Z';
}
void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
@@ -2227,15 +2372,15 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {
void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
mangleCallingConvention(T->getCallConv());
}
+
void MicrosoftCXXNameMangler::mangleThrowSpecification(
const FunctionProtoType *FT) {
- // <throw-spec> ::= Z # throw(...) (default)
- // ::= @ # throw() or __declspec/__attribute__((nothrow))
- // ::= <type>+
- // NOTE: Since the Microsoft compiler ignores throw specifications, they are
- // all actually mangled as 'Z'. (They're ignored because their associated
- // functionality isn't implemented, and probably never will be.)
- Out << 'Z';
+ // <throw-spec> ::= Z # (default)
+ // ::= _E # noexcept
+ if (FT->canThrow())
+ Out << 'Z';
+ else
+ Out << "_E";
}
void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T,
@@ -2285,7 +2430,7 @@ void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) {
}
// If you add a call to this, consider updating isArtificialTagType() too.
-void MicrosoftCXXNameMangler::mangleArtificalTagType(
+void MicrosoftCXXNameMangler::mangleArtificialTagType(
TagTypeKind TK, StringRef UnqualifiedName,
ArrayRef<StringRef> NestedNames) {
// <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @
@@ -2416,7 +2561,11 @@ void MicrosoftCXXNameMangler::mangleType(const PointerType *T, Qualifiers Quals,
QualType PointeeType = T->getPointeeType();
manglePointerCVQualifiers(Quals);
manglePointerExtQualifiers(Quals, PointeeType);
- mangleType(PointeeType, Range);
+
+ if (PointeeType.getQualifiers().hasAddressSpace())
+ mangleAddressSpaceType(PointeeType, PointeeType.getQualifiers(), Range);
+ else
+ mangleType(PointeeType, Range);
}
void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,
@@ -2471,10 +2620,10 @@ void MicrosoftCXXNameMangler::mangleType(const ComplexType *T, Qualifiers,
Extra.mangleSourceName("_Complex");
Extra.mangleType(ElementType, Range, QMM_Escape);
- mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__clang"});
+ mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__clang"});
}
-// Returns true for types that mangleArtificalTagType() gets called for with
+// Returns true for types that mangleArtificialTagType() gets called for with
// TTK_Union, TTK_Struct, TTK_Class and where compatibility with MSVC's
// mangling matters.
// (It doesn't matter for Objective-C types and the like that cl.exe doesn't
@@ -2487,7 +2636,7 @@ bool MicrosoftCXXNameMangler::isArtificialTagType(QualType T) const {
case Type::Vector: {
// For ABI compatibility only __m64, __m128(id), and __m256(id) matter,
- // but since mangleType(VectorType*) always calls mangleArtificalTagType()
+ // but since mangleType(VectorType*) always calls mangleArtificialTagType()
// just always return true (the other vector types are clang-only).
return true;
}
@@ -2502,18 +2651,20 @@ void MicrosoftCXXNameMangler::mangleType(const VectorType *T, Qualifiers Quals,
// Pattern match exactly the typedefs in our intrinsic headers. Anything that
// doesn't match the Intel types uses a custom mangling below.
size_t OutSizeBefore = Out.tell();
- llvm::Triple::ArchType AT =
- getASTContext().getTargetInfo().getTriple().getArch();
- if (AT == llvm::Triple::x86 || AT == llvm::Triple::x86_64) {
- if (Width == 64 && ET->getKind() == BuiltinType::LongLong) {
- mangleArtificalTagType(TTK_Union, "__m64");
- } else if (Width >= 128) {
- if (ET->getKind() == BuiltinType::Float)
- mangleArtificalTagType(TTK_Union, "__m" + llvm::utostr(Width));
- else if (ET->getKind() == BuiltinType::LongLong)
- mangleArtificalTagType(TTK_Union, "__m" + llvm::utostr(Width) + 'i');
- else if (ET->getKind() == BuiltinType::Double)
- mangleArtificalTagType(TTK_Struct, "__m" + llvm::utostr(Width) + 'd');
+ if (!isa<ExtVectorType>(T)) {
+ llvm::Triple::ArchType AT =
+ getASTContext().getTargetInfo().getTriple().getArch();
+ if (AT == llvm::Triple::x86 || AT == llvm::Triple::x86_64) {
+ if (Width == 64 && ET->getKind() == BuiltinType::LongLong) {
+ mangleArtificialTagType(TTK_Union, "__m64");
+ } else if (Width >= 128) {
+ if (ET->getKind() == BuiltinType::Float)
+ mangleArtificialTagType(TTK_Union, "__m" + llvm::utostr(Width));
+ else if (ET->getKind() == BuiltinType::LongLong)
+ mangleArtificialTagType(TTK_Union, "__m" + llvm::utostr(Width) + 'i');
+ else if (ET->getKind() == BuiltinType::Double)
+ mangleArtificialTagType(TTK_Struct, "__m" + llvm::utostr(Width) + 'd');
+ }
}
}
@@ -2532,7 +2683,7 @@ void MicrosoftCXXNameMangler::mangleType(const VectorType *T, Qualifiers Quals,
Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(T->getNumElements()),
/*IsBoolean=*/false);
- mangleArtificalTagType(TTK_Union, TemplateMangling, {"__clang"});
+ mangleArtificialTagType(TTK_Union, TemplateMangling, {"__clang"});
}
}
@@ -2575,9 +2726,12 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, Qualifiers,
mangleName(T->getDecl());
}
-void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers,
- SourceRange Range) {
- if (T->qual_empty())
+void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T,
+ Qualifiers Quals, SourceRange Range) {
+ if (T->isKindOfType())
+ return mangleObjCKindOfType(T, Quals, Range);
+
+ if (T->qual_empty() && !T->isSpecialized())
return mangleType(T->getBaseType(), Range, QMM_Drop);
ArgBackRefMap OuterArgsContext;
@@ -2598,6 +2752,11 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers,
for (const auto &Q : T->quals())
mangleObjCProtocol(Q);
+
+ if (T->isSpecialized())
+ for (const auto &TA : T->getTypeArgs())
+ mangleType(TA, Range, QMM_Drop);
+
Out << '@';
Out << '@';
@@ -2728,7 +2887,7 @@ void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, Qualifiers,
Extra.mangleSourceName("_Atomic");
Extra.mangleType(ValueType, Range, QMM_Escape);
- mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__clang"});
+ mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__clang"});
}
void MicrosoftCXXNameMangler::mangleType(const PipeType *T, Qualifiers,
@@ -2780,14 +2939,14 @@ void MicrosoftMangleContextImpl::mangleCXXName(const NamedDecl *D,
// <vtordisp-shift> ::= <offset-to-vtordisp>
// <vtordispex-shift> ::= <offset-to-vbptr> <vbase-offset-offset>
// <offset-to-vtordisp>
-static void mangleThunkThisAdjustment(const CXXMethodDecl *MD,
+static void mangleThunkThisAdjustment(AccessSpecifier AS,
const ThisAdjustment &Adjustment,
MicrosoftCXXNameMangler &Mangler,
raw_ostream &Out) {
if (!Adjustment.Virtual.isEmpty()) {
Out << '$';
char AccessSpec;
- switch (MD->getAccess()) {
+ switch (AS) {
case AS_none:
llvm_unreachable("Unsupported access specifier");
case AS_private:
@@ -2815,7 +2974,7 @@ static void mangleThunkThisAdjustment(const CXXMethodDecl *MD,
Mangler.mangleNumber(-static_cast<uint32_t>(Adjustment.NonVirtual));
}
} else if (Adjustment.NonVirtual != 0) {
- switch (MD->getAccess()) {
+ switch (AS) {
case AS_none:
llvm_unreachable("Unsupported access specifier");
case AS_private:
@@ -2829,7 +2988,7 @@ static void mangleThunkThisAdjustment(const CXXMethodDecl *MD,
}
Mangler.mangleNumber(-static_cast<uint32_t>(Adjustment.NonVirtual));
} else {
- switch (MD->getAccess()) {
+ switch (AS) {
case AS_none:
llvm_unreachable("Unsupported access specifier");
case AS_private:
@@ -2860,7 +3019,13 @@ void MicrosoftMangleContextImpl::mangleThunk(const CXXMethodDecl *MD,
MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << '?';
Mangler.mangleName(MD);
- mangleThunkThisAdjustment(MD, Thunk.This, Mangler, MHO);
+
+ // Usually the thunk uses the access specifier of the new method, but if this
+ // is a covariant return thunk, then MSVC always uses the public access
+ // specifier, and we do the same.
+ AccessSpecifier AS = Thunk.Return.isEmpty() ? MD->getAccess() : AS_public;
+ mangleThunkThisAdjustment(AS, Thunk.This, Mangler, MHO);
+
if (!Thunk.Return.isEmpty())
assert(Thunk.Method != nullptr &&
"Thunk info should hold the overridee decl");
@@ -2881,7 +3046,7 @@ void MicrosoftMangleContextImpl::mangleCXXDtorThunk(
MicrosoftCXXNameMangler Mangler(*this, MHO, DD, Type);
Mangler.getStream() << "??_E";
Mangler.mangleName(DD->getParent());
- mangleThunkThisAdjustment(DD, Adjustment, Mangler, MHO);
+ mangleThunkThisAdjustment(DD->getAccess(), Adjustment, Mangler, MHO);
Mangler.mangleFunctionType(DD->getType()->castAs<FunctionProtoType>(), DD);
}
@@ -3175,10 +3340,13 @@ void MicrosoftMangleContextImpl::mangleInitFiniStub(const VarDecl *D,
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "??__" << CharCode;
- Mangler.mangleName(D);
if (D->isStaticDataMember()) {
+ Mangler.getStream() << '?';
+ Mangler.mangleName(D);
Mangler.mangleVariableEncoding(D);
- Mangler.getStream() << '@';
+ Mangler.getStream() << "@@";
+ } else {
+ Mangler.mangleName(D);
}
// This is the function class mangling. These stubs are global, non-variadic,
// cdecl functions that return void and take no args.