diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp | 1127 |
1 files changed, 798 insertions, 329 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp index 5256501..e6a6d09 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp @@ -14,17 +14,21 @@ #include "clang/AST/Mangle.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" -#include "clang/AST/CharUnits.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/CharUnits.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/VTableBuilder.h" #include "clang/Basic/ABI.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/TargetInfo.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" +#include "llvm/Support/MathExtras.h" using namespace clang; @@ -71,10 +75,114 @@ static const FunctionDecl *getStructor(const FunctionDecl *fn) { return fn; } +static bool isLambda(const NamedDecl *ND) { + const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND); + if (!Record) + return false; + + return Record->isLambda(); +} + +/// MicrosoftMangleContextImpl - Overrides the default MangleContext for the +/// Microsoft Visual C++ ABI. +class MicrosoftMangleContextImpl : public MicrosoftMangleContext { + typedef std::pair<const DeclContext *, IdentifierInfo *> DiscriminatorKeyTy; + llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator; + llvm::DenseMap<const NamedDecl *, unsigned> Uniquifier; + llvm::DenseMap<const CXXRecordDecl *, unsigned> LambdaIds; + +public: + MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags) + : MicrosoftMangleContext(Context, Diags) {} + bool shouldMangleCXXName(const NamedDecl *D) override; + bool shouldMangleStringLiteral(const StringLiteral *SL) override; + void mangleCXXName(const NamedDecl *D, raw_ostream &Out) override; + void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD, + raw_ostream &) override; + void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, + raw_ostream &) override; + void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, + const ThisAdjustment &ThisAdjustment, + raw_ostream &) override; + void mangleCXXVFTable(const CXXRecordDecl *Derived, + ArrayRef<const CXXRecordDecl *> BasePath, + raw_ostream &Out) override; + void mangleCXXVBTable(const CXXRecordDecl *Derived, + ArrayRef<const CXXRecordDecl *> BasePath, + raw_ostream &Out) override; + void mangleCXXRTTI(QualType T, raw_ostream &Out) override; + void mangleCXXRTTIName(QualType T, raw_ostream &Out) override; + void mangleCXXRTTIBaseClassDescriptor(const CXXRecordDecl *Derived, + uint32_t NVOffset, int32_t VBPtrOffset, + uint32_t VBTableOffset, uint32_t Flags, + raw_ostream &Out) override; + void mangleCXXRTTIBaseClassArray(const CXXRecordDecl *Derived, + raw_ostream &Out) override; + void mangleCXXRTTIClassHierarchyDescriptor(const CXXRecordDecl *Derived, + raw_ostream &Out) override; + void + mangleCXXRTTICompleteObjectLocator(const CXXRecordDecl *Derived, + ArrayRef<const CXXRecordDecl *> BasePath, + raw_ostream &Out) override; + void mangleTypeName(QualType T, raw_ostream &) override; + void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, + raw_ostream &) override; + void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, + raw_ostream &) override; + void mangleReferenceTemporary(const VarDecl *, unsigned ManglingNumber, + raw_ostream &) override; + void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out) override; + void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override; + void mangleDynamicAtExitDestructor(const VarDecl *D, + raw_ostream &Out) override; + void mangleStringLiteral(const StringLiteral *SL, raw_ostream &Out) override; + bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { + // Lambda closure types are already numbered. + if (isLambda(ND)) + return false; + + const DeclContext *DC = getEffectiveDeclContext(ND); + if (!DC->isFunctionOrMethod()) + return false; + + // Use the canonical number for externally visible decls. + if (ND->isExternallyVisible()) { + disc = getASTContext().getManglingNumber(ND); + return true; + } + + // Anonymous tags are already numbered. + if (const TagDecl *Tag = dyn_cast<TagDecl>(ND)) { + if (Tag->getName().empty() && !Tag->getTypedefNameForAnonDecl()) + return false; + } + + // Make up a reasonable number for internal decls. + unsigned &discriminator = Uniquifier[ND]; + if (!discriminator) + discriminator = ++Discriminator[std::make_pair(DC, ND->getIdentifier())]; + disc = discriminator; + return true; + } + + unsigned getLambdaId(const CXXRecordDecl *RD) { + assert(RD->isLambda() && "RD must be a lambda!"); + assert(!RD->isExternallyVisible() && "RD must not be visible!"); + assert(RD->getLambdaManglingNumber() == 0 && + "RD must not have a mangling number!"); + std::pair<llvm::DenseMap<const CXXRecordDecl *, unsigned>::iterator, bool> + Result = LambdaIds.insert(std::make_pair(RD, LambdaIds.size())); + return Result.first->second; + } + +private: + void mangleInitFiniStub(const VarDecl *D, raw_ostream &Out, char CharCode); +}; + /// MicrosoftCXXNameMangler - Manage the mangling of a single name for the /// Microsoft Visual C++ ABI. class MicrosoftCXXNameMangler { - MangleContext &Context; + MicrosoftMangleContextImpl &Context; raw_ostream &Out; /// The "structor" is the top-level declaration being mangled, if @@ -85,9 +193,8 @@ class MicrosoftCXXNameMangler { typedef llvm::StringMap<unsigned> BackRefMap; BackRefMap NameBackReferences; - bool UseNameBackReferences; - typedef llvm::DenseMap<void*, unsigned> ArgBackRefMap; + typedef llvm::DenseMap<void *, unsigned> ArgBackRefMap; ArgBackRefMap TypeBackReferences; ASTContext &getASTContext() const { return Context.getASTContext(); } @@ -99,37 +206,38 @@ class MicrosoftCXXNameMangler { public: enum QualifierMangleMode { QMM_Drop, QMM_Mangle, QMM_Escape, QMM_Result }; - MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_) - : Context(C), Out(Out_), - Structor(0), StructorType(-1), - UseNameBackReferences(true), - PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) == - 64) { } + MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_) + : Context(C), Out(Out_), Structor(nullptr), StructorType(-1), + PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) == + 64) {} - MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_, + MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_, const CXXDestructorDecl *D, CXXDtorType Type) - : Context(C), Out(Out_), - Structor(getStructor(D)), StructorType(Type), - UseNameBackReferences(true), - PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) == - 64) { } + : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), + PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) == + 64) {} raw_ostream &getStream() const { return Out; } void mangle(const NamedDecl *D, StringRef Prefix = "\01?"); void mangleName(const NamedDecl *ND); - void mangleDeclaration(const NamedDecl *ND); void mangleFunctionEncoding(const FunctionDecl *FD); void mangleVariableEncoding(const VarDecl *VD); + void mangleMemberDataPointer(const CXXRecordDecl *RD, const ValueDecl *VD); + void mangleMemberFunctionPointer(const CXXRecordDecl *RD, + const CXXMethodDecl *MD); + void mangleVirtualMemPtrThunk( + const CXXMethodDecl *MD, + const MicrosoftVTableContext::MethodVFTableLocation &ML); void mangleNumber(int64_t Number); void mangleType(QualType T, SourceRange Range, QualifierMangleMode QMM = QMM_Mangle); - void mangleFunctionType(const FunctionType *T, const FunctionDecl *D = 0, + void mangleFunctionType(const FunctionType *T, + const FunctionDecl *D = nullptr, bool ForceInstMethod = false); - void manglePostfix(const DeclContext *DC, bool NoFunction = false); + void mangleNestedName(const NamedDecl *ND); private: - void disableBackReferences() { UseNameBackReferences = false; } void mangleUnqualifiedName(const NamedDecl *ND) { mangleUnqualifiedName(ND, ND->getDeclName()); } @@ -138,13 +246,15 @@ private: void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc); void mangleCXXDtorType(CXXDtorType T); void mangleQualifiers(Qualifiers Quals, bool IsMember); - void manglePointerQualifiers(Qualifiers Quals); + void mangleRefQualifier(RefQualifierKind RefQualifier); + void manglePointerCVQualifiers(Qualifiers Quals); + void manglePointerExtQualifiers(Qualifiers Quals, const Type *PointeeType); void mangleUnscopedTemplateName(const TemplateDecl *ND); - void mangleTemplateInstantiationName(const TemplateDecl *TD, - const TemplateArgumentList &TemplateArgs); + void + mangleTemplateInstantiationName(const TemplateDecl *TD, + const TemplateArgumentList &TemplateArgs); void mangleObjCMethodName(const ObjCMethodDecl *MD); - void mangleLocalName(const FunctionDecl *FD); void mangleArgumentType(QualType T, SourceRange Range); @@ -157,7 +267,7 @@ private: #undef ABSTRACT_TYPE #undef NON_CANONICAL_TYPE #undef TYPE - + void mangleType(const TagDecl *TD); void mangleDecayedArrayType(const ArrayType *T); void mangleArrayType(const ArrayType *T); @@ -171,47 +281,6 @@ private: const TemplateArgumentList &TemplateArgs); void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA); }; - -/// MicrosoftMangleContextImpl - Overrides the default MangleContext for the -/// Microsoft Visual C++ ABI. -class MicrosoftMangleContextImpl : public MicrosoftMangleContext { -public: - MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags) - : MicrosoftMangleContext(Context, Diags) {} - virtual bool shouldMangleCXXName(const NamedDecl *D); - virtual void mangleCXXName(const NamedDecl *D, raw_ostream &Out); - virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD, - uint64_t OffsetInVFTable, - raw_ostream &); - virtual void mangleThunk(const CXXMethodDecl *MD, - const ThunkInfo &Thunk, - raw_ostream &); - virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, - const ThisAdjustment &ThisAdjustment, - raw_ostream &); - virtual void mangleCXXVFTable(const CXXRecordDecl *Derived, - ArrayRef<const CXXRecordDecl *> BasePath, - raw_ostream &Out); - virtual void mangleCXXVBTable(const CXXRecordDecl *Derived, - ArrayRef<const CXXRecordDecl *> BasePath, - raw_ostream &Out); - virtual void mangleCXXRTTI(QualType T, raw_ostream &); - virtual void mangleCXXRTTIName(QualType T, raw_ostream &); - virtual void mangleTypeName(QualType T, raw_ostream &); - virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, - raw_ostream &); - virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, - raw_ostream &); - virtual void mangleReferenceTemporary(const VarDecl *, raw_ostream &); - virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out); - virtual void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out); - virtual void mangleDynamicAtExitDestructor(const VarDecl *D, - raw_ostream &Out); - -private: - void mangleInitFiniStub(const VarDecl *D, raw_ostream &Out, char CharCode); -}; - } bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { @@ -267,8 +336,14 @@ bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { return true; } -void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, - StringRef Prefix) { +bool +MicrosoftMangleContextImpl::shouldMangleStringLiteral(const StringLiteral *SL) { + return SL->isAscii() || SL->isWide(); + // TODO: This needs to be updated when MSVC gains support for Unicode + // literals. +} + +void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) { // MSVC doesn't mangle C++ names the same way it mangles extern "C" names. // Therefore it's really important that we don't decorate the // name with leading underscores or leading/trailing at signs. So, by @@ -286,10 +361,9 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, // TODO: Fields? Can MSVC even mangle them? // Issue a diagnostic for now. DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle this declaration yet"); - Diags.Report(D->getLocation(), DiagID) - << D->getSourceRange(); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, "cannot mangle this declaration yet"); + Diags.Report(D->getLocation(), DiagID) << D->getSourceRange(); } } @@ -324,7 +398,7 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) { // ::= 2 # public static member // ::= 3 # global // ::= 4 # static local - + // The first character in the encoding (after the name) is the storage class. if (VD->isStaticDataMember()) { // If it's a static member, it also encodes the access level. @@ -344,13 +418,13 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) { // ::= <type> <pointee-cvr-qualifiers> # pointers, references // Pointers and references are odd. The type of 'int * const foo;' gets // mangled as 'QAHA' instead of 'PAHB', for example. - TypeLoc TL = VD->getTypeSourceInfo()->getTypeLoc(); - QualType Ty = TL.getType(); + SourceRange SR = VD->getSourceRange(); + QualType Ty = VD->getType(); if (Ty->isPointerType() || Ty->isReferenceType() || Ty->isMemberPointerType()) { - mangleType(Ty, TL.getSourceRange(), QMM_Drop); - if (PointersAre64Bit) - Out << 'E'; + mangleType(Ty, SR, QMM_Drop); + manglePointerExtQualifiers( + Ty.getDesugaredType(getASTContext()).getLocalQualifiers(), nullptr); if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()) { mangleQualifiers(MPT->getPointeeType().getQualifiers(), true); // Member pointers are suffixed with a back reference to the member @@ -366,25 +440,137 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) { else mangleQualifiers(Ty.getQualifiers(), false); } else { - mangleType(Ty, TL.getSourceRange(), QMM_Drop); + mangleType(Ty, SR, QMM_Drop); mangleQualifiers(Ty.getLocalQualifiers(), false); } } +void MicrosoftCXXNameMangler::mangleMemberDataPointer(const CXXRecordDecl *RD, + const ValueDecl *VD) { + // <member-data-pointer> ::= <integer-literal> + // ::= $F <number> <number> + // ::= $G <number> <number> <number> + + int64_t FieldOffset; + int64_t VBTableOffset; + MSInheritanceAttr::Spelling IM = RD->getMSInheritanceModel(); + if (VD) { + FieldOffset = getASTContext().getFieldOffset(VD); + assert(FieldOffset % getASTContext().getCharWidth() == 0 && + "cannot take address of bitfield"); + FieldOffset /= getASTContext().getCharWidth(); + + VBTableOffset = 0; + } else { + FieldOffset = RD->nullFieldOffsetIsZero() ? 0 : -1; + + VBTableOffset = -1; + } + + char Code = '\0'; + switch (IM) { + case MSInheritanceAttr::Keyword_single_inheritance: Code = '0'; break; + case MSInheritanceAttr::Keyword_multiple_inheritance: Code = '0'; break; + case MSInheritanceAttr::Keyword_virtual_inheritance: Code = 'F'; break; + case MSInheritanceAttr::Keyword_unspecified_inheritance: Code = 'G'; break; + } + + Out << '$' << Code; + + mangleNumber(FieldOffset); + + // The C++ standard doesn't allow base-to-derived member pointer conversions + // in template parameter contexts, so the vbptr offset of data member pointers + // is always zero. + if (MSInheritanceAttr::hasVBPtrOffsetField(IM)) + mangleNumber(0); + if (MSInheritanceAttr::hasVBTableOffsetField(IM)) + mangleNumber(VBTableOffset); +} + +void +MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD, + const CXXMethodDecl *MD) { + // <member-function-pointer> ::= $1? <name> + // ::= $H? <name> <number> + // ::= $I? <name> <number> <number> + // ::= $J? <name> <number> <number> <number> + + MSInheritanceAttr::Spelling IM = RD->getMSInheritanceModel(); + + char Code = '\0'; + switch (IM) { + case MSInheritanceAttr::Keyword_single_inheritance: Code = '1'; break; + case MSInheritanceAttr::Keyword_multiple_inheritance: Code = 'H'; break; + case MSInheritanceAttr::Keyword_virtual_inheritance: Code = 'I'; break; + case MSInheritanceAttr::Keyword_unspecified_inheritance: Code = 'J'; break; + } + + // If non-virtual, mangle the name. If virtual, mangle as a virtual memptr + // thunk. + uint64_t NVOffset = 0; + uint64_t VBTableOffset = 0; + uint64_t VBPtrOffset = 0; + if (MD) { + Out << '$' << Code << '?'; + if (MD->isVirtual()) { + MicrosoftVTableContext *VTContext = + cast<MicrosoftVTableContext>(getASTContext().getVTableContext()); + const MicrosoftVTableContext::MethodVFTableLocation &ML = + VTContext->getMethodVFTableLocation(GlobalDecl(MD)); + mangleVirtualMemPtrThunk(MD, ML); + NVOffset = ML.VFPtrOffset.getQuantity(); + VBTableOffset = ML.VBTableIndex * 4; + if (ML.VBase) { + const ASTRecordLayout &Layout = getASTContext().getASTRecordLayout(RD); + VBPtrOffset = Layout.getVBPtrOffset().getQuantity(); + } + } else { + mangleName(MD); + mangleFunctionEncoding(MD); + } + } else { + // Null single inheritance member functions are encoded as a simple nullptr. + if (IM == MSInheritanceAttr::Keyword_single_inheritance) { + Out << "$0A@"; + return; + } + if (IM == MSInheritanceAttr::Keyword_unspecified_inheritance) + VBTableOffset = -1; + Out << '$' << Code; + } + + if (MSInheritanceAttr::hasNVOffsetField(/*IsMemberFunction=*/true, IM)) + mangleNumber(NVOffset); + if (MSInheritanceAttr::hasVBPtrOffsetField(IM)) + mangleNumber(VBPtrOffset); + if (MSInheritanceAttr::hasVBTableOffsetField(IM)) + mangleNumber(VBTableOffset); +} + +void MicrosoftCXXNameMangler::mangleVirtualMemPtrThunk( + const CXXMethodDecl *MD, + const MicrosoftVTableContext::MethodVFTableLocation &ML) { + // Get the vftable offset. + CharUnits PointerWidth = getASTContext().toCharUnitsFromBits( + getASTContext().getTargetInfo().getPointerWidth(0)); + uint64_t OffsetInVFTable = ML.Index * PointerWidth.getQuantity(); + + Out << "?_9"; + mangleName(MD->getParent()); + Out << "$B"; + mangleNumber(OffsetInVFTable); + Out << 'A'; + Out << (PointersAre64Bit ? 'A' : 'E'); +} + void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) { // <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @ - const DeclContext *DC = ND->getDeclContext(); // Always start with the unqualified name. - mangleUnqualifiedName(ND); - - // If this is an extern variable declared locally, the relevant DeclContext - // is that of the containing namespace, or the translation unit. - if (isa<FunctionDecl>(DC) && ND->hasLinkage()) - while (!DC->isNamespace() && !DC->isTranslationUnit()) - DC = DC->getParent(); + mangleUnqualifiedName(ND); - manglePostfix(DC); + mangleNestedName(ND); // Terminate the whole name with an '@'. Out << '@'; @@ -412,8 +598,8 @@ void MicrosoftCXXNameMangler::mangleNumber(int64_t Number) { // in the range of ASCII characters 'A' to 'P'. // The number 0x123450 would be encoded as 'BCDEFA' char EncodedNumberBuffer[sizeof(uint64_t) * 2]; - llvm::MutableArrayRef<char> BufferRef(EncodedNumberBuffer); - llvm::MutableArrayRef<char>::reverse_iterator I = BufferRef.rbegin(); + MutableArrayRef<char> BufferRef(EncodedNumberBuffer); + MutableArrayRef<char>::reverse_iterator I = BufferRef.rbegin(); for (; Value != 0; Value >>= 4) *I++ = 'A' + (Value & 0xf); Out.write(I.base(), I - BufferRef.rbegin()); @@ -424,7 +610,7 @@ void MicrosoftCXXNameMangler::mangleNumber(int64_t Number) { static const TemplateDecl * isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { // Check if we have a function template. - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){ + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { if (const TemplateDecl *TD = FD->getPrimaryTemplate()) { TemplateArgs = FD->getTemplateSpecializationArgs(); return TD; @@ -433,24 +619,30 @@ isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { // Check if we have a class template. if (const ClassTemplateSpecializationDecl *Spec = - dyn_cast<ClassTemplateSpecializationDecl>(ND)) { + dyn_cast<ClassTemplateSpecializationDecl>(ND)) { + TemplateArgs = &Spec->getTemplateArgs(); + return Spec->getSpecializedTemplate(); + } + + // Check if we have a variable template. + if (const VarTemplateSpecializationDecl *Spec = + dyn_cast<VarTemplateSpecializationDecl>(ND)) { TemplateArgs = &Spec->getTemplateArgs(); return Spec->getSpecializedTemplate(); } - return 0; + return nullptr; } -void -MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, - DeclarationName Name) { +void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, + DeclarationName Name) { // <unqualified-name> ::= <operator-name> // ::= <ctor-dtor-name> // ::= <source-name> // ::= <template-name> // Check if we have a template. - const TemplateArgumentList *TemplateArgs = 0; + const TemplateArgumentList *TemplateArgs = nullptr; if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { // Function templates aren't considered for name back referencing. This // makes sense since function templates aren't likely to occur multiple @@ -458,10 +650,10 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // FIXME: Test alias template mangling with MSVC 2013. if (!isa<ClassTemplateDecl>(TD)) { mangleTemplateInstantiationName(TD, *TemplateArgs); + Out << '@'; return; } - // We have a class template. // Here comes the tricky thing: if we need to mangle something like // void foo(A::X<Y>, B::X<Y>), // the X<Y> part is aliased. However, if you need to mangle @@ -473,30 +665,17 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // type [ -> template-parameters] // \-> namespace[s] // What we do is we create a new mangler, mangle the same type (without - // a namespace suffix) using the extra mangler with back references - // disabled (to avoid infinite recursion) and then use the mangled type - // name as a key to check the mangling of different types for aliasing. - - std::string BackReferenceKey; - BackRefMap::iterator Found; - if (UseNameBackReferences) { - llvm::raw_string_ostream Stream(BackReferenceKey); - MicrosoftCXXNameMangler Extra(Context, Stream); - Extra.disableBackReferences(); - Extra.mangleUnqualifiedName(ND, Name); - Stream.flush(); - - Found = NameBackReferences.find(BackReferenceKey); - } - if (!UseNameBackReferences || Found == NameBackReferences.end()) { - mangleTemplateInstantiationName(TD, *TemplateArgs); - if (UseNameBackReferences && NameBackReferences.size() < 10) { - size_t Size = NameBackReferences.size(); - NameBackReferences[BackReferenceKey] = Size; - } - } else { - Out << Found->second; - } + // a namespace suffix) to a string using the extra mangler and then use + // the mangled type name as a key to check the mangling of different types + // for aliasing. + + llvm::SmallString<64> TemplateMangling; + llvm::raw_svector_ostream Stream(TemplateMangling); + MicrosoftCXXNameMangler Extra(Context, Stream); + Extra.mangleTemplateInstantiationName(TD, *TemplateArgs); + Stream.flush(); + + mangleSourceName(TemplateMangling); return; } @@ -506,17 +685,31 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, mangleSourceName(II->getName()); break; } - + // Otherwise, an anonymous entity. We must have a declaration. assert(ND && "mangling empty name without declaration"); - + if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) { if (NS->isAnonymousNamespace()) { Out << "?A@"; break; } } - + + if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) { + // We must have an anonymous union or struct declaration. + const CXXRecordDecl *RD = VD->getType()->getAsCXXRecordDecl(); + assert(RD && "expected variable decl to have a record type"); + // Anonymous types with no tag or typedef get the name of their + // declarator mangled in. If they have no declarator, number them with + // a $S prefix. + llvm::SmallString<64> Name("$S"); + // Get a unique id for the anonymous struct. + Name += llvm::utostr(Context.getAnonymousStructId(RD) + 1); + mangleSourceName(Name.str()); + break; + } + // We must have an anonymous struct. const TagDecl *TD = cast<TagDecl>(ND); if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) { @@ -528,26 +721,43 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, break; } + if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) { + if (Record->isLambda()) { + llvm::SmallString<10> Name("<lambda_"); + unsigned LambdaId; + if (Record->getLambdaManglingNumber()) + LambdaId = Record->getLambdaManglingNumber(); + else + LambdaId = Context.getLambdaId(Record); + + Name += llvm::utostr(LambdaId); + Name += ">"; + + mangleSourceName(Name); + break; + } + } + + llvm::SmallString<64> Name("<unnamed-type-"); if (TD->hasDeclaratorForAnonDecl()) { // Anonymous types with no tag or typedef get the name of their - // declarator mangled in. - llvm::SmallString<64> Name("<unnamed-type-"); + // declarator mangled in if they have one. Name += TD->getDeclaratorForAnonDecl()->getName(); - Name += ">"; - mangleSourceName(Name.str()); } else { - // Anonymous types with no tag, no typedef, or declarator get - // '<unnamed-tag>'. - mangleSourceName("<unnamed-tag>"); + // Otherwise, number the types using a $S prefix. + Name += "$S"; + Name += llvm::utostr(Context.getAnonymousStructId(TD)); } + Name += ">"; + mangleSourceName(Name.str()); break; } - + case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: llvm_unreachable("Can't mangle Objective-C selector names here!"); - + case DeclarationName::CXXConstructorName: if (ND == Structor) { assert(StructorType == Ctor_Complete && @@ -555,7 +765,7 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, } Out << "?0"; break; - + case DeclarationName::CXXDestructorName: if (ND == Structor) // If the named decl is the C++ destructor we're mangling, @@ -566,70 +776,69 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // class with a destructor is declared within a destructor. mangleCXXDtorType(Dtor_Base); break; - + case DeclarationName::CXXConversionFunctionName: // <operator-name> ::= ?B # (cast) // The target type is encoded as the return type. Out << "?B"; break; - + case DeclarationName::CXXOperatorName: mangleOperatorName(Name.getCXXOverloadedOperator(), ND->getLocation()); break; - + case DeclarationName::CXXLiteralOperatorName: { - // FIXME: Was this added in VS2010? Does MS even know how to mangle this? - DiagnosticsEngine Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle this literal operator yet"); - Diags.Report(ND->getLocation(), DiagID); + Out << "?__K"; + mangleSourceName(Name.getCXXLiteralIdentifier()->getName()); break; } - + case DeclarationName::CXXUsingDirective: llvm_unreachable("Can't mangle a using directive name!"); } } -void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC, - bool NoFunction) { +void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) { // <postfix> ::= <unqualified-name> [<postfix>] // ::= <substitution> [<postfix>] - - if (!DC) return; - - while (isa<LinkageSpecDecl>(DC)) - DC = DC->getParent(); - - if (DC->isTranslationUnit()) + if (isLambda(ND)) return; - if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) { - DiagnosticsEngine Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle a local inside this block yet"); - Diags.Report(BD->getLocation(), DiagID); + const DeclContext *DC = ND->getDeclContext(); - // FIXME: This is completely, utterly, wrong; see ItaniumMangle - // for how this should be done. - Out << "__block_invoke" << Context.getBlockId(BD, false); - Out << '@'; - return manglePostfix(DC->getParent(), NoFunction); - } else if (isa<CapturedDecl>(DC)) { - // Skip CapturedDecl context. - manglePostfix(DC->getParent(), NoFunction); - return; - } + while (!DC->isTranslationUnit()) { + if (isa<TagDecl>(ND) || isa<VarDecl>(ND)) { + unsigned Disc; + if (Context.getNextDiscriminator(ND, Disc)) { + Out << '?'; + mangleNumber(Disc); + Out << '?'; + } + } - if (NoFunction && (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC))) - return; - else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) - mangleObjCMethodName(Method); - else if (const FunctionDecl *Func = dyn_cast<FunctionDecl>(DC)) - mangleLocalName(Func); - else { - mangleUnqualifiedName(cast<NamedDecl>(DC)); - manglePostfix(DC->getParent(), NoFunction); + if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = + Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle a local inside this block yet"); + Diags.Report(BD->getLocation(), DiagID); + + // FIXME: This is completely, utterly, wrong; see ItaniumMangle + // for how this should be done. + Out << "__block_invoke" << Context.getBlockId(BD, false); + Out << '@'; + continue; + } else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) { + mangleObjCMethodName(Method); + } else if (isa<NamedDecl>(DC)) { + ND = cast<NamedDecl>(DC); + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { + mangle(FD, "?"); + break; + } else + mangleUnqualifiedName(ND); + } + DC = DC->getParent(); } } @@ -768,7 +977,7 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, case OO_Array_New: Out << "?_U"; break; // <operator-name> ::= ?_V # delete[] case OO_Array_Delete: Out << "?_V"; break; - + case OO_Conditional: { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -776,7 +985,7 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, Diags.Report(Loc, DiagID); break; } - + case OO_None: case NUM_OVERLOADED_OPERATORS: llvm_unreachable("Not an overloaded operator"); @@ -786,14 +995,19 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, void MicrosoftCXXNameMangler::mangleSourceName(StringRef Name) { // <source name> ::= <identifier> @ BackRefMap::iterator Found; - if (UseNameBackReferences) + if (NameBackReferences.size() < 10) { + size_t Size = NameBackReferences.size(); + bool Inserted; + std::tie(Found, Inserted) = + NameBackReferences.insert(std::make_pair(Name, Size)); + if (Inserted) + Found = NameBackReferences.end(); + } else { Found = NameBackReferences.find(Name); - if (!UseNameBackReferences || Found == NameBackReferences.end()) { + } + + if (Found == NameBackReferences.end()) { Out << Name << '@'; - if (UseNameBackReferences && NameBackReferences.size() < 10) { - size_t Size = NameBackReferences.size(); - NameBackReferences[Name] = Size; - } } else { Out << Found->second; } @@ -803,47 +1017,8 @@ void MicrosoftCXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) { Context.mangleObjCMethodName(MD, Out); } -// Find out how many function decls live above this one and return an integer -// suitable for use as the number in a numbered anonymous scope. -// TODO: Memoize. -static unsigned getLocalNestingLevel(const FunctionDecl *FD) { - const DeclContext *DC = FD->getParent(); - int level = 1; - - while (DC && !DC->isTranslationUnit()) { - if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)) level++; - DC = DC->getParent(); - } - - return 2*level; -} - -void MicrosoftCXXNameMangler::mangleLocalName(const FunctionDecl *FD) { - // <nested-name> ::= <numbered-anonymous-scope> ? <mangled-name> - // <numbered-anonymous-scope> ::= ? <number> - // Even though the name is rendered in reverse order (e.g. - // A::B::C is rendered as C@B@A), VC numbers the scopes from outermost to - // innermost. So a method bar in class C local to function foo gets mangled - // as something like: - // ?bar@C@?1??foo@@YAXXZ@QAEXXZ - // This is more apparent when you have a type nested inside a method of a - // type nested inside a function. A method baz in class D local to method - // bar of class C local to function foo gets mangled as: - // ?baz@D@?3??bar@C@?1??foo@@YAXXZ@QAEXXZ@QAEXXZ - // This scheme is general enough to support GCC-style nested - // functions. You could have a method baz of class C inside a function bar - // inside a function foo, like so: - // ?baz@C@?3??bar@?1??foo@@YAXXZ@YAXXZ@QAEXXZ - unsigned NestLevel = getLocalNestingLevel(FD); - Out << '?'; - mangleNumber(NestLevel); - Out << '?'; - mangle(FD, "?"); -} - void MicrosoftCXXNameMangler::mangleTemplateInstantiationName( - const TemplateDecl *TD, - const TemplateArgumentList &TemplateArgs) { + const TemplateDecl *TD, const TemplateArgumentList &TemplateArgs) { // <template-name> ::= <unscoped-template-name> <template-args> // ::= <substitution> // Always start with the unqualified name. @@ -869,9 +1044,8 @@ MicrosoftCXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *TD) { mangleUnqualifiedName(TD); } -void -MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value, - bool IsBoolean) { +void MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value, + bool IsBoolean) { // <integer-literal> ::= $0 <number> Out << "$0"; // Make sure booleans are encoded as 0/1. @@ -881,8 +1055,7 @@ MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value, mangleNumber(Value.getSExtValue()); } -void -MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { +void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { // See if this is a constant expression. llvm::APSInt Value; if (E->isIntegerConstantExpr(Value, Context.getASTContext())) { @@ -890,7 +1063,10 @@ MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { return; } - const CXXUuidofExpr *UE = 0; + // Look through no-op casts like template parameter substitutions. + E = E->IgnoreParenNoopCasts(Context.getASTContext()); + + const CXXUuidofExpr *UE = nullptr; if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) { if (UO->getOpcode() == UO_AddrOf) UE = dyn_cast<CXXUuidofExpr>(UO->getSubExpr()); @@ -919,26 +1095,30 @@ MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { // As bad as this diagnostic is, it's better than crashing. DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot yet mangle expression type %0"); - Diags.Report(E->getExprLoc(), DiagID) - << E->getStmtClassName() << E->getSourceRange(); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, "cannot yet mangle expression type %0"); + Diags.Report(E->getExprLoc(), DiagID) << E->getStmtClassName() + << E->getSourceRange(); } -void -MicrosoftCXXNameMangler::mangleTemplateArgs(const TemplateDecl *TD, - const TemplateArgumentList &TemplateArgs) { - // <template-args> ::= {<type> | <integer-literal>}+ @ - unsigned NumTemplateArgs = TemplateArgs.size(); - for (unsigned i = 0; i < NumTemplateArgs; ++i) { - const TemplateArgument &TA = TemplateArgs[i]; +void MicrosoftCXXNameMangler::mangleTemplateArgs( + const TemplateDecl *TD, const TemplateArgumentList &TemplateArgs) { + // <template-args> ::= <template-arg>+ + for (const TemplateArgument &TA : TemplateArgs.asArray()) mangleTemplateArg(TD, TA); - } - Out << '@'; } void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA) { + // <template-arg> ::= <type> + // ::= <integer-literal> + // ::= <member-data-pointer> + // ::= <member-function-pointer> + // ::= $E? <name> <type-encoding> + // ::= $1? <name> <type-encoding> + // ::= $0A@ + // ::= <template-args> + switch (TA.getKind()) { case TemplateArgument::Null: llvm_unreachable("Can't mangle null template arguments!"); @@ -951,25 +1131,54 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, } case TemplateArgument::Declaration: { const NamedDecl *ND = cast<NamedDecl>(TA.getAsDecl()); - mangle(ND, TA.isDeclForReferenceParam() ? "$E?" : "$1?"); + if (isa<FieldDecl>(ND) || isa<IndirectFieldDecl>(ND)) { + mangleMemberDataPointer( + cast<CXXRecordDecl>(ND->getDeclContext())->getMostRecentDecl(), + cast<ValueDecl>(ND)); + } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { + const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); + if (MD && MD->isInstance()) + mangleMemberFunctionPointer(MD->getParent()->getMostRecentDecl(), MD); + else + mangle(FD, "$1?"); + } else { + mangle(ND, TA.isDeclForReferenceParam() ? "$E?" : "$1?"); + } break; } case TemplateArgument::Integral: mangleIntegerLiteral(TA.getAsIntegral(), TA.getIntegralType()->isBooleanType()); break; - case TemplateArgument::NullPtr: + case TemplateArgument::NullPtr: { + QualType T = TA.getNullPtrType(); + if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) { + const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); + if (MPT->isMemberFunctionPointerType() && isa<ClassTemplateDecl>(TD)) { + mangleMemberFunctionPointer(RD, nullptr); + return; + } + if (MPT->isMemberDataPointer()) { + mangleMemberDataPointer(RD, nullptr); + return; + } + } Out << "$0A@"; break; + } case TemplateArgument::Expression: mangleExpression(TA.getAsExpr()); break; - case TemplateArgument::Pack: - // Unlike Itanium, there is no character code to indicate an argument pack. - for (TemplateArgument::pack_iterator I = TA.pack_begin(), E = TA.pack_end(); - I != E; ++I) - mangleTemplateArg(TD, *I); + case TemplateArgument::Pack: { + ArrayRef<TemplateArgument> TemplateArgs = TA.getPackAsArray(); + if (TemplateArgs.empty()) { + Out << "$S"; + } else { + for (const TemplateArgument &PA : TemplateArgs) + mangleTemplateArg(TD, PA); + } break; + } case TemplateArgument::Template: mangleType(cast<TagDecl>( TA.getAsTemplate().getAsTemplateDecl()->getTemplatedDecl())); @@ -1059,13 +1268,43 @@ void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals, // FIXME: For now, just drop all extension qualifiers on the floor. } -void MicrosoftCXXNameMangler::manglePointerQualifiers(Qualifiers Quals) { - // <pointer-cvr-qualifiers> ::= P # no qualifiers - // ::= Q # const - // ::= R # volatile - // ::= S # const volatile +void +MicrosoftCXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) { + // <ref-qualifier> ::= G # lvalue reference + // ::= H # rvalue-reference + switch (RefQualifier) { + case RQ_None: + break; + + case RQ_LValue: + Out << 'G'; + break; + + case RQ_RValue: + Out << 'H'; + break; + } +} + +void +MicrosoftCXXNameMangler::manglePointerExtQualifiers(Qualifiers Quals, + const Type *PointeeType) { + bool HasRestrict = Quals.hasRestrict(); + if (PointersAre64Bit && (!PointeeType || !PointeeType->isFunctionType())) + Out << 'E'; + + if (HasRestrict) + Out << 'I'; +} + +void MicrosoftCXXNameMangler::manglePointerCVQualifiers(Qualifiers Quals) { + // <pointer-cv-qualifiers> ::= P # no qualifiers + // ::= Q # const + // ::= R # volatile + // ::= S # const volatile bool HasConst = Quals.hasConst(), HasVolatile = Quals.hasVolatile(); + if (HasConst && HasVolatile) { Out << 'S'; } else if (HasVolatile) { @@ -1165,8 +1404,10 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range, } // We have to mangle these now, while we still have enough information. - if (IsPointer) - manglePointerQualifiers(Quals); + if (IsPointer) { + manglePointerCVQualifiers(Quals); + manglePointerExtQualifiers(Quals, T->getPointeeType().getTypePtr()); + } const Type *ty = T.getTypePtr(); switch (ty->getTypeClass()) { @@ -1254,7 +1495,7 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, case BuiltinType::OCLImage3d: Out << "PAUocl_image3d@@"; break; case BuiltinType::OCLSampler: Out << "PAUocl_sampler@@"; break; case BuiltinType::OCLEvent: Out << "PAUocl_event@@"; break; - + case BuiltinType::NullPtr: Out << "$$T"; break; case BuiltinType::Char16: @@ -1306,9 +1547,10 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, // If this is a C++ instance method, mangle the CVR qualifiers for the // this pointer. if (IsInstMethod) { - if (PointersAre64Bit) - Out << 'E'; - mangleQualifiers(Qualifiers::fromCVRMask(Proto->getTypeQuals()), false); + Qualifiers Quals = Qualifiers::fromCVRMask(Proto->getTypeQuals()); + manglePointerExtQualifiers(Quals, nullptr); + mangleRefQualifier(Proto->getRefQualifier()); + mangleQualifiers(Quals, false); } mangleCallingConvention(T); @@ -1327,23 +1569,30 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, } Out << '@'; } else { - QualType ResultType = Proto->getResultType(); - if (ResultType->isVoidType()) - ResultType = ResultType.getUnqualifiedType(); - mangleType(ResultType, Range, QMM_Result); + QualType ResultType = Proto->getReturnType(); + if (const auto *AT = + dyn_cast_or_null<AutoType>(ResultType->getContainedAutoType())) { + Out << '?'; + mangleQualifiers(ResultType.getLocalQualifiers(), /*IsMember=*/false); + Out << '?'; + mangleSourceName(AT->isDecltypeAuto() ? "<decltype-auto>" : "<auto>"); + Out << '@'; + } else { + if (ResultType->isVoidType()) + ResultType = ResultType.getUnqualifiedType(); + mangleType(ResultType, Range, QMM_Result); + } } // <argument-list> ::= X # void // ::= <type>+ @ // ::= <type>* Z # varargs - if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) { + if (Proto->getNumParams() == 0 && !Proto->isVariadic()) { Out << 'X'; } else { // Happens for function pointer type arguments for example. - for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(), - ArgEnd = Proto->arg_type_end(); - Arg != ArgEnd; ++Arg) - mangleArgumentType(*Arg, Range); + for (const QualType Arg : Proto->param_types()) + mangleArgumentType(Arg, Range); // <builtin-type> ::= Z # ellipsis if (Proto->isVariadic()) Out << 'Z'; @@ -1465,7 +1714,7 @@ void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T, // <union-type> ::= T <name> // <struct-type> ::= U <name> // <class-type> ::= V <name> -// <enum-type> ::= W <size> <name> +// <enum-type> ::= W4 <name> void MicrosoftCXXNameMangler::mangleType(const EnumType *T, SourceRange) { mangleType(cast<TagType>(T)->getDecl()); } @@ -1485,9 +1734,7 @@ void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) { Out << 'V'; break; case TTK_Enum: - Out << 'W'; - Out << getASTContext().getTypeSizeInChars( - cast<EnumDecl>(TD)->getIntegerType()).getQuantity(); + Out << "W4"; break; } mangleName(TD); @@ -1503,7 +1750,7 @@ void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) { void MicrosoftCXXNameMangler::mangleDecayedArrayType(const ArrayType *T) { // This isn't a recursive mangling, so now we have to do it all in this // one call. - manglePointerQualifiers(T->getElementType().getQualifiers()); + manglePointerCVQualifiers(T->getElementType().getQualifiers()); mangleType(T->getElementType(), SourceRange()); } void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T, @@ -1527,7 +1774,7 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) { SmallVector<llvm::APInt, 3> Dimensions; for (;;) { if (const ConstantArrayType *CAT = - getASTContext().getAsConstantArrayType(ElementTy)) { + getASTContext().getAsConstantArrayType(ElementTy)) { Dimensions.push_back(CAT->getSize()); ElementTy = CAT->getElementType(); } else if (ElementTy->isVariableArrayType()) { @@ -1550,7 +1797,7 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) { << DSAT->getBracketsRange(); return; } else if (const IncompleteArrayType *IAT = - getASTContext().getAsIncompleteArrayType(ElementTy)) { + getASTContext().getAsIncompleteArrayType(ElementTy)) { Dimensions.push_back(llvm::APInt(32, 0)); ElementTy = IAT->getElementType(); } @@ -1559,8 +1806,8 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) { Out << 'Y'; // <dimension-count> ::= <number> # number of extra dimensions mangleNumber(Dimensions.size()); - for (unsigned Dim = 0; Dim < Dimensions.size(); ++Dim) - mangleNumber(Dimensions[Dim].getLimitedValue()); + for (const llvm::APInt &Dimension : Dimensions) + mangleNumber(Dimension.getLimitedValue()); mangleType(ElementTy, SourceRange(), QMM_Escape); } @@ -1573,10 +1820,8 @@ void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T, if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) { Out << '8'; mangleName(T->getClass()->castAs<RecordType>()->getDecl()); - mangleFunctionType(FPT, 0, true); + mangleFunctionType(FPT, nullptr, true); } else { - if (PointersAre64Bit && !T->getPointeeType()->isFunctionType()) - Out << 'E'; mangleQualifiers(PointeeType.getQualifiers(), true); mangleName(T->getClass()->castAs<RecordType>()->getDecl()); mangleType(PointeeType, Range, QMM_Drop); @@ -1604,42 +1849,37 @@ void MicrosoftCXXNameMangler::mangleType( // <type> ::= <pointer-type> // <pointer-type> ::= E? <pointer-cvr-qualifiers> <cvr-qualifiers> <type> -// # the E is required for 64-bit non static pointers +// # the E is required for 64-bit non-static pointers void MicrosoftCXXNameMangler::mangleType(const PointerType *T, SourceRange Range) { QualType PointeeTy = T->getPointeeType(); - if (PointersAre64Bit && !T->getPointeeType()->isFunctionType()) - Out << 'E'; mangleType(PointeeTy, Range); } void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T, SourceRange Range) { // Object pointers never have qualifiers. Out << 'A'; - if (PointersAre64Bit && !T->getPointeeType()->isFunctionType()) - Out << 'E'; + manglePointerExtQualifiers(Qualifiers(), T->getPointeeType().getTypePtr()); mangleType(T->getPointeeType(), Range); } // <type> ::= <reference-type> // <reference-type> ::= A E? <cvr-qualifiers> <type> -// # the E is required for 64-bit non static lvalue references +// # the E is required for 64-bit non-static lvalue references void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T, SourceRange Range) { Out << 'A'; - if (PointersAre64Bit && !T->getPointeeType()->isFunctionType()) - Out << 'E'; + manglePointerExtQualifiers(Qualifiers(), T->getPointeeType().getTypePtr()); mangleType(T->getPointeeType(), Range); } // <type> ::= <r-value-reference-type> // <r-value-reference-type> ::= $$Q E? <cvr-qualifiers> <type> -// # the E is required for 64-bit non static rvalue references +// # the E is required for 64-bit non-static rvalue references void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T, SourceRange Range) { Out << "$$Q"; - if (PointersAre64Bit && !T->getPointeeType()->isFunctionType()) - Out << 'E'; + manglePointerExtQualifiers(Qualifiers(), T->getPointeeType().getTypePtr()); mangleType(T->getPointeeType(), Range); } @@ -1804,6 +2044,8 @@ void MicrosoftCXXNameMangler::mangleType(const UnaryTransformType *T, } void MicrosoftCXXNameMangler::mangleType(const AutoType *T, SourceRange Range) { + assert(T->getDeducedType().isNull() && "expecting a dependent type!"); + DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "cannot mangle this 'auto' type yet"); @@ -1923,17 +2165,17 @@ static void mangleThunkThisAdjustment(const CXXMethodDecl *MD, } } -void MicrosoftMangleContextImpl::mangleVirtualMemPtrThunk( - const CXXMethodDecl *MD, uint64_t OffsetInVFTable, raw_ostream &Out) { - bool Is64Bit = getASTContext().getTargetInfo().getPointerWidth(0) == 64; +void +MicrosoftMangleContextImpl::mangleVirtualMemPtrThunk(const CXXMethodDecl *MD, + raw_ostream &Out) { + MicrosoftVTableContext *VTContext = + cast<MicrosoftVTableContext>(getASTContext().getVTableContext()); + const MicrosoftVTableContext::MethodVFTableLocation &ML = + VTContext->getMethodVFTableLocation(GlobalDecl(MD)); MicrosoftCXXNameMangler Mangler(*this, Out); - Mangler.getStream() << "\01??_9"; - Mangler.mangleName(MD->getParent()); - Mangler.getStream() << "$B"; - Mangler.mangleNumber(OffsetInVFTable); - Mangler.getStream() << "A"; - Mangler.getStream() << (Is64Bit ? "A" : "E"); + Mangler.getStream() << "\01?"; + Mangler.mangleVirtualMemPtrThunk(MD, ML); } void MicrosoftMangleContextImpl::mangleThunk(const CXXMethodDecl *MD, @@ -1944,7 +2186,8 @@ void MicrosoftMangleContextImpl::mangleThunk(const CXXMethodDecl *MD, Mangler.mangleName(MD); mangleThunkThisAdjustment(MD, Thunk.This, Mangler, Out); if (!Thunk.Return.isEmpty()) - assert(Thunk.Method != 0 && "Thunk info should hold the overridee decl"); + assert(Thunk.Method != nullptr && + "Thunk info should hold the overridee decl"); const CXXMethodDecl *DeclForFPT = Thunk.Method ? Thunk.Method : MD; Mangler.mangleFunctionType( @@ -1976,11 +2219,8 @@ void MicrosoftMangleContextImpl::mangleCXXVFTable( Mangler.getStream() << "\01??_7"; Mangler.mangleName(Derived); Mangler.getStream() << "6B"; // '6' for vftable, 'B' for const. - for (ArrayRef<const CXXRecordDecl *>::iterator I = BasePath.begin(), - E = BasePath.end(); - I != E; ++I) { - Mangler.mangleName(*I); - } + for (const CXXRecordDecl *RD : BasePath) + Mangler.mangleName(RD); Mangler.getStream() << '@'; } @@ -1995,28 +2235,68 @@ void MicrosoftMangleContextImpl::mangleCXXVBTable( Mangler.getStream() << "\01??_8"; Mangler.mangleName(Derived); Mangler.getStream() << "7B"; // '7' for vbtable, 'B' for const. - for (ArrayRef<const CXXRecordDecl *>::iterator I = BasePath.begin(), - E = BasePath.end(); - I != E; ++I) { - Mangler.mangleName(*I); - } + for (const CXXRecordDecl *RD : BasePath) + Mangler.mangleName(RD); Mangler.getStream() << '@'; } -void MicrosoftMangleContextImpl::mangleCXXRTTI(QualType T, raw_ostream &) { - // FIXME: Give a location... - unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle RTTI descriptors for type %0 yet"); - getDiags().Report(DiagID) - << T.getBaseTypeIdentifier(); +void MicrosoftMangleContextImpl::mangleCXXRTTI(QualType T, raw_ostream &Out) { + MicrosoftCXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "\01??_R0"; + Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result); + Mangler.getStream() << "@8"; } -void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T, raw_ostream &) { - // FIXME: Give a location... - unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle the name of type %0 into RTTI descriptors yet"); - getDiags().Report(DiagID) - << T.getBaseTypeIdentifier(); +void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T, + raw_ostream &Out) { + MicrosoftCXXNameMangler Mangler(*this, Out); + Mangler.getStream() << '.'; + Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result); +} + +void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassDescriptor( + const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset, + uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) { + MicrosoftCXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "\01??_R1"; + Mangler.mangleNumber(NVOffset); + Mangler.mangleNumber(VBPtrOffset); + Mangler.mangleNumber(VBTableOffset); + Mangler.mangleNumber(Flags); + Mangler.mangleName(Derived); + Mangler.getStream() << "8"; +} + +void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassArray( + const CXXRecordDecl *Derived, raw_ostream &Out) { + MicrosoftCXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "\01??_R2"; + Mangler.mangleName(Derived); + Mangler.getStream() << "8"; +} + +void MicrosoftMangleContextImpl::mangleCXXRTTIClassHierarchyDescriptor( + const CXXRecordDecl *Derived, raw_ostream &Out) { + MicrosoftCXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "\01??_R3"; + Mangler.mangleName(Derived); + Mangler.getStream() << "8"; +} + +void MicrosoftMangleContextImpl::mangleCXXRTTICompleteObjectLocator( + const CXXRecordDecl *Derived, ArrayRef<const CXXRecordDecl *> BasePath, + raw_ostream &Out) { + // <mangled-name> ::= ?_R4 <class-name> <storage-class> + // <cvr-qualifiers> [<name>] @ + // NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class> + // is always '6' for vftables. + MicrosoftCXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "\01??_R4"; + Mangler.mangleName(Derived); + Mangler.getStream() << "6B"; // '6' for vftable, 'B' for const. + for (const CXXRecordDecl *RD : BasePath) + Mangler.mangleName(RD); + Mangler.getStream() << '@'; } void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) { @@ -2042,6 +2322,7 @@ void MicrosoftMangleContextImpl::mangleCXXDtor(const CXXDestructorDecl *D, } void MicrosoftMangleContextImpl::mangleReferenceTemporary(const VarDecl *VD, + unsigned, raw_ostream &) { unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, "cannot mangle this reference temporary yet"); @@ -2050,7 +2331,16 @@ void MicrosoftMangleContextImpl::mangleReferenceTemporary(const VarDecl *VD, void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD, raw_ostream &Out) { - // <guard-name> ::= ?_B <postfix> @51 + // TODO: This is not correct, especially with respect to MSVC2013. MSVC2013 + // utilizes thread local variables to implement thread safe, re-entrant + // initialization for statics. They no longer differentiate between an + // externally visible and non-externally visible static with respect to + // mangling, they all get $TSS <number>. + // + // N.B. This means that they can get more than 32 static variable guards in a + // scope. It also means that they broke compatibility with their own ABI. + + // <guard-name> ::= ?_B <postfix> @5 <scope-depth> // ::= ?$S <guard-num> @ <postfix> @4IA // The first mangling is what MSVC uses to guard static locals in inline @@ -2064,8 +2354,17 @@ void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD, bool Visible = VD->isExternallyVisible(); // <operator-name> ::= ?_B # local static guard Mangler.getStream() << (Visible ? "\01??_B" : "\01?$S1@"); - Mangler.manglePostfix(VD->getDeclContext()); - Mangler.getStream() << (Visible ? "@51" : "@4IA"); + unsigned ScopeDepth = 0; + if (Visible && !getNextDiscriminator(VD, ScopeDepth)) + // If we do not have a discriminator and are emitting a guard variable for + // use at global scope, then mangling the nested name will not be enough to + // remove ambiguities. + Mangler.mangle(VD, ""); + else + Mangler.mangleNestedName(VD); + Mangler.getStream() << (Visible ? "@5" : "@4IA"); + if (ScopeDepth) + Mangler.mangleNumber(ScopeDepth); } void MicrosoftMangleContextImpl::mangleInitFiniStub(const VarDecl *D, @@ -2074,6 +2373,10 @@ void MicrosoftMangleContextImpl::mangleInitFiniStub(const VarDecl *D, MicrosoftCXXNameMangler Mangler(*this, Out); Mangler.getStream() << "\01??__" << CharCode; Mangler.mangleName(D); + if (D->isStaticDataMember()) { + Mangler.mangleVariableEncoding(D); + Mangler.getStream() << '@'; + } // This is the function class mangling. These stubs are global, non-variadic, // cdecl functions that return void and take no args. Mangler.getStream() << "YAXXZ"; @@ -2092,6 +2395,172 @@ MicrosoftMangleContextImpl::mangleDynamicAtExitDestructor(const VarDecl *D, mangleInitFiniStub(D, Out, 'F'); } +void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, + raw_ostream &Out) { + // <char-type> ::= 0 # char + // ::= 1 # wchar_t + // ::= ??? # char16_t/char32_t will need a mangling too... + // + // <literal-length> ::= <non-negative integer> # the length of the literal + // + // <encoded-crc> ::= <hex digit>+ @ # crc of the literal including + // # null-terminator + // + // <encoded-string> ::= <simple character> # uninteresting character + // ::= '?$' <hex digit> <hex digit> # these two nibbles + // # encode the byte for the + // # character + // ::= '?' [a-z] # \xe1 - \xfa + // ::= '?' [A-Z] # \xc1 - \xda + // ::= '?' [0-9] # [,/\:. \n\t'-] + // + // <literal> ::= '??_C@_' <char-type> <literal-length> <encoded-crc> + // <encoded-string> '@' + MicrosoftCXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "\01??_C@_"; + + // <char-type>: The "kind" of string literal is encoded into the mangled name. + // TODO: This needs to be updated when MSVC gains support for unicode + // literals. + if (SL->isAscii()) + Mangler.getStream() << '0'; + else if (SL->isWide()) + Mangler.getStream() << '1'; + else + llvm_unreachable("unexpected string literal kind!"); + + // <literal-length>: The next part of the mangled name consists of the length + // of the string. + // The StringLiteral does not consider the NUL terminator byte(s) but the + // mangling does. + // N.B. The length is in terms of bytes, not characters. + Mangler.mangleNumber(SL->getByteLength() + SL->getCharByteWidth()); + + // We will use the "Rocksoft^tm Model CRC Algorithm" to describe the + // properties of our CRC: + // Width : 32 + // Poly : 04C11DB7 + // Init : FFFFFFFF + // RefIn : True + // RefOut : True + // XorOut : 00000000 + // Check : 340BC6D9 + uint32_t CRC = 0xFFFFFFFFU; + + auto UpdateCRC = [&CRC](char Byte) { + for (unsigned i = 0; i < 8; ++i) { + bool Bit = CRC & 0x80000000U; + if (Byte & (1U << i)) + Bit = !Bit; + CRC <<= 1; + if (Bit) + CRC ^= 0x04C11DB7U; + } + }; + + auto GetLittleEndianByte = [&Mangler, &SL](unsigned Index) { + unsigned CharByteWidth = SL->getCharByteWidth(); + uint32_t CodeUnit = SL->getCodeUnit(Index / CharByteWidth); + unsigned OffsetInCodeUnit = Index % CharByteWidth; + return static_cast<char>((CodeUnit >> (8 * OffsetInCodeUnit)) & 0xff); + }; + + auto GetBigEndianByte = [&Mangler, &SL](unsigned Index) { + unsigned CharByteWidth = SL->getCharByteWidth(); + uint32_t CodeUnit = SL->getCodeUnit(Index / CharByteWidth); + unsigned OffsetInCodeUnit = (CharByteWidth - 1) - (Index % CharByteWidth); + return static_cast<char>((CodeUnit >> (8 * OffsetInCodeUnit)) & 0xff); + }; + + // CRC all the bytes of the StringLiteral. + for (unsigned I = 0, E = SL->getByteLength(); I != E; ++I) + UpdateCRC(GetLittleEndianByte(I)); + + // The NUL terminator byte(s) were not present earlier, + // we need to manually process those bytes into the CRC. + for (unsigned NullTerminator = 0; NullTerminator < SL->getCharByteWidth(); + ++NullTerminator) + UpdateCRC('\x00'); + + // The literature refers to the process of reversing the bits in the final CRC + // output as "reflection". + CRC = llvm::reverseBits(CRC); + + // <encoded-crc>: The CRC is encoded utilizing the standard number mangling + // scheme. + Mangler.mangleNumber(CRC); + + // <encoded-string>: The mangled name also contains the first 32 _characters_ + // (including null-terminator bytes) of the StringLiteral. + // Each character is encoded by splitting them into bytes and then encoding + // the constituent bytes. + auto MangleByte = [&Mangler](char Byte) { + // There are five different manglings for characters: + // - [a-zA-Z0-9_$]: A one-to-one mapping. + // - ?[a-z]: The range from \xe1 to \xfa. + // - ?[A-Z]: The range from \xc1 to \xda. + // - ?[0-9]: The set of [,/\:. \n\t'-]. + // - ?$XX: A fallback which maps nibbles. + if (isIdentifierBody(Byte, /*AllowDollar=*/true)) { + Mangler.getStream() << Byte; + } else if (isLetter(Byte & 0x7f)) { + Mangler.getStream() << '?' << static_cast<char>(Byte & 0x7f); + } else { + switch (Byte) { + case ',': + Mangler.getStream() << "?0"; + break; + case '/': + Mangler.getStream() << "?1"; + break; + case '\\': + Mangler.getStream() << "?2"; + break; + case ':': + Mangler.getStream() << "?3"; + break; + case '.': + Mangler.getStream() << "?4"; + break; + case ' ': + Mangler.getStream() << "?5"; + break; + case '\n': + Mangler.getStream() << "?6"; + break; + case '\t': + Mangler.getStream() << "?7"; + break; + case '\'': + Mangler.getStream() << "?8"; + break; + case '-': + Mangler.getStream() << "?9"; + break; + default: + Mangler.getStream() << "?$"; + Mangler.getStream() << static_cast<char>('A' + ((Byte >> 4) & 0xf)); + Mangler.getStream() << static_cast<char>('A' + (Byte & 0xf)); + break; + } + } + }; + + // Enforce our 32 character max. + unsigned NumCharsToMangle = std::min(32U, SL->getLength()); + for (unsigned I = 0, E = NumCharsToMangle * SL->getCharByteWidth(); I != E; + ++I) + MangleByte(GetBigEndianByte(I)); + + // Encode the NUL terminator if there is room. + if (NumCharsToMangle < 32) + for (unsigned NullTerminator = 0; NullTerminator < SL->getCharByteWidth(); + ++NullTerminator) + MangleByte(0); + + Mangler.getStream() << '@'; +} + MicrosoftMangleContext * MicrosoftMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) { return new MicrosoftMangleContextImpl(Context, Diags); |