diff options
Diffstat (limited to 'clang/lib/AST/MicrosoftMangle.cpp')
-rw-r--r-- | clang/lib/AST/MicrosoftMangle.cpp | 3443 |
1 files changed, 1718 insertions, 1725 deletions
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index a8737e73e9d..0da7f516db9 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -1,1725 +1,1718 @@ -//===--- MicrosoftMangle.cpp - Microsoft Visual C++ Name Mangling ---------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This provides C++ name mangling targeting the Microsoft Visual C++ ABI.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/AST/Mangle.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Attr.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/ExprCXX.h"
-#include "clang/Basic/ABI.h"
-#include "clang/Basic/DiagnosticOptions.h"
-#include <map>
-
-using namespace clang;
-
-namespace {
-
-/// MicrosoftCXXNameMangler - Manage the mangling of a single name for the
-/// Microsoft Visual C++ ABI.
-class MicrosoftCXXNameMangler {
- MangleContext &Context;
- raw_ostream &Out;
-
- // FIXME: audit the performance of BackRefMap as it might do way too many
- // copying of strings.
- typedef std::map<std::string, unsigned> BackRefMap;
- BackRefMap NameBackReferences;
- bool UseNameBackReferences;
-
- typedef llvm::DenseMap<void*, unsigned> ArgBackRefMap;
- ArgBackRefMap TypeBackReferences;
-
- ASTContext &getASTContext() const { return Context.getASTContext(); }
-
-public:
- MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_)
- : Context(C), Out(Out_), UseNameBackReferences(true) { }
-
- raw_ostream &getStream() const { return Out; }
-
- void mangle(const NamedDecl *D, StringRef Prefix = "\01?");
- void mangleName(const NamedDecl *ND);
- void mangleFunctionEncoding(const FunctionDecl *FD);
- void mangleVariableEncoding(const VarDecl *VD);
- void mangleNumber(int64_t Number);
- void mangleNumber(const llvm::APSInt &Value);
- void mangleType(QualType T, SourceRange Range, bool MangleQualifiers = true);
-
-private:
- void disableBackReferences() { UseNameBackReferences = false; }
- void mangleUnqualifiedName(const NamedDecl *ND) {
- mangleUnqualifiedName(ND, ND->getDeclName());
- }
- void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name);
- void mangleSourceName(const IdentifierInfo *II);
- void manglePostfix(const DeclContext *DC, bool NoFunction=false);
- void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc);
- void mangleQualifiers(Qualifiers Quals, bool IsMember);
- void manglePointerQualifiers(Qualifiers Quals);
-
- void mangleUnscopedTemplateName(const TemplateDecl *ND);
- void mangleTemplateInstantiationName(const TemplateDecl *TD,
- const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs);
- void mangleObjCMethodName(const ObjCMethodDecl *MD);
- void mangleLocalName(const FunctionDecl *FD);
-
- void mangleArgumentType(QualType T, SourceRange Range);
-
- // Declare manglers for every type class.
-#define ABSTRACT_TYPE(CLASS, PARENT)
-#define NON_CANONICAL_TYPE(CLASS, PARENT)
-#define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T, \
- SourceRange Range);
-#include "clang/AST/TypeNodes.def"
-#undef ABSTRACT_TYPE
-#undef NON_CANONICAL_TYPE
-#undef TYPE
-
- void mangleType(const TagType*);
- void mangleType(const FunctionType *T, const FunctionDecl *D,
- bool IsStructor, bool IsInstMethod);
- void mangleType(const ArrayType *T, bool IsGlobal);
- void mangleExtraDimensions(QualType T);
- void mangleFunctionClass(const FunctionDecl *FD);
- void mangleCallingConvention(const FunctionType *T, bool IsInstMethod = false);
- void mangleIntegerLiteral(const llvm::APSInt &Number, bool IsBoolean);
- void mangleExpression(const Expr *E);
- void mangleThrowSpecification(const FunctionProtoType *T);
-
- void mangleTemplateArgs(
- const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs);
-
-};
-
-/// MicrosoftMangleContext - Overrides the default MangleContext for the
-/// Microsoft Visual C++ ABI.
-class MicrosoftMangleContext : public MangleContext {
-public:
- MicrosoftMangleContext(ASTContext &Context,
- DiagnosticsEngine &Diags) : MangleContext(Context, Diags) { }
- virtual bool shouldMangleDeclName(const NamedDecl *D);
- virtual void mangleName(const NamedDecl *D, raw_ostream &Out);
- 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 mangleCXXVTable(const CXXRecordDecl *RD,
- raw_ostream &);
- virtual void mangleCXXVTT(const CXXRecordDecl *RD,
- raw_ostream &);
- virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
- const CXXRecordDecl *Type,
- raw_ostream &);
- virtual void mangleCXXRTTI(QualType T, raw_ostream &);
- virtual void mangleCXXRTTIName(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 clang::VarDecl *,
- raw_ostream &);
-};
-
-}
-
-static bool isInCLinkageSpecification(const Decl *D) {
- D = D->getCanonicalDecl();
- for (const DeclContext *DC = D->getDeclContext();
- !DC->isTranslationUnit(); DC = DC->getParent()) {
- if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))
- return Linkage->getLanguage() == LinkageSpecDecl::lang_c;
- }
-
- return false;
-}
-
-bool MicrosoftMangleContext::shouldMangleDeclName(const NamedDecl *D) {
- // In C, functions with no attributes never need to be mangled. Fastpath them.
- if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs())
- return false;
-
- // Any decl can be declared with __asm("foo") on it, and this takes precedence
- // over all other naming in the .o file.
- if (D->hasAttr<AsmLabelAttr>())
- return true;
-
- // Clang's "overloadable" attribute extension to C/C++ implies name mangling
- // (always) as does passing a C++ member function and a function
- // whose name is not a simple identifier.
- const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (FD && (FD->hasAttr<OverloadableAttr>() || isa<CXXMethodDecl>(FD) ||
- !FD->getDeclName().isIdentifier()))
- return true;
-
- // Otherwise, no mangling is done outside C++ mode.
- if (!getASTContext().getLangOpts().CPlusPlus)
- return false;
-
- // Variables at global scope with internal linkage are not mangled.
- if (!FD) {
- const DeclContext *DC = D->getDeclContext();
- if (DC->isTranslationUnit() && D->getLinkage() == InternalLinkage)
- return false;
- }
-
- // C functions and "main" are not mangled.
- if ((FD && FD->isMain()) || isInCLinkageSpecification(D))
- return false;
-
- return true;
-}
-
-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
- // default, we emit an asm marker at the start so we get the name right.
- // Callers can override this with a custom prefix.
-
- // Any decl can be declared with __asm("foo") on it, and this takes precedence
- // over all other naming in the .o file.
- if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
- // If we have an asm name, then we use it as the mangling.
- Out << '\01' << ALA->getLabel();
- return;
- }
-
- // <mangled-name> ::= ? <name> <type-encoding>
- Out << Prefix;
- mangleName(D);
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- mangleFunctionEncoding(FD);
- else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
- mangleVariableEncoding(VD);
- else {
- // 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();
- }
-}
-
-void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
- // <type-encoding> ::= <function-class> <function-type>
-
- // Don't mangle in the type if this isn't a decl we should typically mangle.
- if (!Context.shouldMangleDeclName(FD))
- return;
-
- // We should never ever see a FunctionNoProtoType at this point.
- // We don't even know how to mangle their types anyway :).
- const FunctionProtoType *FT = FD->getType()->castAs<FunctionProtoType>();
-
- bool InStructor = false, InInstMethod = false;
- const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
- if (MD) {
- if (MD->isInstance())
- InInstMethod = true;
- if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))
- InStructor = true;
- }
-
- // First, the function class.
- mangleFunctionClass(FD);
-
- mangleType(FT, FD, InStructor, InInstMethod);
-}
-
-void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
- // <type-encoding> ::= <storage-class> <variable-type>
- // <storage-class> ::= 0 # private static member
- // ::= 1 # protected static member
- // ::= 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.
- switch (VD->getAccess()) {
- default:
- case AS_private: Out << '0'; break;
- case AS_protected: Out << '1'; break;
- case AS_public: Out << '2'; break;
- }
- }
- else if (!VD->isStaticLocal())
- Out << '3';
- else
- Out << '4';
- // Now mangle the type.
- // <variable-type> ::= <type> <cvr-qualifiers>
- // ::= <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();
- if (Ty->isPointerType() || Ty->isReferenceType()) {
- mangleType(Ty, TL.getSourceRange());
- mangleQualifiers(Ty->getPointeeType().getQualifiers(), false);
- } else if (const ArrayType *AT = getASTContext().getAsArrayType(Ty)) {
- // Global arrays are funny, too.
- mangleType(AT, true);
- mangleQualifiers(Ty.getQualifiers(), false);
- } else {
- mangleType(Ty.getLocalUnqualifiedType(), TL.getSourceRange());
- mangleQualifiers(Ty.getLocalQualifiers(), false);
- }
-}
-
-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();
-
- manglePostfix(DC);
-
- // Terminate the whole name with an '@'.
- Out << '@';
-}
-
-void MicrosoftCXXNameMangler::mangleNumber(int64_t Number) {
- llvm::APSInt APSNumber(/*BitWidth=*/64, /*isUnsigned=*/false);
- APSNumber = Number;
- mangleNumber(APSNumber);
-}
-
-void MicrosoftCXXNameMangler::mangleNumber(const llvm::APSInt &Value) {
- // <number> ::= [?] <decimal digit> # 1 <= Number <= 10
- // ::= [?] <hex digit>+ @ # 0 or > 9; A = 0, B = 1, etc...
- // ::= [?] @ # 0 (alternate mangling, not emitted by VC)
- if (Value.isSigned() && Value.isNegative()) {
- Out << '?';
- mangleNumber(llvm::APSInt(Value.abs()));
- return;
- }
- llvm::APSInt Temp(Value);
- // There's a special shorter mangling for 0, but Microsoft
- // chose not to use it. Instead, 0 gets mangled as "A@". Oh well...
- if (Value.uge(1) && Value.ule(10)) {
- --Temp;
- Temp.print(Out, false);
- } else {
- // We have to build up the encoding in reverse order, so it will come
- // out right when we write it out.
- char Encoding[64];
- char *EndPtr = Encoding+sizeof(Encoding);
- char *CurPtr = EndPtr;
- llvm::APSInt NibbleMask(Value.getBitWidth(), Value.isUnsigned());
- NibbleMask = 0xf;
- do {
- *--CurPtr = 'A' + Temp.And(NibbleMask).getLimitedValue(0xf);
- Temp = Temp.lshr(4);
- } while (Temp != 0);
- Out.write(CurPtr, EndPtr-CurPtr);
- Out << '@';
- }
-}
-
-static const TemplateDecl *
-isTemplate(const NamedDecl *ND,
- SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) {
- // Check if we have a function template.
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){
- if (const TemplateDecl *TD = FD->getPrimaryTemplate()) {
- if (FD->getTemplateSpecializationArgsAsWritten()) {
- const ASTTemplateArgumentListInfo *ArgList =
- FD->getTemplateSpecializationArgsAsWritten();
- TemplateArgs.append(ArgList->getTemplateArgs(),
- ArgList->getTemplateArgs() +
- ArgList->NumTemplateArgs);
- } else {
- const TemplateArgumentList *ArgList =
- FD->getTemplateSpecializationArgs();
- TemplateArgumentListInfo LI;
- for (unsigned i = 0, e = ArgList->size(); i != e; ++i)
- TemplateArgs.push_back(TemplateArgumentLoc(ArgList->get(i),
- FD->getTypeSourceInfo()));
- }
- return TD;
- }
- }
-
- // Check if we have a class template.
- if (const ClassTemplateSpecializationDecl *Spec =
- dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
- TypeSourceInfo *TSI = Spec->getTypeAsWritten();
- if (TSI) {
- TemplateSpecializationTypeLoc TSTL =
- cast<TemplateSpecializationTypeLoc>(TSI->getTypeLoc());
- TemplateArgumentListInfo LI(TSTL.getLAngleLoc(), TSTL.getRAngleLoc());
- for (unsigned i = 0, e = TSTL.getNumArgs(); i != e; ++i)
- TemplateArgs.push_back(TSTL.getArgLoc(i));
- } else {
- TemplateArgumentListInfo LI;
- const TemplateArgumentList &ArgList =
- Spec->getTemplateArgs();
- for (unsigned i = 0, e = ArgList.size(); i != e; ++i)
- TemplateArgs.push_back(TemplateArgumentLoc(ArgList[i],
- TemplateArgumentLocInfo()));
- }
- return Spec->getSpecializedTemplate();
- }
-
- return 0;
-}
-
-void
-MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
- DeclarationName Name) {
- // <unqualified-name> ::= <operator-name>
- // ::= <ctor-dtor-name>
- // ::= <source-name>
- // ::= <template-name>
- SmallVector<TemplateArgumentLoc, 2> TemplateArgs;
- // Check if we have a template.
- if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
- // We have a 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
- // void foo(A::X<A::Y>, A::X<B::Y>),
- // the A::X<> part is not aliased.
- // That said, from the mangler's perspective we have a structure like this:
- // namespace[s] -> type[ -> template-parameters]
- // but from the Clang perspective we have
- // 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;
- }
- return;
- }
-
- switch (Name.getNameKind()) {
- case DeclarationName::Identifier: {
- if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
- mangleSourceName(II);
- 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;
- }
- }
-
- // We must have an anonymous struct.
- const TagDecl *TD = cast<TagDecl>(ND);
- if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) {
- assert(TD->getDeclContext() == D->getDeclContext() &&
- "Typedef should not be in another decl context!");
- assert(D->getDeclName().getAsIdentifierInfo() &&
- "Typedef was not named!");
- mangleSourceName(D->getDeclName().getAsIdentifierInfo());
- break;
- }
-
- // When VC encounters an anonymous type with no tag and no typedef,
- // it literally emits '<unnamed-tag>'.
- Out << "<unnamed-tag>";
- break;
- }
-
- case DeclarationName::ObjCZeroArgSelector:
- case DeclarationName::ObjCOneArgSelector:
- case DeclarationName::ObjCMultiArgSelector:
- llvm_unreachable("Can't mangle Objective-C selector names here!");
-
- case DeclarationName::CXXConstructorName:
- Out << "?0";
- break;
-
- case DeclarationName::CXXDestructorName:
- Out << "?1";
- 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);
- break;
- }
-
- case DeclarationName::CXXUsingDirective:
- llvm_unreachable("Can't mangle a using directive name!");
- }
-}
-
-void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC,
- bool NoFunction) {
- // <postfix> ::= <unqualified-name> [<postfix>]
- // ::= <substitution> [<postfix>]
-
- if (!DC) return;
-
- while (isa<LinkageSpecDecl>(DC))
- DC = DC->getParent();
-
- if (DC->isTranslationUnit())
- return;
-
- if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) {
- Context.mangleBlock(BD, Out);
- Out << '@';
- return manglePostfix(DC->getParent(), NoFunction);
- }
-
- 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);
- }
-}
-
-void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO,
- SourceLocation Loc) {
- switch (OO) {
- // ?0 # constructor
- // ?1 # destructor
- // <operator-name> ::= ?2 # new
- case OO_New: Out << "?2"; break;
- // <operator-name> ::= ?3 # delete
- case OO_Delete: Out << "?3"; break;
- // <operator-name> ::= ?4 # =
- case OO_Equal: Out << "?4"; break;
- // <operator-name> ::= ?5 # >>
- case OO_GreaterGreater: Out << "?5"; break;
- // <operator-name> ::= ?6 # <<
- case OO_LessLess: Out << "?6"; break;
- // <operator-name> ::= ?7 # !
- case OO_Exclaim: Out << "?7"; break;
- // <operator-name> ::= ?8 # ==
- case OO_EqualEqual: Out << "?8"; break;
- // <operator-name> ::= ?9 # !=
- case OO_ExclaimEqual: Out << "?9"; break;
- // <operator-name> ::= ?A # []
- case OO_Subscript: Out << "?A"; break;
- // ?B # conversion
- // <operator-name> ::= ?C # ->
- case OO_Arrow: Out << "?C"; break;
- // <operator-name> ::= ?D # *
- case OO_Star: Out << "?D"; break;
- // <operator-name> ::= ?E # ++
- case OO_PlusPlus: Out << "?E"; break;
- // <operator-name> ::= ?F # --
- case OO_MinusMinus: Out << "?F"; break;
- // <operator-name> ::= ?G # -
- case OO_Minus: Out << "?G"; break;
- // <operator-name> ::= ?H # +
- case OO_Plus: Out << "?H"; break;
- // <operator-name> ::= ?I # &
- case OO_Amp: Out << "?I"; break;
- // <operator-name> ::= ?J # ->*
- case OO_ArrowStar: Out << "?J"; break;
- // <operator-name> ::= ?K # /
- case OO_Slash: Out << "?K"; break;
- // <operator-name> ::= ?L # %
- case OO_Percent: Out << "?L"; break;
- // <operator-name> ::= ?M # <
- case OO_Less: Out << "?M"; break;
- // <operator-name> ::= ?N # <=
- case OO_LessEqual: Out << "?N"; break;
- // <operator-name> ::= ?O # >
- case OO_Greater: Out << "?O"; break;
- // <operator-name> ::= ?P # >=
- case OO_GreaterEqual: Out << "?P"; break;
- // <operator-name> ::= ?Q # ,
- case OO_Comma: Out << "?Q"; break;
- // <operator-name> ::= ?R # ()
- case OO_Call: Out << "?R"; break;
- // <operator-name> ::= ?S # ~
- case OO_Tilde: Out << "?S"; break;
- // <operator-name> ::= ?T # ^
- case OO_Caret: Out << "?T"; break;
- // <operator-name> ::= ?U # |
- case OO_Pipe: Out << "?U"; break;
- // <operator-name> ::= ?V # &&
- case OO_AmpAmp: Out << "?V"; break;
- // <operator-name> ::= ?W # ||
- case OO_PipePipe: Out << "?W"; break;
- // <operator-name> ::= ?X # *=
- case OO_StarEqual: Out << "?X"; break;
- // <operator-name> ::= ?Y # +=
- case OO_PlusEqual: Out << "?Y"; break;
- // <operator-name> ::= ?Z # -=
- case OO_MinusEqual: Out << "?Z"; break;
- // <operator-name> ::= ?_0 # /=
- case OO_SlashEqual: Out << "?_0"; break;
- // <operator-name> ::= ?_1 # %=
- case OO_PercentEqual: Out << "?_1"; break;
- // <operator-name> ::= ?_2 # >>=
- case OO_GreaterGreaterEqual: Out << "?_2"; break;
- // <operator-name> ::= ?_3 # <<=
- case OO_LessLessEqual: Out << "?_3"; break;
- // <operator-name> ::= ?_4 # &=
- case OO_AmpEqual: Out << "?_4"; break;
- // <operator-name> ::= ?_5 # |=
- case OO_PipeEqual: Out << "?_5"; break;
- // <operator-name> ::= ?_6 # ^=
- case OO_CaretEqual: Out << "?_6"; break;
- // ?_7 # vftable
- // ?_8 # vbtable
- // ?_9 # vcall
- // ?_A # typeof
- // ?_B # local static guard
- // ?_C # string
- // ?_D # vbase destructor
- // ?_E # vector deleting destructor
- // ?_F # default constructor closure
- // ?_G # scalar deleting destructor
- // ?_H # vector constructor iterator
- // ?_I # vector destructor iterator
- // ?_J # vector vbase constructor iterator
- // ?_K # virtual displacement map
- // ?_L # eh vector constructor iterator
- // ?_M # eh vector destructor iterator
- // ?_N # eh vector vbase constructor iterator
- // ?_O # copy constructor closure
- // ?_P<name> # udt returning <name>
- // ?_Q # <unknown>
- // ?_R0 # RTTI Type Descriptor
- // ?_R1 # RTTI Base Class Descriptor at (a,b,c,d)
- // ?_R2 # RTTI Base Class Array
- // ?_R3 # RTTI Class Hierarchy Descriptor
- // ?_R4 # RTTI Complete Object Locator
- // ?_S # local vftable
- // ?_T # local vftable constructor closure
- // <operator-name> ::= ?_U # new[]
- 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,
- "cannot mangle this conditional operator yet");
- Diags.Report(Loc, DiagID);
- break;
- }
-
- case OO_None:
- case NUM_OVERLOADED_OPERATORS:
- llvm_unreachable("Not an overloaded operator");
- }
-}
-
-void MicrosoftCXXNameMangler::mangleSourceName(const IdentifierInfo *II) {
- // <source name> ::= <identifier> @
- std::string key = II->getNameStart();
- BackRefMap::iterator Found;
- if (UseNameBackReferences)
- Found = NameBackReferences.find(key);
- if (!UseNameBackReferences || Found == NameBackReferences.end()) {
- Out << II->getName() << '@';
- if (UseNameBackReferences && NameBackReferences.size() < 10) {
- size_t Size = NameBackReferences.size();
- NameBackReferences[key] = Size;
- }
- } else {
- Out << Found->second;
- }
-}
-
-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
- int NestLevel = getLocalNestingLevel(FD);
- Out << '?';
- mangleNumber(NestLevel);
- Out << '?';
- mangle(FD, "?");
-}
-
-void MicrosoftCXXNameMangler::mangleTemplateInstantiationName(
- const TemplateDecl *TD,
- const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) {
- // <template-name> ::= <unscoped-template-name> <template-args>
- // ::= <substitution>
- // Always start with the unqualified name.
-
- // Templates have their own context for back references.
- ArgBackRefMap OuterArgsContext;
- BackRefMap OuterTemplateContext;
- NameBackReferences.swap(OuterTemplateContext);
- TypeBackReferences.swap(OuterArgsContext);
-
- mangleUnscopedTemplateName(TD);
- mangleTemplateArgs(TemplateArgs);
-
- // Restore the previous back reference contexts.
- NameBackReferences.swap(OuterTemplateContext);
- TypeBackReferences.swap(OuterArgsContext);
-}
-
-void
-MicrosoftCXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *TD) {
- // <unscoped-template-name> ::= ?$ <unqualified-name>
- Out << "?$";
- mangleUnqualifiedName(TD);
-}
-
-void
-MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value,
- bool IsBoolean) {
- // <integer-literal> ::= $0 <number>
- Out << "$0";
- // Make sure booleans are encoded as 0/1.
- if (IsBoolean && Value.getBoolValue())
- mangleNumber(1);
- else
- mangleNumber(Value);
-}
-
-void
-MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
- // See if this is a constant expression.
- llvm::APSInt Value;
- if (E->isIntegerConstantExpr(Value, Context.getASTContext())) {
- mangleIntegerLiteral(Value, E->getType()->isBooleanType());
- return;
- }
-
- // 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();
-}
-
-void
-MicrosoftCXXNameMangler::mangleTemplateArgs(
- const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) {
- // <template-args> ::= {<type> | <integer-literal>}+ @
- unsigned NumTemplateArgs = TemplateArgs.size();
- for (unsigned i = 0; i < NumTemplateArgs; ++i) {
- const TemplateArgumentLoc &TAL = TemplateArgs[i];
- const TemplateArgument &TA = TAL.getArgument();
- switch (TA.getKind()) {
- case TemplateArgument::Null:
- llvm_unreachable("Can't mangle null template arguments!");
- case TemplateArgument::Type:
- mangleType(TA.getAsType(), TAL.getSourceRange());
- break;
- case TemplateArgument::Integral:
- mangleIntegerLiteral(TA.getAsIntegral(),
- TA.getIntegralType()->isBooleanType());
- break;
- case TemplateArgument::Expression:
- mangleExpression(TA.getAsExpr());
- break;
- case TemplateArgument::Template:
- case TemplateArgument::TemplateExpansion:
- case TemplateArgument::Declaration:
- case TemplateArgument::NullPtr:
- case TemplateArgument::Pack: {
- // Issue a diagnostic.
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this %select{ERROR|ERROR|pointer/reference|nullptr|"
- "integral|template|template pack expansion|ERROR|parameter pack}0 "
- "template argument yet");
- Diags.Report(TAL.getLocation(), DiagID)
- << TA.getKind()
- << TAL.getSourceRange();
- }
- }
- }
- Out << '@';
-}
-
-void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals,
- bool IsMember) {
- // <cvr-qualifiers> ::= [E] [F] [I] <base-cvr-qualifiers>
- // 'E' means __ptr64 (32-bit only); 'F' means __unaligned (32/64-bit only);
- // 'I' means __restrict (32/64-bit).
- // Note that the MSVC __restrict keyword isn't the same as the C99 restrict
- // keyword!
- // <base-cvr-qualifiers> ::= A # near
- // ::= B # near const
- // ::= C # near volatile
- // ::= D # near const volatile
- // ::= E # far (16-bit)
- // ::= F # far const (16-bit)
- // ::= G # far volatile (16-bit)
- // ::= H # far const volatile (16-bit)
- // ::= I # huge (16-bit)
- // ::= J # huge const (16-bit)
- // ::= K # huge volatile (16-bit)
- // ::= L # huge const volatile (16-bit)
- // ::= M <basis> # based
- // ::= N <basis> # based const
- // ::= O <basis> # based volatile
- // ::= P <basis> # based const volatile
- // ::= Q # near member
- // ::= R # near const member
- // ::= S # near volatile member
- // ::= T # near const volatile member
- // ::= U # far member (16-bit)
- // ::= V # far const member (16-bit)
- // ::= W # far volatile member (16-bit)
- // ::= X # far const volatile member (16-bit)
- // ::= Y # huge member (16-bit)
- // ::= Z # huge const member (16-bit)
- // ::= 0 # huge volatile member (16-bit)
- // ::= 1 # huge const volatile member (16-bit)
- // ::= 2 <basis> # based member
- // ::= 3 <basis> # based const member
- // ::= 4 <basis> # based volatile member
- // ::= 5 <basis> # based const volatile member
- // ::= 6 # near function (pointers only)
- // ::= 7 # far function (pointers only)
- // ::= 8 # near method (pointers only)
- // ::= 9 # far method (pointers only)
- // ::= _A <basis> # based function (pointers only)
- // ::= _B <basis> # based function (far?) (pointers only)
- // ::= _C <basis> # based method (pointers only)
- // ::= _D <basis> # based method (far?) (pointers only)
- // ::= _E # block (Clang)
- // <basis> ::= 0 # __based(void)
- // ::= 1 # __based(segment)?
- // ::= 2 <name> # __based(name)
- // ::= 3 # ?
- // ::= 4 # ?
- // ::= 5 # not really based
- bool HasConst = Quals.hasConst(),
- HasVolatile = Quals.hasVolatile();
- if (!IsMember) {
- if (HasConst && HasVolatile) {
- Out << 'D';
- } else if (HasVolatile) {
- Out << 'C';
- } else if (HasConst) {
- Out << 'B';
- } else {
- Out << 'A';
- }
- } else {
- if (HasConst && HasVolatile) {
- Out << 'T';
- } else if (HasVolatile) {
- Out << 'S';
- } else if (HasConst) {
- Out << 'R';
- } else {
- Out << 'Q';
- }
- }
-
- // 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
- bool HasConst = Quals.hasConst(),
- HasVolatile = Quals.hasVolatile();
- if (HasConst && HasVolatile) {
- Out << 'S';
- } else if (HasVolatile) {
- Out << 'R';
- } else if (HasConst) {
- Out << 'Q';
- } else {
- Out << 'P';
- }
-}
-
-void MicrosoftCXXNameMangler::mangleArgumentType(QualType T,
- SourceRange Range) {
- void *TypePtr = getASTContext().getCanonicalType(T).getAsOpaquePtr();
- ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr);
-
- if (Found == TypeBackReferences.end()) {
- size_t OutSizeBefore = Out.GetNumBytesInBuffer();
-
- mangleType(T, Range, false);
-
- // See if it's worth creating a back reference.
- // Only types longer than 1 character are considered
- // and only 10 back references slots are available:
- bool LongerThanOneChar = (Out.GetNumBytesInBuffer() - OutSizeBefore > 1);
- if (LongerThanOneChar && TypeBackReferences.size() < 10) {
- size_t Size = TypeBackReferences.size();
- TypeBackReferences[TypePtr] = Size;
- }
- } else {
- Out << Found->second;
- }
-}
-
-void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
- bool MangleQualifiers) {
- // Only operate on the canonical type!
- T = getASTContext().getCanonicalType(T);
-
- Qualifiers Quals = T.getLocalQualifiers();
- // We have to mangle these now, while we still have enough information.
- if (T->isAnyPointerType() || T->isMemberPointerType() ||
- T->isBlockPointerType()) {
- manglePointerQualifiers(Quals);
- } else if (Quals && MangleQualifiers) {
- mangleQualifiers(Quals, false);
- }
-
- SplitQualType split = T.split();
- const Type *ty = split.Ty;
-
- // If we're mangling a qualified array type, push the qualifiers to
- // the element type.
- if (split.Quals && isa<ArrayType>(T)) {
- ty = Context.getASTContext().getAsArrayType(T);
- }
-
- switch (ty->getTypeClass()) {
-#define ABSTRACT_TYPE(CLASS, PARENT)
-#define NON_CANONICAL_TYPE(CLASS, PARENT) \
- case Type::CLASS: \
- llvm_unreachable("can't mangle non-canonical type " #CLASS "Type"); \
- return;
-#define TYPE(CLASS, PARENT) \
- case Type::CLASS: \
- mangleType(cast<CLASS##Type>(ty), Range); \
- break;
-#include "clang/AST/TypeNodes.def"
-#undef ABSTRACT_TYPE
-#undef NON_CANONICAL_TYPE
-#undef TYPE
- }
-}
-
-void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T,
- SourceRange Range) {
- // <type> ::= <builtin-type>
- // <builtin-type> ::= X # void
- // ::= C # signed char
- // ::= D # char
- // ::= E # unsigned char
- // ::= F # short
- // ::= G # unsigned short (or wchar_t if it's not a builtin)
- // ::= H # int
- // ::= I # unsigned int
- // ::= J # long
- // ::= K # unsigned long
- // L # <none>
- // ::= M # float
- // ::= N # double
- // ::= O # long double (__float80 is mangled differently)
- // ::= _J # long long, __int64
- // ::= _K # unsigned long long, __int64
- // ::= _L # __int128
- // ::= _M # unsigned __int128
- // ::= _N # bool
- // _O # <array in parameter>
- // ::= _T # __float80 (Intel)
- // ::= _W # wchar_t
- // ::= _Z # __float80 (Digital Mars)
- switch (T->getKind()) {
- case BuiltinType::Void: Out << 'X'; break;
- case BuiltinType::SChar: Out << 'C'; break;
- case BuiltinType::Char_U: case BuiltinType::Char_S: Out << 'D'; break;
- case BuiltinType::UChar: Out << 'E'; break;
- case BuiltinType::Short: Out << 'F'; break;
- case BuiltinType::UShort: Out << 'G'; break;
- case BuiltinType::Int: Out << 'H'; break;
- case BuiltinType::UInt: Out << 'I'; break;
- case BuiltinType::Long: Out << 'J'; break;
- case BuiltinType::ULong: Out << 'K'; break;
- case BuiltinType::Float: Out << 'M'; break;
- case BuiltinType::Double: Out << 'N'; break;
- // TODO: Determine size and mangle accordingly
- case BuiltinType::LongDouble: Out << 'O'; break;
- case BuiltinType::LongLong: Out << "_J"; break;
- case BuiltinType::ULongLong: Out << "_K"; break;
- case BuiltinType::Int128: Out << "_L"; break;
- case BuiltinType::UInt128: Out << "_M"; break;
- case BuiltinType::Bool: Out << "_N"; break;
- case BuiltinType::WChar_S:
- case BuiltinType::WChar_U: Out << "_W"; break;
-
-#define BUILTIN_TYPE(Id, SingletonId)
-#define PLACEHOLDER_TYPE(Id, SingletonId) \
- case BuiltinType::Id:
-#include "clang/AST/BuiltinTypes.def"
- case BuiltinType::Dependent:
- llvm_unreachable("placeholder types shouldn't get to name mangling");
-
- case BuiltinType::ObjCId: Out << "PAUobjc_object@@"; break;
- case BuiltinType::ObjCClass: Out << "PAUobjc_class@@"; break;
- case BuiltinType::ObjCSel: Out << "PAUobjc_selector@@"; break;
-
- case BuiltinType::OCLImage1d: Out << "PAUocl_image1d@@"; break;
- case BuiltinType::OCLImage1dArray: Out << "PAUocl_image1darray@@"; break;
- case BuiltinType::OCLImage1dBuffer: Out << "PAUocl_image1dbuffer@@"; break;
- case BuiltinType::OCLImage2d: Out << "PAUocl_image2d@@"; break;
- case BuiltinType::OCLImage2dArray: Out << "PAUocl_image2darray@@"; break;
- case BuiltinType::OCLImage3d: Out << "PAUocl_image3d@@"; break;
-
- case BuiltinType::NullPtr: Out << "$$T"; break;
-
- case BuiltinType::Char16:
- case BuiltinType::Char32:
- case BuiltinType::Half: {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this built-in %0 type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << T->getName(Context.getASTContext().getPrintingPolicy())
- << Range;
- break;
- }
- }
-}
-
-// <type> ::= <function-type>
-void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T,
- SourceRange) {
- // Structors only appear in decls, so at this point we know it's not a
- // structor type.
- // FIXME: This may not be lambda-friendly.
- Out << "$$A6";
- mangleType(T, NULL, false, false);
-}
-void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T,
- SourceRange) {
- llvm_unreachable("Can't mangle K&R function prototypes");
-}
-
-void MicrosoftCXXNameMangler::mangleType(const FunctionType *T,
- const FunctionDecl *D,
- bool IsStructor,
- bool IsInstMethod) {
- // <function-type> ::= <this-cvr-qualifiers> <calling-convention>
- // <return-type> <argument-list> <throw-spec>
- const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
-
- // If this is a C++ instance method, mangle the CVR qualifiers for the
- // this pointer.
- if (IsInstMethod)
- mangleQualifiers(Qualifiers::fromCVRMask(Proto->getTypeQuals()), false);
-
- mangleCallingConvention(T, IsInstMethod);
-
- // <return-type> ::= <type>
- // ::= @ # structors (they have no declared return type)
- if (IsStructor)
- Out << '@';
- else {
- QualType Result = Proto->getResultType();
- const Type* RT = Result.getTypePtr();
- if (!RT->isAnyPointerType() && !RT->isReferenceType()) {
- if (Result.hasQualifiers() || !RT->isBuiltinType())
- Out << '?';
- if (!RT->isBuiltinType() && !Result.hasQualifiers()) {
- // Lack of qualifiers for user types is mangled as 'A'.
- Out << 'A';
- }
- }
-
- // FIXME: Get the source range for the result type. Or, better yet,
- // implement the unimplemented stuff so we don't need accurate source
- // location info anymore :).
- mangleType(Result, SourceRange());
- }
-
- // <argument-list> ::= X # void
- // ::= <type>+ @
- // ::= <type>* Z # varargs
- if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) {
- Out << 'X';
- } else {
- if (D) {
- // If we got a decl, use the type-as-written to make sure arrays
- // get mangled right. Note that we can't rely on the TSI
- // existing if (for example) the parameter was synthesized.
- for (FunctionDecl::param_const_iterator Parm = D->param_begin(),
- ParmEnd = D->param_end(); Parm != ParmEnd; ++Parm) {
- TypeSourceInfo *TSI = (*Parm)->getTypeSourceInfo();
- QualType Type = TSI ? TSI->getType() : (*Parm)->getType();
- mangleArgumentType(Type, (*Parm)->getSourceRange());
- }
- } 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, SourceRange());
- }
- // <builtin-type> ::= Z # ellipsis
- if (Proto->isVariadic())
- Out << 'Z';
- else
- Out << '@';
- }
-
- mangleThrowSpecification(Proto);
-}
-
-void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
- // <function-class> ::= A # private: near
- // ::= B # private: far
- // ::= C # private: static near
- // ::= D # private: static far
- // ::= E # private: virtual near
- // ::= F # private: virtual far
- // ::= G # private: thunk near
- // ::= H # private: thunk far
- // ::= I # protected: near
- // ::= J # protected: far
- // ::= K # protected: static near
- // ::= L # protected: static far
- // ::= M # protected: virtual near
- // ::= N # protected: virtual far
- // ::= O # protected: thunk near
- // ::= P # protected: thunk far
- // ::= Q # public: near
- // ::= R # public: far
- // ::= S # public: static near
- // ::= T # public: static far
- // ::= U # public: virtual near
- // ::= V # public: virtual far
- // ::= W # public: thunk near
- // ::= X # public: thunk far
- // ::= Y # global near
- // ::= Z # global far
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
- switch (MD->getAccess()) {
- default:
- case AS_private:
- if (MD->isStatic())
- Out << 'C';
- else if (MD->isVirtual())
- Out << 'E';
- else
- Out << 'A';
- break;
- case AS_protected:
- if (MD->isStatic())
- Out << 'K';
- else if (MD->isVirtual())
- Out << 'M';
- else
- Out << 'I';
- break;
- case AS_public:
- if (MD->isStatic())
- Out << 'S';
- else if (MD->isVirtual())
- Out << 'U';
- else
- Out << 'Q';
- }
- } else
- Out << 'Y';
-}
-void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T,
- bool IsInstMethod) {
- // <calling-convention> ::= A # __cdecl
- // ::= B # __export __cdecl
- // ::= C # __pascal
- // ::= D # __export __pascal
- // ::= E # __thiscall
- // ::= F # __export __thiscall
- // ::= G # __stdcall
- // ::= H # __export __stdcall
- // ::= I # __fastcall
- // ::= J # __export __fastcall
- // The 'export' calling conventions are from a bygone era
- // (*cough*Win16*cough*) when functions were declared for export with
- // that keyword. (It didn't actually export them, it just made them so
- // that they could be in a DLL and somebody from another module could call
- // them.)
- CallingConv CC = T->getCallConv();
- if (CC == CC_Default) {
- if (IsInstMethod) {
- const FunctionProtoType *FPT =
- T->getCanonicalTypeUnqualified().castAs<FunctionProtoType>();
- bool isVariadic = FPT->isVariadic();
- CC = getASTContext().getDefaultCXXMethodCallConv(isVariadic);
- } else {
- CC = CC_C;
- }
- }
- switch (CC) {
- default:
- llvm_unreachable("Unsupported CC for mangling");
- case CC_Default:
- case CC_C: Out << 'A'; break;
- case CC_X86Pascal: Out << 'C'; break;
- case CC_X86ThisCall: Out << 'E'; break;
- case CC_X86StdCall: Out << 'G'; break;
- case CC_X86FastCall: Out << 'I'; break;
- }
-}
-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';
-}
-
-void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T,
- SourceRange Range) {
- // Probably should be mangled as a template instantiation; need to see what
- // VC does first.
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this unresolved dependent type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-// <type> ::= <union-type> | <struct-type> | <class-type> | <enum-type>
-// <union-type> ::= T <name>
-// <struct-type> ::= U <name>
-// <class-type> ::= V <name>
-// <enum-type> ::= W <size> <name>
-void MicrosoftCXXNameMangler::mangleType(const EnumType *T, SourceRange) {
- mangleType(cast<TagType>(T));
-}
-void MicrosoftCXXNameMangler::mangleType(const RecordType *T, SourceRange) {
- mangleType(cast<TagType>(T));
-}
-void MicrosoftCXXNameMangler::mangleType(const TagType *T) {
- switch (T->getDecl()->getTagKind()) {
- case TTK_Union:
- Out << 'T';
- break;
- case TTK_Struct:
- case TTK_Interface:
- Out << 'U';
- break;
- case TTK_Class:
- Out << 'V';
- break;
- case TTK_Enum:
- Out << 'W';
- Out << getASTContext().getTypeSizeInChars(
- cast<EnumDecl>(T->getDecl())->getIntegerType()).getQuantity();
- break;
- }
- mangleName(T->getDecl());
-}
-
-// <type> ::= <array-type>
-// <array-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers>
-// [Y <dimension-count> <dimension>+]
-// <element-type> # as global
-// ::= Q <cvr-qualifiers> [Y <dimension-count> <dimension>+]
-// <element-type> # as param
-// It's supposed to be the other way around, but for some strange reason, it
-// isn't. Today this behavior is retained for the sole purpose of backwards
-// compatibility.
-void MicrosoftCXXNameMangler::mangleType(const ArrayType *T, bool IsGlobal) {
- // This isn't a recursive mangling, so now we have to do it all in this
- // one call.
- if (IsGlobal) {
- manglePointerQualifiers(T->getElementType().getQualifiers());
- } else {
- Out << 'Q';
- }
- mangleExtraDimensions(T->getElementType());
-}
-void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T,
- SourceRange) {
- mangleType(cast<ArrayType>(T), false);
-}
-void MicrosoftCXXNameMangler::mangleType(const VariableArrayType *T,
- SourceRange) {
- mangleType(cast<ArrayType>(T), false);
-}
-void MicrosoftCXXNameMangler::mangleType(const DependentSizedArrayType *T,
- SourceRange) {
- mangleType(cast<ArrayType>(T), false);
-}
-void MicrosoftCXXNameMangler::mangleType(const IncompleteArrayType *T,
- SourceRange) {
- mangleType(cast<ArrayType>(T), false);
-}
-void MicrosoftCXXNameMangler::mangleExtraDimensions(QualType ElementTy) {
- SmallVector<llvm::APInt, 3> Dimensions;
- for (;;) {
- if (const ConstantArrayType *CAT =
- getASTContext().getAsConstantArrayType(ElementTy)) {
- Dimensions.push_back(CAT->getSize());
- ElementTy = CAT->getElementType();
- } else if (ElementTy->isVariableArrayType()) {
- const VariableArrayType *VAT =
- getASTContext().getAsVariableArrayType(ElementTy);
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this variable-length array yet");
- Diags.Report(VAT->getSizeExpr()->getExprLoc(), DiagID)
- << VAT->getBracketsRange();
- return;
- } else if (ElementTy->isDependentSizedArrayType()) {
- // The dependent expression has to be folded into a constant (TODO).
- const DependentSizedArrayType *DSAT =
- getASTContext().getAsDependentSizedArrayType(ElementTy);
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this dependent-length array yet");
- Diags.Report(DSAT->getSizeExpr()->getExprLoc(), DiagID)
- << DSAT->getBracketsRange();
- return;
- } else if (ElementTy->isIncompleteArrayType()) continue;
- else break;
- }
- mangleQualifiers(ElementTy.getQualifiers(), false);
- // If there are any additional dimensions, mangle them now.
- if (Dimensions.size() > 0) {
- Out << 'Y';
- // <dimension-count> ::= <number> # number of extra dimensions
- mangleNumber(Dimensions.size());
- for (unsigned Dim = 0; Dim < Dimensions.size(); ++Dim) {
- mangleNumber(Dimensions[Dim].getLimitedValue());
- }
- }
- mangleType(ElementTy.getLocalUnqualifiedType(), SourceRange());
-}
-
-// <type> ::= <pointer-to-member-type>
-// <pointer-to-member-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers>
-// <class name> <type>
-void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T,
- SourceRange Range) {
- QualType PointeeType = T->getPointeeType();
- if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) {
- Out << '8';
- mangleName(T->getClass()->castAs<RecordType>()->getDecl());
- mangleType(FPT, NULL, false, true);
- } else {
- mangleQualifiers(PointeeType.getQualifiers(), true);
- mangleName(T->getClass()->castAs<RecordType>()->getDecl());
- mangleType(PointeeType.getLocalUnqualifiedType(), Range);
- }
-}
-
-void MicrosoftCXXNameMangler::mangleType(const TemplateTypeParmType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this template type parameter type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(
- const SubstTemplateTypeParmPackType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this substituted parameter pack yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-// <type> ::= <pointer-type>
-// <pointer-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers> <type>
-void MicrosoftCXXNameMangler::mangleType(const PointerType *T,
- SourceRange Range) {
- QualType PointeeTy = T->getPointeeType();
- if (PointeeTy->isArrayType()) {
- // Pointers to arrays are mangled like arrays.
- mangleExtraDimensions(PointeeTy);
- } else if (const FunctionType *FT = PointeeTy->getAs<FunctionType>()) {
- // Function pointers are special.
- Out << '6';
- mangleType(FT, NULL, false, false);
- } else {
- mangleQualifiers(PointeeTy.getQualifiers(), false);
- mangleType(PointeeTy, Range, false);
- }
-}
-void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,
- SourceRange Range) {
- // Object pointers never have qualifiers.
- Out << 'A';
- mangleType(T->getPointeeType(), Range);
-}
-
-// <type> ::= <reference-type>
-// <reference-type> ::= A <cvr-qualifiers> <type>
-void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T,
- SourceRange Range) {
- Out << 'A';
- QualType PointeeTy = T->getPointeeType();
- if (!PointeeTy.hasQualifiers())
- // Lack of qualifiers is mangled as 'A'.
- Out << 'A';
- mangleType(PointeeTy, Range);
-}
-
-// <type> ::= <r-value-reference-type>
-// <r-value-reference-type> ::= $$Q <cvr-qualifiers> <type>
-void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T,
- SourceRange Range) {
- Out << "$$Q";
- QualType PointeeTy = T->getPointeeType();
- if (!PointeeTy.hasQualifiers())
- // Lack of qualifiers is mangled as 'A'.
- Out << 'A';
- mangleType(PointeeTy, Range);
-}
-
-void MicrosoftCXXNameMangler::mangleType(const ComplexType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this complex number type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const VectorType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this vector type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this extended vector type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this dependent-sized extended vector type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T,
- SourceRange) {
- // ObjC interfaces have structs underlying them.
- Out << 'U';
- mangleName(T->getDecl());
-}
-
-void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T,
- SourceRange Range) {
- // We don't allow overloading by different protocol qualification,
- // so mangling them isn't necessary.
- mangleType(T->getBaseType(), Range);
-}
-
-void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T,
- SourceRange Range) {
- Out << "_E";
-
- QualType pointee = T->getPointeeType();
- mangleType(pointee->castAs<FunctionProtoType>(), NULL, false, false);
-}
-
-void MicrosoftCXXNameMangler::mangleType(const InjectedClassNameType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this injected class name type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const TemplateSpecializationType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this template specialization type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const DependentNameType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this dependent name type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(
- const DependentTemplateSpecializationType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this dependent template specialization type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const PackExpansionType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this pack expansion yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this typeof(type) yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const TypeOfExprType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this typeof(expression) yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this decltype() yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const UnaryTransformType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this unary transform type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const AutoType *T, SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this 'auto' type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const AtomicType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this C11 atomic type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftMangleContext::mangleName(const NamedDecl *D,
- raw_ostream &Out) {
- assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
- "Invalid mangleName() call, argument is not a variable or function!");
- assert(!isa<CXXConstructorDecl>(D) && !isa<CXXDestructorDecl>(D) &&
- "Invalid mangleName() call on 'structor decl!");
-
- PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
- getASTContext().getSourceManager(),
- "Mangling declaration");
-
- MicrosoftCXXNameMangler Mangler(*this, Out);
- return Mangler.mangle(D);
-}
-void MicrosoftMangleContext::mangleThunk(const CXXMethodDecl *MD,
- const ThunkInfo &Thunk,
- raw_ostream &) {
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle thunk for this method yet");
- getDiags().Report(MD->getLocation(), DiagID);
-}
-void MicrosoftMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD,
- CXXDtorType Type,
- const ThisAdjustment &,
- raw_ostream &) {
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle thunk for this destructor yet");
- getDiags().Report(DD->getLocation(), DiagID);
-}
-void MicrosoftMangleContext::mangleCXXVTable(const CXXRecordDecl *RD,
- raw_ostream &Out) {
- // <mangled-name> ::= ? <operator-name> <class-name> <storage-class>
- // <cvr-qualifiers> [<name>] @
- // <operator-name> ::= _7 # vftable
- // ::= _8 # vbtable
- // NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class>
- // is always '6' for vftables and '7' for vbtables. (The difference is
- // beyond me.)
- // TODO: vbtables.
- MicrosoftCXXNameMangler Mangler(*this, Out);
- Mangler.getStream() << "\01??_7";
- Mangler.mangleName(RD);
- Mangler.getStream() << "6B";
- // TODO: If the class has more than one vtable, mangle in the class it came
- // from.
- Mangler.getStream() << '@';
-}
-void MicrosoftMangleContext::mangleCXXVTT(const CXXRecordDecl *RD,
- raw_ostream &) {
- llvm_unreachable("The MS C++ ABI does not have virtual table tables!");
-}
-void MicrosoftMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD,
- int64_t Offset,
- const CXXRecordDecl *Type,
- raw_ostream &) {
- llvm_unreachable("The MS C++ ABI does not have constructor vtables!");
-}
-void MicrosoftMangleContext::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 MicrosoftMangleContext::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 MicrosoftMangleContext::mangleCXXCtor(const CXXConstructorDecl *D,
- CXXCtorType Type,
- raw_ostream & Out) {
- MicrosoftCXXNameMangler mangler(*this, Out);
- mangler.mangle(D);
-}
-void MicrosoftMangleContext::mangleCXXDtor(const CXXDestructorDecl *D,
- CXXDtorType Type,
- raw_ostream & Out) {
- MicrosoftCXXNameMangler mangler(*this, Out);
- mangler.mangle(D);
-}
-void MicrosoftMangleContext::mangleReferenceTemporary(const clang::VarDecl *VD,
- raw_ostream &) {
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this reference temporary yet");
- getDiags().Report(VD->getLocation(), DiagID);
-}
-
-MangleContext *clang::createMicrosoftMangleContext(ASTContext &Context,
- DiagnosticsEngine &Diags) {
- return new MicrosoftMangleContext(Context, Diags);
-}
+//===--- MicrosoftMangle.cpp - Microsoft Visual C++ Name Mangling ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This provides C++ name mangling targeting the Microsoft Visual C++ ABI. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/Mangle.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.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/ExprCXX.h" +#include "clang/Basic/ABI.h" +#include "clang/Basic/DiagnosticOptions.h" +#include <map> + +using namespace clang; + +namespace { + +/// MicrosoftCXXNameMangler - Manage the mangling of a single name for the +/// Microsoft Visual C++ ABI. +class MicrosoftCXXNameMangler { + MangleContext &Context; + raw_ostream &Out; + + // FIXME: audit the performance of BackRefMap as it might do way too many + // copying of strings. + typedef std::map<std::string, unsigned> BackRefMap; + BackRefMap NameBackReferences; + bool UseNameBackReferences; + + typedef llvm::DenseMap<void*, unsigned> ArgBackRefMap; + ArgBackRefMap TypeBackReferences; + + ASTContext &getASTContext() const { return Context.getASTContext(); } + +public: + MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_) + : Context(C), Out(Out_), UseNameBackReferences(true) { } + + raw_ostream &getStream() const { return Out; } + + void mangle(const NamedDecl *D, StringRef Prefix = "\01?"); + void mangleName(const NamedDecl *ND); + void mangleFunctionEncoding(const FunctionDecl *FD); + void mangleVariableEncoding(const VarDecl *VD); + void mangleNumber(int64_t Number); + void mangleNumber(const llvm::APSInt &Value); + void mangleType(QualType T, SourceRange Range, bool MangleQualifiers = true); + +private: + void disableBackReferences() { UseNameBackReferences = false; } + void mangleUnqualifiedName(const NamedDecl *ND) { + mangleUnqualifiedName(ND, ND->getDeclName()); + } + void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name); + void mangleSourceName(const IdentifierInfo *II); + void manglePostfix(const DeclContext *DC, bool NoFunction=false); + void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc); + void mangleQualifiers(Qualifiers Quals, bool IsMember); + void manglePointerQualifiers(Qualifiers Quals); + + void mangleUnscopedTemplateName(const TemplateDecl *ND); + void mangleTemplateInstantiationName(const TemplateDecl *TD, + const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs); + void mangleObjCMethodName(const ObjCMethodDecl *MD); + void mangleLocalName(const FunctionDecl *FD); + + void mangleArgumentType(QualType T, SourceRange Range); + + // Declare manglers for every type class. +#define ABSTRACT_TYPE(CLASS, PARENT) +#define NON_CANONICAL_TYPE(CLASS, PARENT) +#define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T, \ + SourceRange Range); +#include "clang/AST/TypeNodes.def" +#undef ABSTRACT_TYPE +#undef NON_CANONICAL_TYPE +#undef TYPE + + void mangleType(const TagType*); + void mangleType(const FunctionType *T, const FunctionDecl *D, + bool IsStructor, bool IsInstMethod); + void mangleType(const ArrayType *T, bool IsGlobal); + void mangleExtraDimensions(QualType T); + void mangleFunctionClass(const FunctionDecl *FD); + void mangleCallingConvention(const FunctionType *T, bool IsInstMethod = false); + void mangleIntegerLiteral(const llvm::APSInt &Number, bool IsBoolean); + void mangleExpression(const Expr *E); + void mangleThrowSpecification(const FunctionProtoType *T); + + void mangleTemplateArgs( + const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs); + +}; + +/// MicrosoftMangleContext - Overrides the default MangleContext for the +/// Microsoft Visual C++ ABI. +class MicrosoftMangleContext : public MangleContext { +public: + MicrosoftMangleContext(ASTContext &Context, + DiagnosticsEngine &Diags) : MangleContext(Context, Diags) { } + virtual bool shouldMangleDeclName(const NamedDecl *D); + virtual void mangleName(const NamedDecl *D, raw_ostream &Out); + 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 mangleCXXVTable(const CXXRecordDecl *RD, + raw_ostream &); + virtual void mangleCXXVTT(const CXXRecordDecl *RD, + raw_ostream &); + virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, + const CXXRecordDecl *Type, + raw_ostream &); + virtual void mangleCXXRTTI(QualType T, raw_ostream &); + virtual void mangleCXXRTTIName(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 clang::VarDecl *, + raw_ostream &); +}; + +} + +static bool isInCLinkageSpecification(const Decl *D) { + D = D->getCanonicalDecl(); + for (const DeclContext *DC = D->getDeclContext(); + !DC->isTranslationUnit(); DC = DC->getParent()) { + if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) + return Linkage->getLanguage() == LinkageSpecDecl::lang_c; + } + + return false; +} + +bool MicrosoftMangleContext::shouldMangleDeclName(const NamedDecl *D) { + // In C, functions with no attributes never need to be mangled. Fastpath them. + if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs()) + return false; + + // Any decl can be declared with __asm("foo") on it, and this takes precedence + // over all other naming in the .o file. + if (D->hasAttr<AsmLabelAttr>()) + return true; + + // Clang's "overloadable" attribute extension to C/C++ implies name mangling + // (always) as does passing a C++ member function and a function + // whose name is not a simple identifier. + const FunctionDecl *FD = dyn_cast<FunctionDecl>(D); + if (FD && (FD->hasAttr<OverloadableAttr>() || isa<CXXMethodDecl>(FD) || + !FD->getDeclName().isIdentifier())) + return true; + + // Otherwise, no mangling is done outside C++ mode. + if (!getASTContext().getLangOpts().CPlusPlus) + return false; + + // Variables at global scope with internal linkage are not mangled. + if (!FD) { + const DeclContext *DC = D->getDeclContext(); + if (DC->isTranslationUnit() && D->getLinkage() == InternalLinkage) + return false; + } + + // C functions and "main" are not mangled. + if ((FD && FD->isMain()) || isInCLinkageSpecification(D)) + return false; + + return true; +} + +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 + // default, we emit an asm marker at the start so we get the name right. + // Callers can override this with a custom prefix. + + // Any decl can be declared with __asm("foo") on it, and this takes precedence + // over all other naming in the .o file. + if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) { + // If we have an asm name, then we use it as the mangling. + Out << '\01' << ALA->getLabel(); + return; + } + + // <mangled-name> ::= ? <name> <type-encoding> + Out << Prefix; + mangleName(D); + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + mangleFunctionEncoding(FD); + else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) + mangleVariableEncoding(VD); + else { + // 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(); + } +} + +void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { + // <type-encoding> ::= <function-class> <function-type> + + // Don't mangle in the type if this isn't a decl we should typically mangle. + if (!Context.shouldMangleDeclName(FD)) + return; + + // We should never ever see a FunctionNoProtoType at this point. + // We don't even know how to mangle their types anyway :). + const FunctionProtoType *FT = FD->getType()->castAs<FunctionProtoType>(); + + bool InStructor = false, InInstMethod = false; + const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); + if (MD) { + if (MD->isInstance()) + InInstMethod = true; + if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) + InStructor = true; + } + + // First, the function class. + mangleFunctionClass(FD); + + mangleType(FT, FD, InStructor, InInstMethod); +} + +void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) { + // <type-encoding> ::= <storage-class> <variable-type> + // <storage-class> ::= 0 # private static member + // ::= 1 # protected static member + // ::= 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. + switch (VD->getAccess()) { + default: + case AS_private: Out << '0'; break; + case AS_protected: Out << '1'; break; + case AS_public: Out << '2'; break; + } + } + else if (!VD->isStaticLocal()) + Out << '3'; + else + Out << '4'; + // Now mangle the type. + // <variable-type> ::= <type> <cvr-qualifiers> + // ::= <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(); + if (Ty->isPointerType() || Ty->isReferenceType()) { + mangleType(Ty, TL.getSourceRange()); + mangleQualifiers(Ty->getPointeeType().getQualifiers(), false); + } else if (const ArrayType *AT = getASTContext().getAsArrayType(Ty)) { + // Global arrays are funny, too. + mangleType(AT, true); + mangleQualifiers(Ty.getQualifiers(), false); + } else { + mangleType(Ty.getLocalUnqualifiedType(), TL.getSourceRange()); + mangleQualifiers(Ty.getLocalQualifiers(), false); + } +} + +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(); + + manglePostfix(DC); + + // Terminate the whole name with an '@'. + Out << '@'; +} + +void MicrosoftCXXNameMangler::mangleNumber(int64_t Number) { + llvm::APSInt APSNumber(/*BitWidth=*/64, /*isUnsigned=*/false); + APSNumber = Number; + mangleNumber(APSNumber); +} + +void MicrosoftCXXNameMangler::mangleNumber(const llvm::APSInt &Value) { + // <number> ::= [?] <decimal digit> # 1 <= Number <= 10 + // ::= [?] <hex digit>+ @ # 0 or > 9; A = 0, B = 1, etc... + // ::= [?] @ # 0 (alternate mangling, not emitted by VC) + if (Value.isSigned() && Value.isNegative()) { + Out << '?'; + mangleNumber(llvm::APSInt(Value.abs())); + return; + } + llvm::APSInt Temp(Value); + // There's a special shorter mangling for 0, but Microsoft + // chose not to use it. Instead, 0 gets mangled as "A@". Oh well... + if (Value.uge(1) && Value.ule(10)) { + --Temp; + Temp.print(Out, false); + } else { + // We have to build up the encoding in reverse order, so it will come + // out right when we write it out. + char Encoding[64]; + char *EndPtr = Encoding+sizeof(Encoding); + char *CurPtr = EndPtr; + llvm::APSInt NibbleMask(Value.getBitWidth(), Value.isUnsigned()); + NibbleMask = 0xf; + do { + *--CurPtr = 'A' + Temp.And(NibbleMask).getLimitedValue(0xf); + Temp = Temp.lshr(4); + } while (Temp != 0); + Out.write(CurPtr, EndPtr-CurPtr); + Out << '@'; + } +} + +static const TemplateDecl * +isTemplate(const NamedDecl *ND, + SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) { + // Check if we have a function template. + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){ + if (const TemplateDecl *TD = FD->getPrimaryTemplate()) { + if (FD->getTemplateSpecializationArgsAsWritten()) { + const ASTTemplateArgumentListInfo *ArgList = + FD->getTemplateSpecializationArgsAsWritten(); + TemplateArgs.append(ArgList->getTemplateArgs(), + ArgList->getTemplateArgs() + + ArgList->NumTemplateArgs); + } else { + const TemplateArgumentList *ArgList = + FD->getTemplateSpecializationArgs(); + TemplateArgumentListInfo LI; + for (unsigned i = 0, e = ArgList->size(); i != e; ++i) + TemplateArgs.push_back(TemplateArgumentLoc(ArgList->get(i), + FD->getTypeSourceInfo())); + } + return TD; + } + } + + // Check if we have a class template. + if (const ClassTemplateSpecializationDecl *Spec = + dyn_cast<ClassTemplateSpecializationDecl>(ND)) { + TypeSourceInfo *TSI = Spec->getTypeAsWritten(); + if (TSI) { + TemplateSpecializationTypeLoc TSTL = + cast<TemplateSpecializationTypeLoc>(TSI->getTypeLoc()); + TemplateArgumentListInfo LI(TSTL.getLAngleLoc(), TSTL.getRAngleLoc()); + for (unsigned i = 0, e = TSTL.getNumArgs(); i != e; ++i) + TemplateArgs.push_back(TSTL.getArgLoc(i)); + } else { + TemplateArgumentListInfo LI; + const TemplateArgumentList &ArgList = + Spec->getTemplateArgs(); + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) + TemplateArgs.push_back(TemplateArgumentLoc(ArgList[i], + TemplateArgumentLocInfo())); + } + return Spec->getSpecializedTemplate(); + } + + return 0; +} + +void +MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, + DeclarationName Name) { + // <unqualified-name> ::= <operator-name> + // ::= <ctor-dtor-name> + // ::= <source-name> + // ::= <template-name> + SmallVector<TemplateArgumentLoc, 2> TemplateArgs; + // Check if we have a template. + if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { + // We have a 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 + // void foo(A::X<A::Y>, A::X<B::Y>), + // the A::X<> part is not aliased. + // That said, from the mangler's perspective we have a structure like this: + // namespace[s] -> type[ -> template-parameters] + // but from the Clang perspective we have + // 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; + } + return; + } + + switch (Name.getNameKind()) { + case DeclarationName::Identifier: { + if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) { + mangleSourceName(II); + 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; + } + } + + // We must have an anonymous struct. + const TagDecl *TD = cast<TagDecl>(ND); + if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) { + assert(TD->getDeclContext() == D->getDeclContext() && + "Typedef should not be in another decl context!"); + assert(D->getDeclName().getAsIdentifierInfo() && + "Typedef was not named!"); + mangleSourceName(D->getDeclName().getAsIdentifierInfo()); + break; + } + + // When VC encounters an anonymous type with no tag and no typedef, + // it literally emits '<unnamed-tag>'. + Out << "<unnamed-tag>"; + break; + } + + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + llvm_unreachable("Can't mangle Objective-C selector names here!"); + + case DeclarationName::CXXConstructorName: + Out << "?0"; + break; + + case DeclarationName::CXXDestructorName: + Out << "?1"; + 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); + break; + } + + case DeclarationName::CXXUsingDirective: + llvm_unreachable("Can't mangle a using directive name!"); + } +} + +void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC, + bool NoFunction) { + // <postfix> ::= <unqualified-name> [<postfix>] + // ::= <substitution> [<postfix>] + + if (!DC) return; + + while (isa<LinkageSpecDecl>(DC)) + DC = DC->getParent(); + + if (DC->isTranslationUnit()) + return; + + if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) { + Context.mangleBlock(BD, Out); + Out << '@'; + return manglePostfix(DC->getParent(), NoFunction); + } + + 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); + } +} + +void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, + SourceLocation Loc) { + switch (OO) { + // ?0 # constructor + // ?1 # destructor + // <operator-name> ::= ?2 # new + case OO_New: Out << "?2"; break; + // <operator-name> ::= ?3 # delete + case OO_Delete: Out << "?3"; break; + // <operator-name> ::= ?4 # = + case OO_Equal: Out << "?4"; break; + // <operator-name> ::= ?5 # >> + case OO_GreaterGreater: Out << "?5"; break; + // <operator-name> ::= ?6 # << + case OO_LessLess: Out << "?6"; break; + // <operator-name> ::= ?7 # ! + case OO_Exclaim: Out << "?7"; break; + // <operator-name> ::= ?8 # == + case OO_EqualEqual: Out << "?8"; break; + // <operator-name> ::= ?9 # != + case OO_ExclaimEqual: Out << "?9"; break; + // <operator-name> ::= ?A # [] + case OO_Subscript: Out << "?A"; break; + // ?B # conversion + // <operator-name> ::= ?C # -> + case OO_Arrow: Out << "?C"; break; + // <operator-name> ::= ?D # * + case OO_Star: Out << "?D"; break; + // <operator-name> ::= ?E # ++ + case OO_PlusPlus: Out << "?E"; break; + // <operator-name> ::= ?F # -- + case OO_MinusMinus: Out << "?F"; break; + // <operator-name> ::= ?G # - + case OO_Minus: Out << "?G"; break; + // <operator-name> ::= ?H # + + case OO_Plus: Out << "?H"; break; + // <operator-name> ::= ?I # & + case OO_Amp: Out << "?I"; break; + // <operator-name> ::= ?J # ->* + case OO_ArrowStar: Out << "?J"; break; + // <operator-name> ::= ?K # / + case OO_Slash: Out << "?K"; break; + // <operator-name> ::= ?L # % + case OO_Percent: Out << "?L"; break; + // <operator-name> ::= ?M # < + case OO_Less: Out << "?M"; break; + // <operator-name> ::= ?N # <= + case OO_LessEqual: Out << "?N"; break; + // <operator-name> ::= ?O # > + case OO_Greater: Out << "?O"; break; + // <operator-name> ::= ?P # >= + case OO_GreaterEqual: Out << "?P"; break; + // <operator-name> ::= ?Q # , + case OO_Comma: Out << "?Q"; break; + // <operator-name> ::= ?R # () + case OO_Call: Out << "?R"; break; + // <operator-name> ::= ?S # ~ + case OO_Tilde: Out << "?S"; break; + // <operator-name> ::= ?T # ^ + case OO_Caret: Out << "?T"; break; + // <operator-name> ::= ?U # | + case OO_Pipe: Out << "?U"; break; + // <operator-name> ::= ?V # && + case OO_AmpAmp: Out << "?V"; break; + // <operator-name> ::= ?W # || + case OO_PipePipe: Out << "?W"; break; + // <operator-name> ::= ?X # *= + case OO_StarEqual: Out << "?X"; break; + // <operator-name> ::= ?Y # += + case OO_PlusEqual: Out << "?Y"; break; + // <operator-name> ::= ?Z # -= + case OO_MinusEqual: Out << "?Z"; break; + // <operator-name> ::= ?_0 # /= + case OO_SlashEqual: Out << "?_0"; break; + // <operator-name> ::= ?_1 # %= + case OO_PercentEqual: Out << "?_1"; break; + // <operator-name> ::= ?_2 # >>= + case OO_GreaterGreaterEqual: Out << "?_2"; break; + // <operator-name> ::= ?_3 # <<= + case OO_LessLessEqual: Out << "?_3"; break; + // <operator-name> ::= ?_4 # &= + case OO_AmpEqual: Out << "?_4"; break; + // <operator-name> ::= ?_5 # |= + case OO_PipeEqual: Out << "?_5"; break; + // <operator-name> ::= ?_6 # ^= + case OO_CaretEqual: Out << "?_6"; break; + // ?_7 # vftable + // ?_8 # vbtable + // ?_9 # vcall + // ?_A # typeof + // ?_B # local static guard + // ?_C # string + // ?_D # vbase destructor + // ?_E # vector deleting destructor + // ?_F # default constructor closure + // ?_G # scalar deleting destructor + // ?_H # vector constructor iterator + // ?_I # vector destructor iterator + // ?_J # vector vbase constructor iterator + // ?_K # virtual displacement map + // ?_L # eh vector constructor iterator + // ?_M # eh vector destructor iterator + // ?_N # eh vector vbase constructor iterator + // ?_O # copy constructor closure + // ?_P<name> # udt returning <name> + // ?_Q # <unknown> + // ?_R0 # RTTI Type Descriptor + // ?_R1 # RTTI Base Class Descriptor at (a,b,c,d) + // ?_R2 # RTTI Base Class Array + // ?_R3 # RTTI Class Hierarchy Descriptor + // ?_R4 # RTTI Complete Object Locator + // ?_S # local vftable + // ?_T # local vftable constructor closure + // <operator-name> ::= ?_U # new[] + 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, + "cannot mangle this conditional operator yet"); + Diags.Report(Loc, DiagID); + break; + } + + case OO_None: + case NUM_OVERLOADED_OPERATORS: + llvm_unreachable("Not an overloaded operator"); + } +} + +void MicrosoftCXXNameMangler::mangleSourceName(const IdentifierInfo *II) { + // <source name> ::= <identifier> @ + std::string key = II->getNameStart(); + BackRefMap::iterator Found; + if (UseNameBackReferences) + Found = NameBackReferences.find(key); + if (!UseNameBackReferences || Found == NameBackReferences.end()) { + Out << II->getName() << '@'; + if (UseNameBackReferences && NameBackReferences.size() < 10) { + size_t Size = NameBackReferences.size(); + NameBackReferences[key] = Size; + } + } else { + Out << Found->second; + } +} + +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 + int NestLevel = getLocalNestingLevel(FD); + Out << '?'; + mangleNumber(NestLevel); + Out << '?'; + mangle(FD, "?"); +} + +void MicrosoftCXXNameMangler::mangleTemplateInstantiationName( + const TemplateDecl *TD, + const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) { + // <template-name> ::= <unscoped-template-name> <template-args> + // ::= <substitution> + // Always start with the unqualified name. + + // Templates have their own context for back references. + ArgBackRefMap OuterArgsContext; + BackRefMap OuterTemplateContext; + NameBackReferences.swap(OuterTemplateContext); + TypeBackReferences.swap(OuterArgsContext); + + mangleUnscopedTemplateName(TD); + mangleTemplateArgs(TemplateArgs); + + // Restore the previous back reference contexts. + NameBackReferences.swap(OuterTemplateContext); + TypeBackReferences.swap(OuterArgsContext); +} + +void +MicrosoftCXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *TD) { + // <unscoped-template-name> ::= ?$ <unqualified-name> + Out << "?$"; + mangleUnqualifiedName(TD); +} + +void +MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value, + bool IsBoolean) { + // <integer-literal> ::= $0 <number> + Out << "$0"; + // Make sure booleans are encoded as 0/1. + if (IsBoolean && Value.getBoolValue()) + mangleNumber(1); + else + mangleNumber(Value); +} + +void +MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { + // See if this is a constant expression. + llvm::APSInt Value; + if (E->isIntegerConstantExpr(Value, Context.getASTContext())) { + mangleIntegerLiteral(Value, E->getType()->isBooleanType()); + return; + } + + // 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(); +} + +void +MicrosoftCXXNameMangler::mangleTemplateArgs( + const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) { + // <template-args> ::= {<type> | <integer-literal>}+ @ + unsigned NumTemplateArgs = TemplateArgs.size(); + for (unsigned i = 0; i < NumTemplateArgs; ++i) { + const TemplateArgumentLoc &TAL = TemplateArgs[i]; + const TemplateArgument &TA = TAL.getArgument(); + switch (TA.getKind()) { + case TemplateArgument::Null: + llvm_unreachable("Can't mangle null template arguments!"); + case TemplateArgument::Type: + mangleType(TA.getAsType(), TAL.getSourceRange()); + break; + case TemplateArgument::Integral: + mangleIntegerLiteral(TA.getAsIntegral(), + TA.getIntegralType()->isBooleanType()); + break; + case TemplateArgument::Expression: + mangleExpression(TA.getAsExpr()); + break; + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + case TemplateArgument::Declaration: + case TemplateArgument::NullPtr: + case TemplateArgument::Pack: { + // Issue a diagnostic. + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this %select{ERROR|ERROR|pointer/reference|nullptr|" + "integral|template|template pack expansion|ERROR|parameter pack}0 " + "template argument yet"); + Diags.Report(TAL.getLocation(), DiagID) + << TA.getKind() + << TAL.getSourceRange(); + } + } + } + Out << '@'; +} + +void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals, + bool IsMember) { + // <cvr-qualifiers> ::= [E] [F] [I] <base-cvr-qualifiers> + // 'E' means __ptr64 (32-bit only); 'F' means __unaligned (32/64-bit only); + // 'I' means __restrict (32/64-bit). + // Note that the MSVC __restrict keyword isn't the same as the C99 restrict + // keyword! + // <base-cvr-qualifiers> ::= A # near + // ::= B # near const + // ::= C # near volatile + // ::= D # near const volatile + // ::= E # far (16-bit) + // ::= F # far const (16-bit) + // ::= G # far volatile (16-bit) + // ::= H # far const volatile (16-bit) + // ::= I # huge (16-bit) + // ::= J # huge const (16-bit) + // ::= K # huge volatile (16-bit) + // ::= L # huge const volatile (16-bit) + // ::= M <basis> # based + // ::= N <basis> # based const + // ::= O <basis> # based volatile + // ::= P <basis> # based const volatile + // ::= Q # near member + // ::= R # near const member + // ::= S # near volatile member + // ::= T # near const volatile member + // ::= U # far member (16-bit) + // ::= V # far const member (16-bit) + // ::= W # far volatile member (16-bit) + // ::= X # far const volatile member (16-bit) + // ::= Y # huge member (16-bit) + // ::= Z # huge const member (16-bit) + // ::= 0 # huge volatile member (16-bit) + // ::= 1 # huge const volatile member (16-bit) + // ::= 2 <basis> # based member + // ::= 3 <basis> # based const member + // ::= 4 <basis> # based volatile member + // ::= 5 <basis> # based const volatile member + // ::= 6 # near function (pointers only) + // ::= 7 # far function (pointers only) + // ::= 8 # near method (pointers only) + // ::= 9 # far method (pointers only) + // ::= _A <basis> # based function (pointers only) + // ::= _B <basis> # based function (far?) (pointers only) + // ::= _C <basis> # based method (pointers only) + // ::= _D <basis> # based method (far?) (pointers only) + // ::= _E # block (Clang) + // <basis> ::= 0 # __based(void) + // ::= 1 # __based(segment)? + // ::= 2 <name> # __based(name) + // ::= 3 # ? + // ::= 4 # ? + // ::= 5 # not really based + bool HasConst = Quals.hasConst(), + HasVolatile = Quals.hasVolatile(); + if (!IsMember) { + if (HasConst && HasVolatile) { + Out << 'D'; + } else if (HasVolatile) { + Out << 'C'; + } else if (HasConst) { + Out << 'B'; + } else { + Out << 'A'; + } + } else { + if (HasConst && HasVolatile) { + Out << 'T'; + } else if (HasVolatile) { + Out << 'S'; + } else if (HasConst) { + Out << 'R'; + } else { + Out << 'Q'; + } + } + + // 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 + bool HasConst = Quals.hasConst(), + HasVolatile = Quals.hasVolatile(); + if (HasConst && HasVolatile) { + Out << 'S'; + } else if (HasVolatile) { + Out << 'R'; + } else if (HasConst) { + Out << 'Q'; + } else { + Out << 'P'; + } +} + +void MicrosoftCXXNameMangler::mangleArgumentType(QualType T, + SourceRange Range) { + void *TypePtr = getASTContext().getCanonicalType(T).getAsOpaquePtr(); + ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr); + + if (Found == TypeBackReferences.end()) { + size_t OutSizeBefore = Out.GetNumBytesInBuffer(); + + mangleType(T, Range, false); + + // See if it's worth creating a back reference. + // Only types longer than 1 character are considered + // and only 10 back references slots are available: + bool LongerThanOneChar = (Out.GetNumBytesInBuffer() - OutSizeBefore > 1); + if (LongerThanOneChar && TypeBackReferences.size() < 10) { + size_t Size = TypeBackReferences.size(); + TypeBackReferences[TypePtr] = Size; + } + } else { + Out << Found->second; + } +} + +void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range, + bool MangleQualifiers) { + // Only operate on the canonical type! + T = getASTContext().getCanonicalType(T); + + Qualifiers Quals = T.getLocalQualifiers(); + // We have to mangle these now, while we still have enough information. + if (T->isAnyPointerType() || T->isMemberPointerType() || + T->isBlockPointerType()) { + manglePointerQualifiers(Quals); + } else if (Quals && MangleQualifiers) { + mangleQualifiers(Quals, false); + } + + SplitQualType split = T.split(); + const Type *ty = split.Ty; + + // If we're mangling a qualified array type, push the qualifiers to + // the element type. + if (split.Quals && isa<ArrayType>(T)) { + ty = Context.getASTContext().getAsArrayType(T); + } + + switch (ty->getTypeClass()) { +#define ABSTRACT_TYPE(CLASS, PARENT) +#define NON_CANONICAL_TYPE(CLASS, PARENT) \ + case Type::CLASS: \ + llvm_unreachable("can't mangle non-canonical type " #CLASS "Type"); \ + return; +#define TYPE(CLASS, PARENT) \ + case Type::CLASS: \ + mangleType(cast<CLASS##Type>(ty), Range); \ + break; +#include "clang/AST/TypeNodes.def" +#undef ABSTRACT_TYPE +#undef NON_CANONICAL_TYPE +#undef TYPE + } +} + +void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, + SourceRange Range) { + // <type> ::= <builtin-type> + // <builtin-type> ::= X # void + // ::= C # signed char + // ::= D # char + // ::= E # unsigned char + // ::= F # short + // ::= G # unsigned short (or wchar_t if it's not a builtin) + // ::= H # int + // ::= I # unsigned int + // ::= J # long + // ::= K # unsigned long + // L # <none> + // ::= M # float + // ::= N # double + // ::= O # long double (__float80 is mangled differently) + // ::= _J # long long, __int64 + // ::= _K # unsigned long long, __int64 + // ::= _L # __int128 + // ::= _M # unsigned __int128 + // ::= _N # bool + // _O # <array in parameter> + // ::= _T # __float80 (Intel) + // ::= _W # wchar_t + // ::= _Z # __float80 (Digital Mars) + switch (T->getKind()) { + case BuiltinType::Void: Out << 'X'; break; + case BuiltinType::SChar: Out << 'C'; break; + case BuiltinType::Char_U: case BuiltinType::Char_S: Out << 'D'; break; + case BuiltinType::UChar: Out << 'E'; break; + case BuiltinType::Short: Out << 'F'; break; + case BuiltinType::UShort: Out << 'G'; break; + case BuiltinType::Int: Out << 'H'; break; + case BuiltinType::UInt: Out << 'I'; break; + case BuiltinType::Long: Out << 'J'; break; + case BuiltinType::ULong: Out << 'K'; break; + case BuiltinType::Float: Out << 'M'; break; + case BuiltinType::Double: Out << 'N'; break; + // TODO: Determine size and mangle accordingly + case BuiltinType::LongDouble: Out << 'O'; break; + case BuiltinType::LongLong: Out << "_J"; break; + case BuiltinType::ULongLong: Out << "_K"; break; + case BuiltinType::Int128: Out << "_L"; break; + case BuiltinType::UInt128: Out << "_M"; break; + case BuiltinType::Bool: Out << "_N"; break; + case BuiltinType::WChar_S: + case BuiltinType::WChar_U: Out << "_W"; break; + +#define BUILTIN_TYPE(Id, SingletonId) +#define PLACEHOLDER_TYPE(Id, SingletonId) \ + case BuiltinType::Id: +#include "clang/AST/BuiltinTypes.def" + case BuiltinType::Dependent: + llvm_unreachable("placeholder types shouldn't get to name mangling"); + + case BuiltinType::ObjCId: Out << "PAUobjc_object@@"; break; + case BuiltinType::ObjCClass: Out << "PAUobjc_class@@"; break; + case BuiltinType::ObjCSel: Out << "PAUobjc_selector@@"; break; + + case BuiltinType::NullPtr: Out << "$$T"; break; + + case BuiltinType::Char16: + case BuiltinType::Char32: + case BuiltinType::Half: { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this built-in %0 type yet"); + Diags.Report(Range.getBegin(), DiagID) + << T->getName(Context.getASTContext().getPrintingPolicy()) + << Range; + break; + } + } +} + +// <type> ::= <function-type> +void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T, + SourceRange) { + // Structors only appear in decls, so at this point we know it's not a + // structor type. + // FIXME: This may not be lambda-friendly. + Out << "$$A6"; + mangleType(T, NULL, false, false); +} +void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T, + SourceRange) { + llvm_unreachable("Can't mangle K&R function prototypes"); +} + +void MicrosoftCXXNameMangler::mangleType(const FunctionType *T, + const FunctionDecl *D, + bool IsStructor, + bool IsInstMethod) { + // <function-type> ::= <this-cvr-qualifiers> <calling-convention> + // <return-type> <argument-list> <throw-spec> + const FunctionProtoType *Proto = cast<FunctionProtoType>(T); + + // If this is a C++ instance method, mangle the CVR qualifiers for the + // this pointer. + if (IsInstMethod) + mangleQualifiers(Qualifiers::fromCVRMask(Proto->getTypeQuals()), false); + + mangleCallingConvention(T, IsInstMethod); + + // <return-type> ::= <type> + // ::= @ # structors (they have no declared return type) + if (IsStructor) + Out << '@'; + else { + QualType Result = Proto->getResultType(); + const Type* RT = Result.getTypePtr(); + if (!RT->isAnyPointerType() && !RT->isReferenceType()) { + if (Result.hasQualifiers() || !RT->isBuiltinType()) + Out << '?'; + if (!RT->isBuiltinType() && !Result.hasQualifiers()) { + // Lack of qualifiers for user types is mangled as 'A'. + Out << 'A'; + } + } + + // FIXME: Get the source range for the result type. Or, better yet, + // implement the unimplemented stuff so we don't need accurate source + // location info anymore :). + mangleType(Result, SourceRange()); + } + + // <argument-list> ::= X # void + // ::= <type>+ @ + // ::= <type>* Z # varargs + if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) { + Out << 'X'; + } else { + if (D) { + // If we got a decl, use the type-as-written to make sure arrays + // get mangled right. Note that we can't rely on the TSI + // existing if (for example) the parameter was synthesized. + for (FunctionDecl::param_const_iterator Parm = D->param_begin(), + ParmEnd = D->param_end(); Parm != ParmEnd; ++Parm) { + TypeSourceInfo *TSI = (*Parm)->getTypeSourceInfo(); + QualType Type = TSI ? TSI->getType() : (*Parm)->getType(); + mangleArgumentType(Type, (*Parm)->getSourceRange()); + } + } 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, SourceRange()); + } + // <builtin-type> ::= Z # ellipsis + if (Proto->isVariadic()) + Out << 'Z'; + else + Out << '@'; + } + + mangleThrowSpecification(Proto); +} + +void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) { + // <function-class> ::= A # private: near + // ::= B # private: far + // ::= C # private: static near + // ::= D # private: static far + // ::= E # private: virtual near + // ::= F # private: virtual far + // ::= G # private: thunk near + // ::= H # private: thunk far + // ::= I # protected: near + // ::= J # protected: far + // ::= K # protected: static near + // ::= L # protected: static far + // ::= M # protected: virtual near + // ::= N # protected: virtual far + // ::= O # protected: thunk near + // ::= P # protected: thunk far + // ::= Q # public: near + // ::= R # public: far + // ::= S # public: static near + // ::= T # public: static far + // ::= U # public: virtual near + // ::= V # public: virtual far + // ::= W # public: thunk near + // ::= X # public: thunk far + // ::= Y # global near + // ::= Z # global far + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { + switch (MD->getAccess()) { + default: + case AS_private: + if (MD->isStatic()) + Out << 'C'; + else if (MD->isVirtual()) + Out << 'E'; + else + Out << 'A'; + break; + case AS_protected: + if (MD->isStatic()) + Out << 'K'; + else if (MD->isVirtual()) + Out << 'M'; + else + Out << 'I'; + break; + case AS_public: + if (MD->isStatic()) + Out << 'S'; + else if (MD->isVirtual()) + Out << 'U'; + else + Out << 'Q'; + } + } else + Out << 'Y'; +} +void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T, + bool IsInstMethod) { + // <calling-convention> ::= A # __cdecl + // ::= B # __export __cdecl + // ::= C # __pascal + // ::= D # __export __pascal + // ::= E # __thiscall + // ::= F # __export __thiscall + // ::= G # __stdcall + // ::= H # __export __stdcall + // ::= I # __fastcall + // ::= J # __export __fastcall + // The 'export' calling conventions are from a bygone era + // (*cough*Win16*cough*) when functions were declared for export with + // that keyword. (It didn't actually export them, it just made them so + // that they could be in a DLL and somebody from another module could call + // them.) + CallingConv CC = T->getCallConv(); + if (CC == CC_Default) { + if (IsInstMethod) { + const FunctionProtoType *FPT = + T->getCanonicalTypeUnqualified().castAs<FunctionProtoType>(); + bool isVariadic = FPT->isVariadic(); + CC = getASTContext().getDefaultCXXMethodCallConv(isVariadic); + } else { + CC = CC_C; + } + } + switch (CC) { + default: + llvm_unreachable("Unsupported CC for mangling"); + case CC_Default: + case CC_C: Out << 'A'; break; + case CC_X86Pascal: Out << 'C'; break; + case CC_X86ThisCall: Out << 'E'; break; + case CC_X86StdCall: Out << 'G'; break; + case CC_X86FastCall: Out << 'I'; break; + } +} +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'; +} + +void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T, + SourceRange Range) { + // Probably should be mangled as a template instantiation; need to see what + // VC does first. + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this unresolved dependent type yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} + +// <type> ::= <union-type> | <struct-type> | <class-type> | <enum-type> +// <union-type> ::= T <name> +// <struct-type> ::= U <name> +// <class-type> ::= V <name> +// <enum-type> ::= W <size> <name> +void MicrosoftCXXNameMangler::mangleType(const EnumType *T, SourceRange) { + mangleType(cast<TagType>(T)); +} +void MicrosoftCXXNameMangler::mangleType(const RecordType *T, SourceRange) { + mangleType(cast<TagType>(T)); +} +void MicrosoftCXXNameMangler::mangleType(const TagType *T) { + switch (T->getDecl()->getTagKind()) { + case TTK_Union: + Out << 'T'; + break; + case TTK_Struct: + case TTK_Interface: + Out << 'U'; + break; + case TTK_Class: + Out << 'V'; + break; + case TTK_Enum: + Out << 'W'; + Out << getASTContext().getTypeSizeInChars( + cast<EnumDecl>(T->getDecl())->getIntegerType()).getQuantity(); + break; + } + mangleName(T->getDecl()); +} + +// <type> ::= <array-type> +// <array-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers> +// [Y <dimension-count> <dimension>+] +// <element-type> # as global +// ::= Q <cvr-qualifiers> [Y <dimension-count> <dimension>+] +// <element-type> # as param +// It's supposed to be the other way around, but for some strange reason, it +// isn't. Today this behavior is retained for the sole purpose of backwards +// compatibility. +void MicrosoftCXXNameMangler::mangleType(const ArrayType *T, bool IsGlobal) { + // This isn't a recursive mangling, so now we have to do it all in this + // one call. + if (IsGlobal) { + manglePointerQualifiers(T->getElementType().getQualifiers()); + } else { + Out << 'Q'; + } + mangleExtraDimensions(T->getElementType()); +} +void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T, + SourceRange) { + mangleType(cast<ArrayType>(T), false); +} +void MicrosoftCXXNameMangler::mangleType(const VariableArrayType *T, + SourceRange) { + mangleType(cast<ArrayType>(T), false); +} +void MicrosoftCXXNameMangler::mangleType(const DependentSizedArrayType *T, + SourceRange) { + mangleType(cast<ArrayType>(T), false); +} +void MicrosoftCXXNameMangler::mangleType(const IncompleteArrayType *T, + SourceRange) { + mangleType(cast<ArrayType>(T), false); +} +void MicrosoftCXXNameMangler::mangleExtraDimensions(QualType ElementTy) { + SmallVector<llvm::APInt, 3> Dimensions; + for (;;) { + if (const ConstantArrayType *CAT = + getASTContext().getAsConstantArrayType(ElementTy)) { + Dimensions.push_back(CAT->getSize()); + ElementTy = CAT->getElementType(); + } else if (ElementTy->isVariableArrayType()) { + const VariableArrayType *VAT = + getASTContext().getAsVariableArrayType(ElementTy); + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this variable-length array yet"); + Diags.Report(VAT->getSizeExpr()->getExprLoc(), DiagID) + << VAT->getBracketsRange(); + return; + } else if (ElementTy->isDependentSizedArrayType()) { + // The dependent expression has to be folded into a constant (TODO). + const DependentSizedArrayType *DSAT = + getASTContext().getAsDependentSizedArrayType(ElementTy); + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this dependent-length array yet"); + Diags.Report(DSAT->getSizeExpr()->getExprLoc(), DiagID) + << DSAT->getBracketsRange(); + return; + } else if (ElementTy->isIncompleteArrayType()) continue; + else break; + } + mangleQualifiers(ElementTy.getQualifiers(), false); + // If there are any additional dimensions, mangle them now. + if (Dimensions.size() > 0) { + Out << 'Y'; + // <dimension-count> ::= <number> # number of extra dimensions + mangleNumber(Dimensions.size()); + for (unsigned Dim = 0; Dim < Dimensions.size(); ++Dim) { + mangleNumber(Dimensions[Dim].getLimitedValue()); + } + } + mangleType(ElementTy.getLocalUnqualifiedType(), SourceRange()); +} + +// <type> ::= <pointer-to-member-type> +// <pointer-to-member-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers> +// <class name> <type> +void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T, + SourceRange Range) { + QualType PointeeType = T->getPointeeType(); + if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) { + Out << '8'; + mangleName(T->getClass()->castAs<RecordType>()->getDecl()); + mangleType(FPT, NULL, false, true); + } else { + mangleQualifiers(PointeeType.getQualifiers(), true); + mangleName(T->getClass()->castAs<RecordType>()->getDecl()); + mangleType(PointeeType.getLocalUnqualifiedType(), Range); + } +} + +void MicrosoftCXXNameMangler::mangleType(const TemplateTypeParmType *T, + SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this template type parameter type yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} + +void MicrosoftCXXNameMangler::mangleType( + const SubstTemplateTypeParmPackType *T, + SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this substituted parameter pack yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} + +// <type> ::= <pointer-type> +// <pointer-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers> <type> +void MicrosoftCXXNameMangler::mangleType(const PointerType *T, + SourceRange Range) { + QualType PointeeTy = T->getPointeeType(); + if (PointeeTy->isArrayType()) { + // Pointers to arrays are mangled like arrays. + mangleExtraDimensions(PointeeTy); + } else if (const FunctionType *FT = PointeeTy->getAs<FunctionType>()) { + // Function pointers are special. + Out << '6'; + mangleType(FT, NULL, false, false); + } else { + mangleQualifiers(PointeeTy.getQualifiers(), false); + mangleType(PointeeTy, Range, false); + } +} +void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T, + SourceRange Range) { + // Object pointers never have qualifiers. + Out << 'A'; + mangleType(T->getPointeeType(), Range); +} + +// <type> ::= <reference-type> +// <reference-type> ::= A <cvr-qualifiers> <type> +void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T, + SourceRange Range) { + Out << 'A'; + QualType PointeeTy = T->getPointeeType(); + if (!PointeeTy.hasQualifiers()) + // Lack of qualifiers is mangled as 'A'. + Out << 'A'; + mangleType(PointeeTy, Range); +} + +// <type> ::= <r-value-reference-type> +// <r-value-reference-type> ::= $$Q <cvr-qualifiers> <type> +void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T, + SourceRange Range) { + Out << "$$Q"; + QualType PointeeTy = T->getPointeeType(); + if (!PointeeTy.hasQualifiers()) + // Lack of qualifiers is mangled as 'A'. + Out << 'A'; + mangleType(PointeeTy, Range); +} + +void MicrosoftCXXNameMangler::mangleType(const ComplexType *T, + SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this complex number type yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} + +void MicrosoftCXXNameMangler::mangleType(const VectorType *T, + SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this vector type yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} +void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T, + SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this extended vector type yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} +void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T, + SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this dependent-sized extended vector type yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} + +void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, + SourceRange) { + // ObjC interfaces have structs underlying them. + Out << 'U'; + mangleName(T->getDecl()); +} + +void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, + SourceRange Range) { + // We don't allow overloading by different protocol qualification, + // so mangling them isn't necessary. + mangleType(T->getBaseType(), Range); +} + +void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T, + SourceRange Range) { + Out << "_E"; + + QualType pointee = T->getPointeeType(); + mangleType(pointee->castAs<FunctionProtoType>(), NULL, false, false); +} + +void MicrosoftCXXNameMangler::mangleType(const InjectedClassNameType *T, + SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this injected class name type yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} + +void MicrosoftCXXNameMangler::mangleType(const TemplateSpecializationType *T, + SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this template specialization type yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} + +void MicrosoftCXXNameMangler::mangleType(const DependentNameType *T, + SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this dependent name type yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} + +void MicrosoftCXXNameMangler::mangleType( + const DependentTemplateSpecializationType *T, + SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this dependent template specialization type yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} + +void MicrosoftCXXNameMangler::mangleType(const PackExpansionType *T, + SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this pack expansion yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} + +void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T, + SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this typeof(type) yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} + +void MicrosoftCXXNameMangler::mangleType(const TypeOfExprType *T, + SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this typeof(expression) yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} + +void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T, + SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this decltype() yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} + +void MicrosoftCXXNameMangler::mangleType(const UnaryTransformType *T, + SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this unary transform type yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} + +void MicrosoftCXXNameMangler::mangleType(const AutoType *T, SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this 'auto' type yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} + +void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, + SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this C11 atomic type yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} + +void MicrosoftMangleContext::mangleName(const NamedDecl *D, + raw_ostream &Out) { + assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) && + "Invalid mangleName() call, argument is not a variable or function!"); + assert(!isa<CXXConstructorDecl>(D) && !isa<CXXDestructorDecl>(D) && + "Invalid mangleName() call on 'structor decl!"); + + PrettyStackTraceDecl CrashInfo(D, SourceLocation(), + getASTContext().getSourceManager(), + "Mangling declaration"); + + MicrosoftCXXNameMangler Mangler(*this, Out); + return Mangler.mangle(D); +} +void MicrosoftMangleContext::mangleThunk(const CXXMethodDecl *MD, + const ThunkInfo &Thunk, + raw_ostream &) { + unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle thunk for this method yet"); + getDiags().Report(MD->getLocation(), DiagID); +} +void MicrosoftMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD, + CXXDtorType Type, + const ThisAdjustment &, + raw_ostream &) { + unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle thunk for this destructor yet"); + getDiags().Report(DD->getLocation(), DiagID); +} +void MicrosoftMangleContext::mangleCXXVTable(const CXXRecordDecl *RD, + raw_ostream &Out) { + // <mangled-name> ::= ? <operator-name> <class-name> <storage-class> + // <cvr-qualifiers> [<name>] @ + // <operator-name> ::= _7 # vftable + // ::= _8 # vbtable + // NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class> + // is always '6' for vftables and '7' for vbtables. (The difference is + // beyond me.) + // TODO: vbtables. + MicrosoftCXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "\01??_7"; + Mangler.mangleName(RD); + Mangler.getStream() << "6B"; + // TODO: If the class has more than one vtable, mangle in the class it came + // from. + Mangler.getStream() << '@'; +} +void MicrosoftMangleContext::mangleCXXVTT(const CXXRecordDecl *RD, + raw_ostream &) { + llvm_unreachable("The MS C++ ABI does not have virtual table tables!"); +} +void MicrosoftMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD, + int64_t Offset, + const CXXRecordDecl *Type, + raw_ostream &) { + llvm_unreachable("The MS C++ ABI does not have constructor vtables!"); +} +void MicrosoftMangleContext::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 MicrosoftMangleContext::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 MicrosoftMangleContext::mangleCXXCtor(const CXXConstructorDecl *D, + CXXCtorType Type, + raw_ostream & Out) { + MicrosoftCXXNameMangler mangler(*this, Out); + mangler.mangle(D); +} +void MicrosoftMangleContext::mangleCXXDtor(const CXXDestructorDecl *D, + CXXDtorType Type, + raw_ostream & Out) { + MicrosoftCXXNameMangler mangler(*this, Out); + mangler.mangle(D); +} +void MicrosoftMangleContext::mangleReferenceTemporary(const clang::VarDecl *VD, + raw_ostream &) { + unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this reference temporary yet"); + getDiags().Report(VD->getLocation(), DiagID); +} + +MangleContext *clang::createMicrosoftMangleContext(ASTContext &Context, + DiagnosticsEngine &Diags) { + return new MicrosoftMangleContext(Context, Diags); +} |