summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/Mangle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/Mangle.cpp')
-rw-r--r--lib/CodeGen/Mangle.cpp772
1 files changed, 772 insertions, 0 deletions
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
new file mode 100644
index 0000000..6ee1223
--- /dev/null
+++ b/lib/CodeGen/Mangle.cpp
@@ -0,0 +1,772 @@
+//===--- Mangle.cpp - Mangle C++ Names --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements C++ name mangling according to the Itanium C++ ABI,
+// which is used in GCC 3.2 and newer (and many compilers that are
+// ABI-compatible with GCC):
+//
+// http://www.codesourcery.com/public/cxx-abi/abi.html
+//
+//===----------------------------------------------------------------------===//
+#include "Mangle.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+namespace {
+ class VISIBILITY_HIDDEN CXXNameMangler {
+ ASTContext &Context;
+ llvm::raw_ostream &Out;
+
+ const CXXMethodDecl *Structor;
+ unsigned StructorType;
+ CXXCtorType CtorType;
+
+ public:
+ CXXNameMangler(ASTContext &C, llvm::raw_ostream &os)
+ : Context(C), Out(os), Structor(0), StructorType(0) { }
+
+ bool mangle(const NamedDecl *D);
+ void mangleGuardVariable(const VarDecl *D);
+
+ void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type);
+ void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type);
+
+ private:
+ bool mangleFunctionDecl(const FunctionDecl *FD);
+
+ void mangleFunctionEncoding(const FunctionDecl *FD);
+ void mangleName(const NamedDecl *ND);
+ void mangleUnqualifiedName(const NamedDecl *ND);
+ void mangleSourceName(const IdentifierInfo *II);
+ void mangleLocalName(const NamedDecl *ND);
+ void mangleNestedName(const NamedDecl *ND);
+ void manglePrefix(const DeclContext *DC);
+ void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
+ void mangleCVQualifiers(unsigned Quals);
+ void mangleType(QualType T);
+ void mangleType(const BuiltinType *T);
+ void mangleType(const FunctionType *T);
+ void mangleBareFunctionType(const FunctionType *T, bool MangleReturnType);
+ void mangleType(const TagType *T);
+ void mangleType(const ArrayType *T);
+ void mangleType(const MemberPointerType *T);
+ void mangleType(const TemplateTypeParmType *T);
+ void mangleType(const ObjCInterfaceType *T);
+ void mangleExpression(Expr *E);
+ void mangleCXXCtorType(CXXCtorType T);
+ void mangleCXXDtorType(CXXDtorType T);
+
+ void mangleTemplateArgumentList(const TemplateArgumentList &L);
+ void mangleTemplateArgument(const TemplateArgument &A);
+ };
+}
+
+static bool isInCLinkageSpecification(const Decl *D) {
+ 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 CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) {
+ // Clang's "overloadable" attribute extension to C/C++ implies
+ // name mangling (always).
+ if (FD->hasAttr<OverloadableAttr>()) {
+ ; // fall into mangling code unconditionally.
+ } else if (// C functions are not mangled
+ !Context.getLangOptions().CPlusPlus ||
+ // "main" is not mangled in C++
+ FD->isMain() ||
+ // No mangling in an "implicit extern C" header.
+ (FD->getLocation().isValid() &&
+ Context.getSourceManager().getFileCharacteristic(FD->getLocation()))
+ == SrcMgr::C_ExternCSystem ||
+ // No name mangling in a C linkage specification.
+ isInCLinkageSpecification(FD))
+ return false;
+
+ // If we get here, mangle the decl name!
+ Out << "_Z";
+ mangleFunctionEncoding(FD);
+ return true;
+}
+
+bool CXXNameMangler::mangle(const NamedDecl *D) {
+ // 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'; // LLVM IR Marker for __asm("foo")
+ Out << ALA->getLabel();
+ return true;
+ }
+
+ // <mangled-name> ::= _Z <encoding>
+ // ::= <data name>
+ // ::= <special-name>
+
+ // FIXME: Actually use a visitor to decode these?
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ return mangleFunctionDecl(FD);
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (!Context.getLangOptions().CPlusPlus ||
+ isInCLinkageSpecification(D) ||
+ D->getDeclContext()->isTranslationUnit())
+ return false;
+
+ Out << "_Z";
+ mangleName(VD);
+ return true;
+ }
+
+ return false;
+}
+
+void CXXNameMangler::mangleCXXCtor(const CXXConstructorDecl *D,
+ CXXCtorType Type) {
+ assert(!Structor && "Structor already set!");
+ Structor = D;
+ StructorType = Type;
+
+ mangle(D);
+}
+
+void CXXNameMangler::mangleCXXDtor(const CXXDestructorDecl *D,
+ CXXDtorType Type) {
+ assert(!Structor && "Structor already set!");
+ Structor = D;
+ StructorType = Type;
+
+ mangle(D);
+}
+
+void CXXNameMangler::mangleGuardVariable(const VarDecl *D)
+{
+ // <special-name> ::= GV <object name> # Guard variable for one-time
+ // # initialization
+
+ Out << "_ZGV";
+ mangleName(D);
+}
+
+void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
+ // <encoding> ::= <function name> <bare-function-type>
+ mangleName(FD);
+ mangleBareFunctionType(FD->getType()->getAsFunctionType(), false);
+}
+
+static bool isStdNamespace(const DeclContext *DC) {
+ if (!DC->isNamespace() || !DC->getParent()->isTranslationUnit())
+ return false;
+
+ const NamespaceDecl *NS = cast<NamespaceDecl>(DC);
+ return NS->getOriginalNamespace()->getIdentifier()->isStr("std");
+}
+
+void CXXNameMangler::mangleName(const NamedDecl *ND) {
+ // <name> ::= <nested-name>
+ // ::= <unscoped-name>
+ // ::= <unscoped-template-name> <template-args>
+ // ::= <local-name> # See Scope Encoding below
+ //
+ // <unscoped-name> ::= <unqualified-name>
+ // ::= St <unqualified-name> # ::std::
+ if (ND->getDeclContext()->isTranslationUnit())
+ mangleUnqualifiedName(ND);
+ else if (isStdNamespace(ND->getDeclContext())) {
+ Out << "St";
+ mangleUnqualifiedName(ND);
+ } else if (isa<FunctionDecl>(ND->getDeclContext()))
+ mangleLocalName(ND);
+ else
+ mangleNestedName(ND);
+}
+
+void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
+ // <unqualified-name> ::= <operator-name>
+ // ::= <ctor-dtor-name>
+ // ::= <source-name>
+ DeclarationName Name = ND->getDeclName();
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ mangleSourceName(Name.getAsIdentifierInfo());
+ break;
+
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ assert(false && "Can't mangle Objective-C selector names here!");
+ break;
+
+ case DeclarationName::CXXConstructorName:
+ if (ND == Structor)
+ // If the named decl is the C++ constructor we're mangling, use the
+ // type we were given.
+ mangleCXXCtorType(static_cast<CXXCtorType>(StructorType));
+ else
+ // Otherwise, use the complete constructor name. This is relevant if a
+ // class with a constructor is declared within a constructor.
+ mangleCXXCtorType(Ctor_Complete);
+ break;
+
+ case DeclarationName::CXXDestructorName:
+ if (ND == Structor)
+ // If the named decl is the C++ destructor we're mangling, use the
+ // type we were given.
+ mangleCXXDtorType(static_cast<CXXDtorType>(StructorType));
+ else
+ // Otherwise, use the complete destructor name. This is relevant if a
+ // class with a destructor is declared within a destructor.
+ mangleCXXDtorType(Dtor_Complete);
+ break;
+
+ case DeclarationName::CXXConversionFunctionName:
+ // <operator-name> ::= cv <type> # (cast)
+ Out << "cv";
+ mangleType(Context.getCanonicalType(Name.getCXXNameType()));
+ break;
+
+ case DeclarationName::CXXOperatorName:
+ mangleOperatorName(Name.getCXXOverloadedOperator(),
+ cast<FunctionDecl>(ND)->getNumParams());
+ break;
+
+ case DeclarationName::CXXUsingDirective:
+ assert(false && "Can't mangle a using directive name!");
+ break;
+ }
+}
+
+void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) {
+ // <source-name> ::= <positive length number> <identifier>
+ // <number> ::= [n] <non-negative decimal integer>
+ // <identifier> ::= <unqualified source code identifier>
+ Out << II->getLength() << II->getName();
+}
+
+void CXXNameMangler::mangleNestedName(const NamedDecl *ND) {
+ // <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
+ // ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
+ // FIXME: no template support
+ Out << 'N';
+ if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND))
+ mangleCVQualifiers(Method->getTypeQualifiers());
+ manglePrefix(ND->getDeclContext());
+ mangleUnqualifiedName(ND);
+ Out << 'E';
+}
+
+void CXXNameMangler::mangleLocalName(const NamedDecl *ND) {
+ // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
+ // := Z <function encoding> E s [<discriminator>]
+ // <discriminator> := _ <non-negative number>
+ Out << 'Z';
+ mangleFunctionEncoding(cast<FunctionDecl>(ND->getDeclContext()));
+ Out << 'E';
+ mangleSourceName(ND->getIdentifier());
+}
+
+void CXXNameMangler::manglePrefix(const DeclContext *DC) {
+ // <prefix> ::= <prefix> <unqualified-name>
+ // ::= <template-prefix> <template-args>
+ // ::= <template-param>
+ // ::= # empty
+ // ::= <substitution>
+ // FIXME: We only handle mangling of namespaces and classes at the moment.
+ if (!DC->getParent()->isTranslationUnit())
+ manglePrefix(DC->getParent());
+
+ if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(DC))
+ mangleSourceName(Namespace->getIdentifier());
+ else if (const RecordDecl *Record = dyn_cast<RecordDecl>(DC)) {
+ if (const ClassTemplateSpecializationDecl *D =
+ dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
+ mangleType(QualType(D->getTypeForDecl(), 0));
+ } else
+ mangleSourceName(Record->getIdentifier());
+ }
+}
+
+void
+CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
+ switch (OO) {
+ // <operator-name> ::= nw # new
+ case OO_New: Out << "nw"; break;
+ // ::= na # new[]
+ case OO_Array_New: Out << "na"; break;
+ // ::= dl # delete
+ case OO_Delete: Out << "dl"; break;
+ // ::= da # delete[]
+ case OO_Array_Delete: Out << "da"; break;
+ // ::= ps # + (unary)
+ // ::= pl # +
+ case OO_Plus: Out << (Arity == 1? "ps" : "pl"); break;
+ // ::= ng # - (unary)
+ // ::= mi # -
+ case OO_Minus: Out << (Arity == 1? "ng" : "mi"); break;
+ // ::= ad # & (unary)
+ // ::= an # &
+ case OO_Amp: Out << (Arity == 1? "ad" : "an"); break;
+ // ::= de # * (unary)
+ // ::= ml # *
+ case OO_Star: Out << (Arity == 1? "de" : "ml"); break;
+ // ::= co # ~
+ case OO_Tilde: Out << "co"; break;
+ // ::= dv # /
+ case OO_Slash: Out << "dv"; break;
+ // ::= rm # %
+ case OO_Percent: Out << "rm"; break;
+ // ::= or # |
+ case OO_Pipe: Out << "or"; break;
+ // ::= eo # ^
+ case OO_Caret: Out << "eo"; break;
+ // ::= aS # =
+ case OO_Equal: Out << "aS"; break;
+ // ::= pL # +=
+ case OO_PlusEqual: Out << "pL"; break;
+ // ::= mI # -=
+ case OO_MinusEqual: Out << "mI"; break;
+ // ::= mL # *=
+ case OO_StarEqual: Out << "mL"; break;
+ // ::= dV # /=
+ case OO_SlashEqual: Out << "dV"; break;
+ // ::= rM # %=
+ case OO_PercentEqual: Out << "rM"; break;
+ // ::= aN # &=
+ case OO_AmpEqual: Out << "aN"; break;
+ // ::= oR # |=
+ case OO_PipeEqual: Out << "oR"; break;
+ // ::= eO # ^=
+ case OO_CaretEqual: Out << "eO"; break;
+ // ::= ls # <<
+ case OO_LessLess: Out << "ls"; break;
+ // ::= rs # >>
+ case OO_GreaterGreater: Out << "rs"; break;
+ // ::= lS # <<=
+ case OO_LessLessEqual: Out << "lS"; break;
+ // ::= rS # >>=
+ case OO_GreaterGreaterEqual: Out << "rS"; break;
+ // ::= eq # ==
+ case OO_EqualEqual: Out << "eq"; break;
+ // ::= ne # !=
+ case OO_ExclaimEqual: Out << "ne"; break;
+ // ::= lt # <
+ case OO_Less: Out << "lt"; break;
+ // ::= gt # >
+ case OO_Greater: Out << "gt"; break;
+ // ::= le # <=
+ case OO_LessEqual: Out << "le"; break;
+ // ::= ge # >=
+ case OO_GreaterEqual: Out << "ge"; break;
+ // ::= nt # !
+ case OO_Exclaim: Out << "nt"; break;
+ // ::= aa # &&
+ case OO_AmpAmp: Out << "aa"; break;
+ // ::= oo # ||
+ case OO_PipePipe: Out << "oo"; break;
+ // ::= pp # ++
+ case OO_PlusPlus: Out << "pp"; break;
+ // ::= mm # --
+ case OO_MinusMinus: Out << "mm"; break;
+ // ::= cm # ,
+ case OO_Comma: Out << "cm"; break;
+ // ::= pm # ->*
+ case OO_ArrowStar: Out << "pm"; break;
+ // ::= pt # ->
+ case OO_Arrow: Out << "pt"; break;
+ // ::= cl # ()
+ case OO_Call: Out << "cl"; break;
+ // ::= ix # []
+ case OO_Subscript: Out << "ix"; break;
+ // UNSUPPORTED: ::= qu # ?
+
+ case OO_None:
+ case OO_Conditional:
+ case NUM_OVERLOADED_OPERATORS:
+ assert(false && "Not an overloaded operator");
+ break;
+ }
+}
+
+void CXXNameMangler::mangleCVQualifiers(unsigned Quals) {
+ // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
+ if (Quals & QualType::Restrict)
+ Out << 'r';
+ if (Quals & QualType::Volatile)
+ Out << 'V';
+ if (Quals & QualType::Const)
+ Out << 'K';
+}
+
+void CXXNameMangler::mangleType(QualType T) {
+ // Only operate on the canonical type!
+ T = Context.getCanonicalType(T);
+
+ // FIXME: Should we have a TypeNodes.def to make this easier? (YES!)
+
+ // <type> ::= <CV-qualifiers> <type>
+ mangleCVQualifiers(T.getCVRQualifiers());
+
+ // ::= <builtin-type>
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr()))
+ mangleType(BT);
+ // ::= <function-type>
+ else if (const FunctionType *FT = dyn_cast<FunctionType>(T.getTypePtr()))
+ mangleType(FT);
+ // ::= <class-enum-type>
+ else if (const TagType *TT = dyn_cast<TagType>(T.getTypePtr()))
+ mangleType(TT);
+ // ::= <array-type>
+ else if (const ArrayType *AT = dyn_cast<ArrayType>(T.getTypePtr()))
+ mangleType(AT);
+ // ::= <pointer-to-member-type>
+ else if (const MemberPointerType *MPT
+ = dyn_cast<MemberPointerType>(T.getTypePtr()))
+ mangleType(MPT);
+ // ::= <template-param>
+ else if (const TemplateTypeParmType *TypeParm
+ = dyn_cast<TemplateTypeParmType>(T.getTypePtr()))
+ mangleType(TypeParm);
+ // FIXME: ::= <template-template-param> <template-args>
+ // FIXME: ::= <substitution> # See Compression below
+ // ::= P <type> # pointer-to
+ else if (const PointerType *PT = dyn_cast<PointerType>(T.getTypePtr())) {
+ Out << 'P';
+ mangleType(PT->getPointeeType());
+ }
+ // ::= R <type> # reference-to
+ else if (const LValueReferenceType *RT =
+ dyn_cast<LValueReferenceType>(T.getTypePtr())) {
+ Out << 'R';
+ mangleType(RT->getPointeeType());
+ }
+ // ::= O <type> # rvalue reference-to (C++0x)
+ else if (const RValueReferenceType *RT =
+ dyn_cast<RValueReferenceType>(T.getTypePtr())) {
+ Out << 'O';
+ mangleType(RT->getPointeeType());
+ }
+ // ::= C <type> # complex pair (C 2000)
+ else if (const ComplexType *CT = dyn_cast<ComplexType>(T.getTypePtr())) {
+ Out << 'C';
+ mangleType(CT->getElementType());
+ } else if (const VectorType *VT = dyn_cast<VectorType>(T.getTypePtr())) {
+ // GNU extension: vector types
+ Out << "U8__vector";
+ mangleType(VT->getElementType());
+ } else if (const ObjCInterfaceType *IT =
+ dyn_cast<ObjCInterfaceType>(T.getTypePtr())) {
+ mangleType(IT);
+ }
+ // FIXME: ::= G <type> # imaginary (C 2000)
+ // FIXME: ::= U <source-name> <type> # vendor extended type qualifier
+ else
+ assert(false && "Cannot mangle unknown type");
+}
+
+void CXXNameMangler::mangleType(const BuiltinType *T) {
+ // <builtin-type> ::= v # void
+ // ::= w # wchar_t
+ // ::= b # bool
+ // ::= c # char
+ // ::= a # signed char
+ // ::= h # unsigned char
+ // ::= s # short
+ // ::= t # unsigned short
+ // ::= i # int
+ // ::= j # unsigned int
+ // ::= l # long
+ // ::= m # unsigned long
+ // ::= x # long long, __int64
+ // ::= y # unsigned long long, __int64
+ // ::= n # __int128
+ // UNSUPPORTED: ::= o # unsigned __int128
+ // ::= f # float
+ // ::= d # double
+ // ::= e # long double, __float80
+ // UNSUPPORTED: ::= g # __float128
+ // UNSUPPORTED: ::= Dd # IEEE 754r decimal floating point (64 bits)
+ // UNSUPPORTED: ::= De # IEEE 754r decimal floating point (128 bits)
+ // UNSUPPORTED: ::= Df # IEEE 754r decimal floating point (32 bits)
+ // UNSUPPORTED: ::= Dh # IEEE 754r half-precision floating point (16 bits)
+ // UNSUPPORTED: ::= Di # char32_t
+ // UNSUPPORTED: ::= Ds # char16_t
+ // ::= u <source-name> # vendor extended type
+ // From our point of view, std::nullptr_t is a builtin, but as far as mangling
+ // is concerned, it's a type called std::nullptr_t.
+ switch (T->getKind()) {
+ case BuiltinType::Void: Out << 'v'; break;
+ case BuiltinType::Bool: Out << 'b'; break;
+ case BuiltinType::Char_U: case BuiltinType::Char_S: Out << 'c'; break;
+ case BuiltinType::UChar: Out << 'h'; break;
+ case BuiltinType::UShort: Out << 't'; break;
+ case BuiltinType::UInt: Out << 'j'; break;
+ case BuiltinType::ULong: Out << 'm'; break;
+ case BuiltinType::ULongLong: Out << 'y'; break;
+ case BuiltinType::UInt128: Out << 'o'; break;
+ case BuiltinType::SChar: Out << 'a'; break;
+ case BuiltinType::WChar: Out << 'w'; break;
+ case BuiltinType::Short: Out << 's'; break;
+ case BuiltinType::Int: Out << 'i'; break;
+ case BuiltinType::Long: Out << 'l'; break;
+ case BuiltinType::LongLong: Out << 'x'; break;
+ case BuiltinType::Int128: Out << 'n'; break;
+ case BuiltinType::Float: Out << 'f'; break;
+ case BuiltinType::Double: Out << 'd'; break;
+ case BuiltinType::LongDouble: Out << 'e'; break;
+ case BuiltinType::NullPtr: Out << "St9nullptr_t"; break;
+
+ case BuiltinType::Overload:
+ case BuiltinType::Dependent:
+ assert(false &&
+ "Overloaded and dependent types shouldn't get to name mangling");
+ break;
+ }
+}
+
+void CXXNameMangler::mangleType(const FunctionType *T) {
+ // <function-type> ::= F [Y] <bare-function-type> E
+ Out << 'F';
+ // FIXME: We don't have enough information in the AST to produce the 'Y'
+ // encoding for extern "C" function types.
+ mangleBareFunctionType(T, /*MangleReturnType=*/true);
+ Out << 'E';
+}
+
+void CXXNameMangler::mangleBareFunctionType(const FunctionType *T,
+ bool MangleReturnType) {
+ // <bare-function-type> ::= <signature type>+
+ if (MangleReturnType)
+ mangleType(T->getResultType());
+
+ const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(T);
+ assert(Proto && "Can't mangle K&R function prototypes");
+
+ if (Proto->getNumArgs() == 0) {
+ Out << 'v';
+ return;
+ }
+
+ for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
+ ArgEnd = Proto->arg_type_end();
+ Arg != ArgEnd; ++Arg)
+ mangleType(*Arg);
+
+ // <builtin-type> ::= z # ellipsis
+ if (Proto->isVariadic())
+ Out << 'z';
+}
+
+void CXXNameMangler::mangleType(const TagType *T) {
+ // <class-enum-type> ::= <name>
+
+ if (!T->getDecl()->getIdentifier())
+ mangleName(T->getDecl()->getTypedefForAnonDecl());
+ else
+ mangleName(T->getDecl());
+
+ // If this is a class template specialization, mangle the template
+ // arguments.
+ if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl()))
+ mangleTemplateArgumentList(Spec->getTemplateArgs());
+}
+
+void CXXNameMangler::mangleType(const ArrayType *T) {
+ // <array-type> ::= A <positive dimension number> _ <element type>
+ // ::= A [<dimension expression>] _ <element type>
+ Out << 'A';
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T))
+ Out << CAT->getSize();
+ else if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(T))
+ mangleExpression(VAT->getSizeExpr());
+ else if (const DependentSizedArrayType *DSAT
+ = dyn_cast<DependentSizedArrayType>(T))
+ mangleExpression(DSAT->getSizeExpr());
+
+ Out << '_';
+ mangleType(T->getElementType());
+}
+
+void CXXNameMangler::mangleType(const MemberPointerType *T) {
+ // <pointer-to-member-type> ::= M <class type> <member type>
+ Out << 'M';
+ mangleType(QualType(T->getClass(), 0));
+ QualType PointeeType = T->getPointeeType();
+ if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(PointeeType)) {
+ mangleCVQualifiers(FPT->getTypeQuals());
+ mangleType(FPT);
+ } else
+ mangleType(PointeeType);
+}
+
+void CXXNameMangler::mangleType(const TemplateTypeParmType *T) {
+ // <template-param> ::= T_ # first template parameter
+ // ::= T <parameter-2 non-negative number> _
+ if (T->getIndex() == 0)
+ Out << "T_";
+ else
+ Out << 'T' << (T->getIndex() - 1) << '_';
+}
+
+void CXXNameMangler::mangleType(const ObjCInterfaceType *T) {
+ mangleSourceName(T->getDecl()->getIdentifier());
+}
+
+void CXXNameMangler::mangleExpression(Expr *E) {
+ assert(false && "Cannot mangle expressions yet");
+}
+
+void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) {
+ // <ctor-dtor-name> ::= C1 # complete object constructor
+ // ::= C2 # base object constructor
+ // ::= C3 # complete object allocating constructor
+ //
+ switch (T) {
+ case Ctor_Complete:
+ Out << "C1";
+ break;
+ case Ctor_Base:
+ Out << "C2";
+ break;
+ case Ctor_CompleteAllocating:
+ Out << "C3";
+ break;
+ }
+}
+
+void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
+ // <ctor-dtor-name> ::= D0 # deleting destructor
+ // ::= D1 # complete object destructor
+ // ::= D2 # base object destructor
+ //
+ switch (T) {
+ case Dtor_Deleting:
+ Out << "D0";
+ break;
+ case Dtor_Complete:
+ Out << "D1";
+ break;
+ case Dtor_Base:
+ Out << "D2";
+ break;
+ }
+}
+
+void CXXNameMangler::mangleTemplateArgumentList(const TemplateArgumentList &L) {
+ // <template-args> ::= I <template-arg>+ E
+ Out << "I";
+
+ for (unsigned i = 0, e = L.size(); i != e; ++i) {
+ const TemplateArgument &A = L[i];
+
+ mangleTemplateArgument(A);
+ }
+
+ Out << "E";
+}
+
+void CXXNameMangler::mangleTemplateArgument(const TemplateArgument &A) {
+ // <template-arg> ::= <type> # type or template
+ // ::= X <expression> E # expression
+ // ::= <expr-primary> # simple expressions
+ // ::= I <template-arg>* E # argument pack
+ // ::= sp <expression> # pack expansion of (C++0x)
+ switch (A.getKind()) {
+ default:
+ assert(0 && "Unknown template argument kind!");
+ case TemplateArgument::Type:
+ mangleType(A.getAsType());
+ break;
+ case TemplateArgument::Integral:
+ // <expr-primary> ::= L <type> <value number> E # integer literal
+
+ Out << 'L';
+
+ mangleType(A.getIntegralType());
+
+ const llvm::APSInt *Integral = A.getAsIntegral();
+ if (A.getIntegralType()->isBooleanType()) {
+ // Boolean values are encoded as 0/1.
+ Out << (Integral->getBoolValue() ? '1' : '0');
+ } else {
+ if (Integral->isNegative())
+ Out << 'n';
+ Integral->abs().print(Out, false);
+ }
+
+ Out << 'E';
+ break;
+ }
+}
+
+namespace clang {
+ /// \brief Mangles the name of the declaration D and emits that name
+ /// to the given output stream.
+ ///
+ /// If the declaration D requires a mangled name, this routine will
+ /// emit that mangled name to \p os and return true. Otherwise, \p
+ /// os will be unchanged and this routine will return false. In this
+ /// case, the caller should just emit the identifier of the declaration
+ /// (\c D->getIdentifier()) as its name.
+ bool mangleName(const NamedDecl *D, ASTContext &Context,
+ llvm::raw_ostream &os) {
+ assert(!isa<CXXConstructorDecl>(D) &&
+ "Use mangleCXXCtor for constructor decls!");
+ assert(!isa<CXXDestructorDecl>(D) &&
+ "Use mangleCXXDtor for destructor decls!");
+
+ CXXNameMangler Mangler(Context, os);
+ if (!Mangler.mangle(D))
+ return false;
+
+ os.flush();
+ return true;
+ }
+
+ /// mangleGuardVariable - Returns the mangled name for a guard variable
+ /// for the passed in VarDecl.
+ void mangleGuardVariable(const VarDecl *D, ASTContext &Context,
+ llvm::raw_ostream &os) {
+ CXXNameMangler Mangler(Context, os);
+ Mangler.mangleGuardVariable(D);
+
+ os.flush();
+ }
+
+ void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
+ ASTContext &Context, llvm::raw_ostream &os) {
+ CXXNameMangler Mangler(Context, os);
+ Mangler.mangleCXXCtor(D, Type);
+
+ os.flush();
+ }
+
+ void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
+ ASTContext &Context, llvm::raw_ostream &os) {
+ CXXNameMangler Mangler(Context, os);
+ Mangler.mangleCXXDtor(D, Type);
+
+ os.flush();
+ }
+
+
+}
+
OpenPOWER on IntegriCloud