diff options
Diffstat (limited to 'lib/AST/MicrosoftMangle.cpp')
-rw-r--r-- | lib/AST/MicrosoftMangle.cpp | 302 |
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. |