2009-02-19 07:53:56 +08:00
|
|
|
//===--- Mangle.cpp - Mangle C++ Names --------------------------*- C++ -*-===//
|
2009-02-13 08:10:09 +08:00
|
|
|
//
|
|
|
|
// 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"
|
2009-03-08 06:03:21 +08:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
2009-05-16 00:09:15 +08:00
|
|
|
#include "clang/AST/DeclTemplate.h"
|
2009-09-28 04:11:34 +08:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
2009-02-19 07:53:56 +08:00
|
|
|
#include "clang/Basic/SourceManager.h"
|
2009-10-07 09:45:02 +08:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2009-02-13 08:10:09 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2009-09-05 15:56:18 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2009-11-26 10:49:32 +08:00
|
|
|
#include "CGVtable.h"
|
2009-02-13 08:10:09 +08:00
|
|
|
using namespace clang;
|
2009-11-26 10:49:32 +08:00
|
|
|
using namespace CodeGen;
|
2009-02-13 08:10:09 +08:00
|
|
|
|
|
|
|
namespace {
|
2009-11-24 13:36:32 +08:00
|
|
|
|
|
|
|
static const CXXMethodDecl *getStructor(const CXXMethodDecl *MD) {
|
|
|
|
assert((isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) &&
|
|
|
|
"Passed in decl is not a ctor or dtor!");
|
|
|
|
|
|
|
|
if (const TemplateDecl *TD = MD->getPrimaryTemplate()) {
|
|
|
|
MD = cast<CXXMethodDecl>(TD->getTemplatedDecl());
|
|
|
|
|
|
|
|
assert((isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) &&
|
|
|
|
"Templated decl is not a ctor or dtor!");
|
|
|
|
}
|
|
|
|
|
|
|
|
return MD;
|
|
|
|
}
|
|
|
|
|
2009-11-21 17:06:10 +08:00
|
|
|
/// CXXNameMangler - Manage the mangling of a single name.
|
2009-11-21 17:12:13 +08:00
|
|
|
class CXXNameMangler {
|
2009-11-21 17:06:10 +08:00
|
|
|
MangleContext &Context;
|
2009-11-21 17:06:22 +08:00
|
|
|
llvm::raw_svector_ostream Out;
|
2009-02-13 08:10:09 +08:00
|
|
|
|
2009-11-21 17:06:10 +08:00
|
|
|
const CXXMethodDecl *Structor;
|
|
|
|
unsigned StructorType;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-21 17:06:10 +08:00
|
|
|
llvm::DenseMap<uintptr_t, unsigned> Substitutions;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-11-21 17:12:13 +08:00
|
|
|
public:
|
2009-11-21 17:06:22 +08:00
|
|
|
CXXNameMangler(MangleContext &C, llvm::SmallVectorImpl<char> &Res)
|
|
|
|
: Context(C), Out(Res), Structor(0), StructorType(0) { }
|
2009-11-21 17:06:31 +08:00
|
|
|
CXXNameMangler(MangleContext &C, llvm::SmallVectorImpl<char> &Res,
|
|
|
|
const CXXConstructorDecl *D, CXXCtorType Type)
|
2009-11-24 13:36:32 +08:00
|
|
|
: Context(C), Out(Res), Structor(getStructor(D)), StructorType(Type) { }
|
2009-11-21 17:06:31 +08:00
|
|
|
CXXNameMangler(MangleContext &C, llvm::SmallVectorImpl<char> &Res,
|
|
|
|
const CXXDestructorDecl *D, CXXDtorType Type)
|
2009-11-24 13:36:32 +08:00
|
|
|
: Context(C), Out(Res), Structor(getStructor(D)), StructorType(Type) { }
|
2009-04-15 13:36:58 +08:00
|
|
|
|
2009-11-21 17:12:13 +08:00
|
|
|
llvm::raw_svector_ostream &getStream() { return Out; }
|
|
|
|
|
2009-11-21 17:17:15 +08:00
|
|
|
void mangle(const NamedDecl *D, llvm::StringRef Prefix = "_Z");
|
2009-11-26 10:49:32 +08:00
|
|
|
void mangleCallOffset(const ThunkAdjustment &Adjustment);
|
2009-11-26 10:32:05 +08:00
|
|
|
void mangleNumber(int64_t Number);
|
2009-11-21 17:12:13 +08:00
|
|
|
void mangleFunctionEncoding(const FunctionDecl *FD);
|
|
|
|
void mangleName(const NamedDecl *ND);
|
|
|
|
void mangleType(QualType T);
|
|
|
|
|
|
|
|
private:
|
2009-11-21 17:06:10 +08:00
|
|
|
bool mangleSubstitution(const NamedDecl *ND);
|
|
|
|
bool mangleSubstitution(QualType T);
|
|
|
|
bool mangleSubstitution(uintptr_t Ptr);
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-11-21 17:06:10 +08:00
|
|
|
bool mangleStandardSubstitution(const NamedDecl *ND);
|
2009-11-07 12:26:04 +08:00
|
|
|
|
2009-11-21 17:06:10 +08:00
|
|
|
void addSubstitution(const NamedDecl *ND) {
|
|
|
|
ND = cast<NamedDecl>(ND->getCanonicalDecl());
|
2009-09-05 15:56:18 +08:00
|
|
|
|
2009-11-21 17:06:10 +08:00
|
|
|
addSubstitution(reinterpret_cast<uintptr_t>(ND));
|
|
|
|
}
|
|
|
|
void addSubstitution(QualType T);
|
|
|
|
void addSubstitution(uintptr_t Ptr);
|
|
|
|
|
|
|
|
void mangleName(const TemplateDecl *TD,
|
|
|
|
const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs);
|
|
|
|
void mangleUnqualifiedName(const NamedDecl *ND);
|
|
|
|
void mangleUnscopedName(const NamedDecl *ND);
|
|
|
|
void mangleUnscopedTemplateName(const TemplateDecl *ND);
|
|
|
|
void mangleSourceName(const IdentifierInfo *II);
|
|
|
|
void mangleLocalName(const NamedDecl *ND);
|
2009-12-03 04:32:49 +08:00
|
|
|
void mangleNestedName(const NamedDecl *ND, const DeclContext *DC);
|
2009-11-21 17:06:10 +08:00
|
|
|
void mangleNestedName(const TemplateDecl *TD,
|
|
|
|
const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs);
|
|
|
|
void manglePrefix(const DeclContext *DC);
|
|
|
|
void mangleTemplatePrefix(const TemplateDecl *ND);
|
|
|
|
void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
|
|
|
|
void mangleQualifiers(Qualifiers Quals);
|
|
|
|
|
2009-12-10 11:14:39 +08:00
|
|
|
void mangleObjCMethodName(const ObjCMethodDecl *MD);
|
|
|
|
|
2009-11-21 17:06:10 +08:00
|
|
|
// Declare manglers for every type class.
|
2009-09-05 15:56:18 +08:00
|
|
|
#define ABSTRACT_TYPE(CLASS, PARENT)
|
|
|
|
#define NON_CANONICAL_TYPE(CLASS, PARENT)
|
|
|
|
#define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T);
|
|
|
|
#include "clang/AST/TypeNodes.def"
|
|
|
|
|
2009-11-21 17:06:10 +08:00
|
|
|
void mangleType(const TagType*);
|
|
|
|
void mangleBareFunctionType(const FunctionType *T,
|
|
|
|
bool MangleReturnType);
|
2009-12-14 09:45:37 +08:00
|
|
|
|
|
|
|
void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value);
|
2009-11-21 17:06:10 +08:00
|
|
|
void mangleExpression(const Expr *E);
|
|
|
|
void mangleCXXCtorType(CXXCtorType T);
|
|
|
|
void mangleCXXDtorType(CXXDtorType T);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-21 17:06:10 +08:00
|
|
|
void mangleTemplateArgs(const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs);
|
2009-12-24 03:30:55 +08:00
|
|
|
void mangleTemplateArgs(const TemplateArgumentList &L);
|
|
|
|
void mangleTemplateArg(const TemplateArgument &A);
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-11-21 17:06:10 +08:00
|
|
|
void mangleTemplateParameter(unsigned Index);
|
|
|
|
};
|
2009-02-13 08:10:09 +08:00
|
|
|
}
|
|
|
|
|
2009-04-02 23:51:53 +08:00
|
|
|
static bool isInCLinkageSpecification(const Decl *D) {
|
2009-10-29 00:31:34 +08:00
|
|
|
D = D->getCanonicalDecl();
|
2009-09-09 23:08:12 +08:00
|
|
|
for (const DeclContext *DC = D->getDeclContext();
|
2009-04-02 23:51:53 +08:00
|
|
|
!DC->isTranslationUnit(); DC = DC->getParent()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))
|
2009-04-02 23:51:53 +08:00
|
|
|
return Linkage->getLanguage() == LinkageSpecDecl::lang_c;
|
2009-03-21 16:24:40 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-04-02 23:51:53 +08:00
|
|
|
return false;
|
|
|
|
}
|
2009-02-13 08:10:09 +08:00
|
|
|
|
2009-11-21 17:14:52 +08:00
|
|
|
bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
|
|
|
|
// In C, functions with no attributes never need to be mangled. Fastpath them.
|
|
|
|
if (!getASTContext().getLangOptions().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;
|
|
|
|
|
2009-09-02 08:25:38 +08:00
|
|
|
// Clang's "overloadable" attribute extension to C/C++ implies name mangling
|
2009-11-07 15:15:03 +08:00
|
|
|
// (always) as does passing a C++ member function and a function
|
|
|
|
// whose name is not a simple identifier.
|
2009-11-21 17:14:52 +08:00
|
|
|
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
|
|
|
|
if (FD && (FD->hasAttr<OverloadableAttr>() || isa<CXXMethodDecl>(FD) ||
|
|
|
|
!FD->getDeclName().isIdentifier()))
|
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-21 17:14:52 +08:00
|
|
|
// Otherwise, no mangling is done outside C++ mode.
|
|
|
|
if (!getASTContext().getLangOptions().CPlusPlus)
|
|
|
|
return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-21 17:14:52 +08:00
|
|
|
// No mangling in an "implicit extern C" header.
|
|
|
|
if (D->getLocation().isValid() &&
|
|
|
|
getASTContext().getSourceManager().
|
|
|
|
isInExternCSystemHeader(D->getLocation()))
|
|
|
|
return false;
|
|
|
|
|
2009-12-03 04:32:49 +08:00
|
|
|
// Variables at global scope are not mangled.
|
|
|
|
if (!FD) {
|
|
|
|
const DeclContext *DC = D->getDeclContext();
|
|
|
|
// Check for extern variable declared locally.
|
|
|
|
if (isa<FunctionDecl>(DC) && D->hasLinkage())
|
|
|
|
while (!DC->isNamespace() && !DC->isTranslationUnit())
|
|
|
|
DC = DC->getParent();
|
|
|
|
if (DC->isTranslationUnit())
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// C functions and "main" are not mangled.
|
|
|
|
if ((FD && FD->isMain()) || isInCLinkageSpecification(D))
|
2009-11-21 17:14:52 +08:00
|
|
|
return false;
|
2009-02-13 08:10:09 +08:00
|
|
|
|
2009-03-21 14:19:20 +08:00
|
|
|
return true;
|
2009-02-13 08:10:09 +08:00
|
|
|
}
|
|
|
|
|
2009-11-21 17:17:15 +08:00
|
|
|
void CXXNameMangler::mangle(const NamedDecl *D, llvm::StringRef Prefix) {
|
2009-09-02 08:25:38 +08:00
|
|
|
// Any decl can be declared with __asm("foo") on it, and this takes precedence
|
|
|
|
// over all other naming in the .o file.
|
2009-06-30 10:34:44 +08:00
|
|
|
if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
|
2009-04-02 23:51:53 +08:00
|
|
|
// If we have an asm name, then we use it as the mangling.
|
|
|
|
Out << '\01'; // LLVM IR Marker for __asm("foo")
|
|
|
|
Out << ALA->getLabel();
|
2009-11-21 17:14:52 +08:00
|
|
|
return;
|
2009-04-02 23:51:53 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-04-02 23:51:53 +08:00
|
|
|
// <mangled-name> ::= _Z <encoding>
|
|
|
|
// ::= <data name>
|
|
|
|
// ::= <special-name>
|
2009-11-21 17:17:15 +08:00
|
|
|
Out << Prefix;
|
|
|
|
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
|
2009-11-21 17:14:52 +08:00
|
|
|
mangleFunctionEncoding(FD);
|
2009-11-21 17:17:15 +08:00
|
|
|
else
|
|
|
|
mangleName(cast<VarDecl>(D));
|
2009-04-02 23:51:53 +08:00
|
|
|
}
|
|
|
|
|
2009-02-13 08:10:09 +08:00
|
|
|
void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
|
|
|
|
// <encoding> ::= <function name> <bare-function-type>
|
|
|
|
mangleName(FD);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-21 17:17:15 +08:00
|
|
|
// Don't mangle in the type if this isn't a decl we should typically mangle.
|
|
|
|
if (!Context.shouldMangleDeclName(FD))
|
|
|
|
return;
|
|
|
|
|
2009-09-02 08:25:38 +08:00
|
|
|
// Whether the mangling of a function type includes the return type depends on
|
|
|
|
// the context and the nature of the function. The rules for deciding whether
|
|
|
|
// the return type is included are:
|
2009-09-09 23:08:12 +08:00
|
|
|
//
|
2009-06-30 06:39:32 +08:00
|
|
|
// 1. Template functions (names or types) have return types encoded, with
|
|
|
|
// the exceptions listed below.
|
2009-09-09 23:08:12 +08:00
|
|
|
// 2. Function types not appearing as part of a function name mangling,
|
2009-06-30 06:39:32 +08:00
|
|
|
// e.g. parameters, pointer types, etc., have return type encoded, with the
|
|
|
|
// exceptions listed below.
|
|
|
|
// 3. Non-template function names do not have return types encoded.
|
|
|
|
//
|
2009-09-02 08:25:38 +08:00
|
|
|
// The exceptions mentioned in (1) and (2) above, for which the return type is
|
|
|
|
// never included, are
|
2009-06-30 06:39:32 +08:00
|
|
|
// 1. Constructors.
|
|
|
|
// 2. Destructors.
|
|
|
|
// 3. Conversion operator functions, e.g. operator int.
|
|
|
|
bool MangleReturnType = false;
|
2009-09-17 11:46:43 +08:00
|
|
|
if (FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate()) {
|
|
|
|
if (!(isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD) ||
|
|
|
|
isa<CXXConversionDecl>(FD)))
|
|
|
|
MangleReturnType = true;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-17 11:46:43 +08:00
|
|
|
// Mangle the type of the primary template.
|
|
|
|
FD = PrimaryTemplate->getTemplatedDecl();
|
|
|
|
}
|
|
|
|
|
2009-10-23 06:37:11 +08:00
|
|
|
// Do the canonicalization out here because parameter types can
|
|
|
|
// undergo additional canonicalization (e.g. array decay).
|
|
|
|
FunctionType *FT = cast<FunctionType>(Context.getASTContext()
|
|
|
|
.getCanonicalType(FD->getType()));
|
|
|
|
|
|
|
|
mangleBareFunctionType(FT, MangleReturnType);
|
2009-02-13 08:10:09 +08:00
|
|
|
}
|
|
|
|
|
2009-12-04 14:23:23 +08:00
|
|
|
/// isStd - Return whether a given namespace is the 'std' namespace.
|
|
|
|
static bool isStd(const NamespaceDecl *NS) {
|
2009-10-01 08:25:31 +08:00
|
|
|
const IdentifierInfo *II = NS->getOriginalNamespace()->getIdentifier();
|
|
|
|
return II && II->isStr("std");
|
2009-02-13 08:10:09 +08:00
|
|
|
}
|
|
|
|
|
2009-12-04 14:23:23 +08:00
|
|
|
static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) {
|
|
|
|
while (isa<LinkageSpecDecl>(DC)) {
|
|
|
|
assert(cast<LinkageSpecDecl>(DC)->getLanguage() ==
|
|
|
|
LinkageSpecDecl::lang_cxx && "Unexpected linkage decl!");
|
|
|
|
DC = DC->getParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
return DC;
|
|
|
|
}
|
|
|
|
|
|
|
|
// isStdNamespace - Return whether a given decl context is a toplevel 'std'
|
|
|
|
// namespace.
|
2009-11-21 17:11:45 +08:00
|
|
|
static bool isStdNamespace(const DeclContext *DC) {
|
2009-12-04 14:23:23 +08:00
|
|
|
if (!DC->isNamespace())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!IgnoreLinkageSpecDecls(DC->getParent())->isTranslationUnit())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return isStd(cast<NamespaceDecl>(DC));
|
2009-11-21 17:11:45 +08:00
|
|
|
}
|
|
|
|
|
2009-09-26 11:24:57 +08:00
|
|
|
static const TemplateDecl *
|
|
|
|
isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) {
|
2009-09-19 03:00:18 +08:00
|
|
|
// Check if we have a function template.
|
|
|
|
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){
|
2009-09-26 11:24:57 +08:00
|
|
|
if (const TemplateDecl *TD = FD->getPrimaryTemplate()) {
|
2009-09-19 03:00:18 +08:00
|
|
|
TemplateArgs = FD->getTemplateSpecializationArgs();
|
2009-09-26 11:24:57 +08:00
|
|
|
return TD;
|
2009-09-19 03:00:18 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-19 03:44:50 +08:00
|
|
|
// Check if we have a class template.
|
|
|
|
if (const ClassTemplateSpecializationDecl *Spec =
|
|
|
|
dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
|
|
|
|
TemplateArgs = &Spec->getTemplateArgs();
|
2009-09-26 11:24:57 +08:00
|
|
|
return Spec->getSpecializedTemplate();
|
2009-09-19 03:44:50 +08:00
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-19 03:00:18 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-02-13 08:10:09 +08:00
|
|
|
void CXXNameMangler::mangleName(const NamedDecl *ND) {
|
|
|
|
// <name> ::= <nested-name>
|
|
|
|
// ::= <unscoped-name>
|
|
|
|
// ::= <unscoped-template-name> <template-args>
|
2009-09-17 11:17:01 +08:00
|
|
|
// ::= <local-name>
|
2009-02-13 08:10:09 +08:00
|
|
|
//
|
2009-09-18 00:12:20 +08:00
|
|
|
const DeclContext *DC = ND->getDeclContext();
|
2009-12-03 04:32:49 +08:00
|
|
|
|
|
|
|
// 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();
|
|
|
|
|
2009-09-23 01:23:30 +08:00
|
|
|
while (isa<LinkageSpecDecl>(DC))
|
2009-09-18 00:12:20 +08:00
|
|
|
DC = DC->getParent();
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-18 00:12:20 +08:00
|
|
|
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
|
2009-09-19 03:00:18 +08:00
|
|
|
// Check if we have a template.
|
|
|
|
const TemplateArgumentList *TemplateArgs = 0;
|
2009-09-27 03:45:45 +08:00
|
|
|
if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
|
2009-09-19 03:00:18 +08:00
|
|
|
mangleUnscopedTemplateName(TD);
|
2009-12-24 03:30:55 +08:00
|
|
|
mangleTemplateArgs(*TemplateArgs);
|
2009-09-19 03:00:18 +08:00
|
|
|
return;
|
2009-09-18 12:29:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
mangleUnscopedName(ND);
|
|
|
|
return;
|
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-12-10 11:14:39 +08:00
|
|
|
if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)) {
|
2009-04-03 00:24:45 +08:00
|
|
|
mangleLocalName(ND);
|
2009-09-18 12:29:09 +08:00
|
|
|
return;
|
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-12-03 04:32:49 +08:00
|
|
|
mangleNestedName(ND, DC);
|
2009-02-13 08:10:09 +08:00
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
void CXXNameMangler::mangleName(const TemplateDecl *TD,
|
2009-09-18 10:42:01 +08:00
|
|
|
const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs) {
|
2009-12-04 14:23:23 +08:00
|
|
|
const DeclContext *DC = IgnoreLinkageSpecDecls(TD->getDeclContext());
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-18 10:42:01 +08:00
|
|
|
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
|
2009-09-27 03:45:45 +08:00
|
|
|
mangleUnscopedTemplateName(TD);
|
2009-09-18 10:42:01 +08:00
|
|
|
mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
|
|
|
|
} else {
|
|
|
|
mangleNestedName(TD, TemplateArgs, NumTemplateArgs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-17 11:17:01 +08:00
|
|
|
void CXXNameMangler::mangleUnscopedName(const NamedDecl *ND) {
|
|
|
|
// <unscoped-name> ::= <unqualified-name>
|
|
|
|
// ::= St <unqualified-name> # ::std::
|
|
|
|
if (isStdNamespace(ND->getDeclContext()))
|
|
|
|
Out << "St";
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-17 11:17:01 +08:00
|
|
|
mangleUnqualifiedName(ND);
|
|
|
|
}
|
|
|
|
|
2009-09-27 03:45:45 +08:00
|
|
|
void CXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *ND) {
|
2009-09-17 11:17:01 +08:00
|
|
|
// <unscoped-template-name> ::= <unscoped-name>
|
|
|
|
// ::= <substitution>
|
2009-09-18 10:42:01 +08:00
|
|
|
if (mangleSubstitution(ND))
|
2009-09-17 12:02:31 +08:00
|
|
|
return;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-27 04:13:56 +08:00
|
|
|
mangleUnscopedName(ND->getTemplatedDecl());
|
2009-09-18 10:42:01 +08:00
|
|
|
addSubstitution(ND);
|
2009-09-17 11:17:01 +08:00
|
|
|
}
|
|
|
|
|
2009-11-26 10:32:05 +08:00
|
|
|
void CXXNameMangler::mangleNumber(int64_t Number) {
|
|
|
|
// <number> ::= [n] <non-negative decimal integer>
|
|
|
|
if (Number < 0) {
|
|
|
|
Out << 'n';
|
|
|
|
Number = -Number;
|
|
|
|
}
|
|
|
|
|
|
|
|
Out << Number;
|
|
|
|
}
|
|
|
|
|
2009-11-26 10:49:32 +08:00
|
|
|
void CXXNameMangler::mangleCallOffset(const ThunkAdjustment &Adjustment) {
|
2009-09-02 08:25:38 +08:00
|
|
|
// <call-offset> ::= h <nv-offset> _
|
|
|
|
// ::= v <v-offset> _
|
|
|
|
// <nv-offset> ::= <offset number> # non-virtual base override
|
2009-11-26 10:32:05 +08:00
|
|
|
// <v-offset> ::= <offset number> _ <virtual offset number>
|
2009-09-02 08:25:38 +08:00
|
|
|
// # virtual base override, with vcall offset
|
2009-11-26 10:49:32 +08:00
|
|
|
if (!Adjustment.Virtual) {
|
2009-11-26 10:32:05 +08:00
|
|
|
Out << 'h';
|
2009-11-26 10:49:32 +08:00
|
|
|
mangleNumber(Adjustment.NonVirtual);
|
2009-11-26 10:32:05 +08:00
|
|
|
Out << '_';
|
|
|
|
return;
|
2009-09-02 08:25:38 +08:00
|
|
|
}
|
2009-11-26 10:32:05 +08:00
|
|
|
|
|
|
|
Out << 'v';
|
2009-11-26 10:49:32 +08:00
|
|
|
mangleNumber(Adjustment.NonVirtual);
|
2009-11-26 10:32:05 +08:00
|
|
|
Out << '_';
|
2009-11-26 10:49:32 +08:00
|
|
|
mangleNumber(Adjustment.Virtual);
|
2009-11-26 10:32:05 +08:00
|
|
|
Out << '_';
|
2009-09-02 08:56:18 +08:00
|
|
|
}
|
|
|
|
|
2009-02-13 08:10:09 +08:00
|
|
|
void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
|
|
|
|
// <unqualified-name> ::= <operator-name>
|
2009-09-09 23:08:12 +08:00
|
|
|
// ::= <ctor-dtor-name>
|
|
|
|
// ::= <source-name>
|
2009-02-13 08:10:09 +08:00
|
|
|
DeclarationName Name = ND->getDeclName();
|
|
|
|
switch (Name.getNameKind()) {
|
2009-10-07 09:45:02 +08:00
|
|
|
case DeclarationName::Identifier: {
|
|
|
|
if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
|
2009-10-01 08:25:31 +08:00
|
|
|
if (NS->isAnonymousNamespace()) {
|
|
|
|
// This is how gcc mangles these names. It's apparently
|
|
|
|
// always '1', no matter how many different anonymous
|
|
|
|
// namespaces appear in a context.
|
|
|
|
Out << "12_GLOBAL__N_1";
|
|
|
|
break;
|
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
}
|
2009-10-07 09:45:02 +08:00
|
|
|
|
|
|
|
if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
|
|
|
|
mangleSourceName(II);
|
|
|
|
break;
|
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-10-07 09:45:02 +08:00
|
|
|
// We must have an anonymous struct.
|
|
|
|
const TagDecl *TD = cast<TagDecl>(ND);
|
|
|
|
if (const TypedefDecl *D = TD->getTypedefForAnonDecl()) {
|
|
|
|
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;
|
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-10-07 09:45:02 +08:00
|
|
|
// Get a unique id for the anonymous struct.
|
|
|
|
uint64_t AnonStructId = Context.getAnonymousStructId(TD);
|
|
|
|
|
|
|
|
// Mangle it as a source name in the form
|
2009-11-21 17:05:47 +08:00
|
|
|
// [n] $_<id>
|
2009-10-07 09:45:02 +08:00
|
|
|
// where n is the length of the string.
|
|
|
|
llvm::SmallString<8> Str;
|
|
|
|
Str += "$_";
|
|
|
|
Str += llvm::utostr(AnonStructId);
|
|
|
|
|
|
|
|
Out << Str.size();
|
|
|
|
Out << Str.str();
|
2009-02-13 08:10:09 +08:00
|
|
|
break;
|
2009-10-07 09:45:02 +08:00
|
|
|
}
|
2009-02-13 08:10:09 +08:00
|
|
|
|
|
|
|
case DeclarationName::ObjCZeroArgSelector:
|
|
|
|
case DeclarationName::ObjCOneArgSelector:
|
|
|
|
case DeclarationName::ObjCMultiArgSelector:
|
|
|
|
assert(false && "Can't mangle Objective-C selector names here!");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DeclarationName::CXXConstructorName:
|
2009-04-17 09:58:57 +08:00
|
|
|
if (ND == Structor)
|
2009-09-02 08:25:38 +08:00
|
|
|
// If the named decl is the C++ constructor we're mangling, use the type
|
|
|
|
// we were given.
|
2009-04-17 09:58:57 +08:00
|
|
|
mangleCXXCtorType(static_cast<CXXCtorType>(StructorType));
|
2009-04-15 13:36:58 +08:00
|
|
|
else
|
|
|
|
// Otherwise, use the complete constructor name. This is relevant if a
|
|
|
|
// class with a constructor is declared within a constructor.
|
|
|
|
mangleCXXCtorType(Ctor_Complete);
|
2009-02-13 08:10:09 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DeclarationName::CXXDestructorName:
|
2009-04-17 09:58:57 +08:00
|
|
|
if (ND == Structor)
|
2009-09-02 08:25:38 +08:00
|
|
|
// If the named decl is the C++ destructor we're mangling, use the type we
|
|
|
|
// were given.
|
2009-04-17 09:58:57 +08:00
|
|
|
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);
|
2009-02-13 08:10:09 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DeclarationName::CXXConversionFunctionName:
|
2009-09-09 23:08:12 +08:00
|
|
|
// <operator-name> ::= cv <type> # (cast)
|
2009-02-13 09:28:03 +08:00
|
|
|
Out << "cv";
|
2009-10-07 09:06:45 +08:00
|
|
|
mangleType(Context.getASTContext().getCanonicalType(Name.getCXXNameType()));
|
2009-02-13 08:10:09 +08:00
|
|
|
break;
|
|
|
|
|
2009-12-22 14:36:32 +08:00
|
|
|
case DeclarationName::CXXOperatorName: {
|
|
|
|
unsigned Arity = cast<FunctionDecl>(ND)->getNumParams();
|
|
|
|
|
|
|
|
// If we have a C++ member function, we need to include the 'this' pointer.
|
|
|
|
// FIXME: This does not make sense for operators that are static, but their
|
|
|
|
// names stay the same regardless of the arity (operator new for instance).
|
|
|
|
if (isa<CXXMethodDecl>(ND))
|
|
|
|
Arity++;
|
|
|
|
mangleOperatorName(Name.getCXXOverloadedOperator(), Arity);
|
2009-02-13 08:10:09 +08:00
|
|
|
break;
|
2009-12-22 14:36:32 +08:00
|
|
|
}
|
2009-02-13 08:10:09 +08:00
|
|
|
|
2009-11-29 15:34:05 +08:00
|
|
|
case DeclarationName::CXXLiteralOperatorName:
|
2009-12-05 05:11:13 +08:00
|
|
|
// FIXME: This mangling is not yet official.
|
2009-12-05 05:01:37 +08:00
|
|
|
Out << "li";
|
2009-11-29 15:34:05 +08:00
|
|
|
mangleSourceName(Name.getCXXLiteralIdentifier());
|
|
|
|
break;
|
|
|
|
|
2009-02-13 08:10:09 +08:00
|
|
|
case DeclarationName::CXXUsingDirective:
|
|
|
|
assert(false && "Can't mangle a using directive name!");
|
2009-02-13 09:28:03 +08:00
|
|
|
break;
|
2009-02-13 08:10:09 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2009-12-03 04:32:49 +08:00
|
|
|
void CXXNameMangler::mangleNestedName(const NamedDecl *ND,
|
|
|
|
const DeclContext *DC) {
|
2009-02-13 08:10:09 +08:00
|
|
|
// <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
|
|
|
|
// ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
|
2009-09-26 11:55:37 +08:00
|
|
|
|
2009-02-13 08:10:09 +08:00
|
|
|
Out << 'N';
|
|
|
|
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND))
|
2009-09-25 03:53:00 +08:00
|
|
|
mangleQualifiers(Qualifiers::fromCVRMask(Method->getTypeQualifiers()));
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-19 03:00:18 +08:00
|
|
|
// Check if we have a template.
|
|
|
|
const TemplateArgumentList *TemplateArgs = 0;
|
2009-11-21 17:05:47 +08:00
|
|
|
if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
|
2009-09-19 03:00:18 +08:00
|
|
|
mangleTemplatePrefix(TD);
|
2009-12-24 03:30:55 +08:00
|
|
|
mangleTemplateArgs(*TemplateArgs);
|
2009-09-18 12:29:09 +08:00
|
|
|
} else {
|
2009-12-03 04:32:49 +08:00
|
|
|
manglePrefix(DC);
|
2009-09-18 12:29:09 +08:00
|
|
|
mangleUnqualifiedName(ND);
|
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-02-13 08:10:09 +08:00
|
|
|
Out << 'E';
|
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
void CXXNameMangler::mangleNestedName(const TemplateDecl *TD,
|
2009-09-18 10:42:01 +08:00
|
|
|
const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs) {
|
2009-09-28 03:53:49 +08:00
|
|
|
// <nested-name> ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
|
|
|
|
|
2009-09-18 10:42:01 +08:00
|
|
|
Out << 'N';
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-28 03:53:49 +08:00
|
|
|
mangleTemplatePrefix(TD);
|
2009-09-18 10:42:01 +08:00
|
|
|
mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-18 10:42:01 +08:00
|
|
|
Out << 'E';
|
|
|
|
}
|
|
|
|
|
2009-04-03 00:24:45 +08:00
|
|
|
void CXXNameMangler::mangleLocalName(const NamedDecl *ND) {
|
|
|
|
// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
|
|
|
|
// := Z <function encoding> E s [<discriminator>]
|
2009-09-09 23:08:12 +08:00
|
|
|
// <discriminator> := _ <non-negative number>
|
2009-04-03 00:24:45 +08:00
|
|
|
Out << 'Z';
|
2009-12-10 11:14:39 +08:00
|
|
|
|
|
|
|
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ND->getDeclContext()))
|
|
|
|
mangleObjCMethodName(MD);
|
|
|
|
else
|
|
|
|
mangleFunctionEncoding(cast<FunctionDecl>(ND->getDeclContext()));
|
|
|
|
|
2009-04-03 00:24:45 +08:00
|
|
|
Out << 'E';
|
2009-12-12 04:21:38 +08:00
|
|
|
mangleUnqualifiedName(ND);
|
2009-04-03 00:24:45 +08:00
|
|
|
}
|
|
|
|
|
2009-02-13 08:10:09 +08:00
|
|
|
void CXXNameMangler::manglePrefix(const DeclContext *DC) {
|
|
|
|
// <prefix> ::= <prefix> <unqualified-name>
|
|
|
|
// ::= <template-prefix> <template-args>
|
|
|
|
// ::= <template-param>
|
|
|
|
// ::= # empty
|
|
|
|
// ::= <substitution>
|
2009-09-17 12:16:28 +08:00
|
|
|
|
2009-09-23 04:33:31 +08:00
|
|
|
while (isa<LinkageSpecDecl>(DC))
|
|
|
|
DC = DC->getParent();
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-19 02:39:58 +08:00
|
|
|
if (DC->isTranslationUnit())
|
|
|
|
return;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-17 12:16:28 +08:00
|
|
|
if (mangleSubstitution(cast<NamedDecl>(DC)))
|
|
|
|
return;
|
2009-09-18 12:29:09 +08:00
|
|
|
|
2009-09-19 04:11:09 +08:00
|
|
|
// Check if we have a template.
|
|
|
|
const TemplateArgumentList *TemplateArgs = 0;
|
2009-11-21 17:05:47 +08:00
|
|
|
if (const TemplateDecl *TD = isTemplate(cast<NamedDecl>(DC), TemplateArgs)) {
|
2009-09-19 04:11:09 +08:00
|
|
|
mangleTemplatePrefix(TD);
|
2009-12-24 03:30:55 +08:00
|
|
|
mangleTemplateArgs(*TemplateArgs);
|
2009-09-19 04:11:09 +08:00
|
|
|
} else {
|
|
|
|
manglePrefix(DC->getParent());
|
|
|
|
mangleUnqualifiedName(cast<NamedDecl>(DC));
|
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-17 12:16:28 +08:00
|
|
|
addSubstitution(cast<NamedDecl>(DC));
|
2009-02-13 08:10:09 +08:00
|
|
|
}
|
|
|
|
|
2009-09-27 03:45:45 +08:00
|
|
|
void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND) {
|
2009-09-18 12:29:09 +08:00
|
|
|
// <template-prefix> ::= <prefix> <template unqualified-name>
|
|
|
|
// ::= <template-param>
|
|
|
|
// ::= <substitution>
|
|
|
|
|
2009-09-27 06:18:22 +08:00
|
|
|
if (mangleSubstitution(ND))
|
|
|
|
return;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-27 06:18:22 +08:00
|
|
|
// FIXME: <template-param>
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-19 02:47:07 +08:00
|
|
|
manglePrefix(ND->getDeclContext());
|
2009-09-27 04:13:56 +08:00
|
|
|
mangleUnqualifiedName(ND->getTemplatedDecl());
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-27 06:18:22 +08:00
|
|
|
addSubstitution(ND);
|
2009-09-18 12:29:09 +08:00
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
void
|
2009-02-13 08:10:09 +08:00
|
|
|
CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
|
|
|
|
switch (OO) {
|
2009-04-17 01:51:27 +08:00
|
|
|
// <operator-name> ::= nw # new
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_New: Out << "nw"; break;
|
|
|
|
// ::= na # new[]
|
|
|
|
case OO_Array_New: Out << "na"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= dl # delete
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_Delete: Out << "dl"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= da # delete[]
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_Array_Delete: Out << "da"; break;
|
|
|
|
// ::= ps # + (unary)
|
|
|
|
// ::= pl # +
|
2009-12-22 14:36:32 +08:00
|
|
|
case OO_Plus:
|
|
|
|
assert((Arity == 1 || Arity == 2) && "Invalid arity!");
|
|
|
|
Out << (Arity == 1? "ps" : "pl"); break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= ng # - (unary)
|
|
|
|
// ::= mi # -
|
2009-12-22 14:36:32 +08:00
|
|
|
case OO_Minus:
|
|
|
|
assert((Arity == 1 || Arity == 2) && "Invalid arity!");
|
|
|
|
Out << (Arity == 1? "ng" : "mi"); break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= ad # & (unary)
|
|
|
|
// ::= an # &
|
2009-12-22 14:36:32 +08:00
|
|
|
case OO_Amp:
|
|
|
|
assert((Arity == 1 || Arity == 2) && "Invalid arity!");
|
|
|
|
Out << (Arity == 1? "ad" : "an"); break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= de # * (unary)
|
|
|
|
// ::= ml # *
|
2009-12-22 14:36:32 +08:00
|
|
|
case OO_Star:
|
|
|
|
assert((Arity == 1 || Arity == 2) && "Invalid arity!");
|
|
|
|
Out << (Arity == 1? "de" : "ml"); break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= co # ~
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_Tilde: Out << "co"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= dv # /
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_Slash: Out << "dv"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= rm # %
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_Percent: Out << "rm"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= or # |
|
|
|
|
case OO_Pipe: Out << "or"; break;
|
|
|
|
// ::= eo # ^
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_Caret: Out << "eo"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= aS # =
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_Equal: Out << "aS"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= pL # +=
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_PlusEqual: Out << "pL"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= mI # -=
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_MinusEqual: Out << "mI"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= mL # *=
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_StarEqual: Out << "mL"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= dV # /=
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_SlashEqual: Out << "dV"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= 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 # <<
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_LessLess: Out << "ls"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= rs # >>
|
|
|
|
case OO_GreaterGreater: Out << "rs"; break;
|
|
|
|
// ::= lS # <<=
|
|
|
|
case OO_LessLessEqual: Out << "lS"; break;
|
|
|
|
// ::= rS # >>=
|
|
|
|
case OO_GreaterGreaterEqual: Out << "rS"; break;
|
2009-02-13 08:10:09 +08:00
|
|
|
// ::= eq # ==
|
|
|
|
case OO_EqualEqual: Out << "eq"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= ne # !=
|
|
|
|
case OO_ExclaimEqual: Out << "ne"; break;
|
|
|
|
// ::= lt # <
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_Less: Out << "lt"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= gt # >
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_Greater: Out << "gt"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= le # <=
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_LessEqual: Out << "le"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= ge # >=
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_GreaterEqual: Out << "ge"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= nt # !
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_Exclaim: Out << "nt"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= aa # &&
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_AmpAmp: Out << "aa"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= oo # ||
|
|
|
|
case OO_PipePipe: Out << "oo"; break;
|
|
|
|
// ::= pp # ++
|
|
|
|
case OO_PlusPlus: Out << "pp"; break;
|
|
|
|
// ::= mm # --
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_MinusMinus: Out << "mm"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= cm # ,
|
|
|
|
case OO_Comma: Out << "cm"; break;
|
|
|
|
// ::= pm # ->*
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_ArrowStar: Out << "pm"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= pt # ->
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_Arrow: Out << "pt"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= cl # ()
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_Call: Out << "cl"; break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= ix # []
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_Subscript: Out << "ix"; break;
|
2009-12-14 09:45:37 +08:00
|
|
|
|
|
|
|
// ::= qu # ?
|
|
|
|
// The conditional operator can't be overloaded, but we still handle it when
|
|
|
|
// mangling expressions.
|
|
|
|
case OO_Conditional: Out << "qu"; break;
|
2009-02-13 08:10:09 +08:00
|
|
|
|
2009-04-17 01:51:27 +08:00
|
|
|
case OO_None:
|
2009-02-13 08:10:09 +08:00
|
|
|
case NUM_OVERLOADED_OPERATORS:
|
2009-09-09 23:08:12 +08:00
|
|
|
assert(false && "Not an overloaded operator");
|
2009-02-13 08:10:09 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-25 03:53:00 +08:00
|
|
|
void CXXNameMangler::mangleQualifiers(Qualifiers Quals) {
|
2009-09-09 23:08:12 +08:00
|
|
|
// <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
|
2009-09-25 03:53:00 +08:00
|
|
|
if (Quals.hasRestrict())
|
2009-02-13 08:10:09 +08:00
|
|
|
Out << 'r';
|
2009-09-25 03:53:00 +08:00
|
|
|
if (Quals.hasVolatile())
|
2009-02-13 08:10:09 +08:00
|
|
|
Out << 'V';
|
2009-09-25 03:53:00 +08:00
|
|
|
if (Quals.hasConst())
|
2009-02-13 08:10:09 +08:00
|
|
|
Out << 'K';
|
2009-09-25 03:53:00 +08:00
|
|
|
|
|
|
|
// FIXME: For now, just drop all extension qualifiers on the floor.
|
2009-02-13 08:10:09 +08:00
|
|
|
}
|
|
|
|
|
2009-12-10 11:14:39 +08:00
|
|
|
void CXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {
|
|
|
|
llvm::SmallString<64> Name;
|
|
|
|
llvm::raw_svector_ostream OS(Name);
|
|
|
|
|
|
|
|
const ObjCContainerDecl *CD =
|
|
|
|
dyn_cast<ObjCContainerDecl>(MD->getDeclContext());
|
|
|
|
assert (CD && "Missing container decl in GetNameForMethod");
|
|
|
|
OS << (MD->isInstanceMethod() ? '-' : '+') << '[' << CD->getName();
|
|
|
|
if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(CD))
|
|
|
|
OS << '(' << CID->getNameAsString() << ')';
|
|
|
|
OS << ' ' << MD->getSelector().getAsString() << ']';
|
|
|
|
|
|
|
|
Out << OS.str().size() << OS.str();
|
|
|
|
}
|
|
|
|
|
2009-02-13 08:10:09 +08:00
|
|
|
void CXXNameMangler::mangleType(QualType T) {
|
2009-03-11 01:07:44 +08:00
|
|
|
// Only operate on the canonical type!
|
2009-10-07 09:06:45 +08:00
|
|
|
T = Context.getASTContext().getCanonicalType(T);
|
2009-03-11 01:07:44 +08:00
|
|
|
|
First part of changes to eliminate problems with cv-qualifiers and
sugared types. The basic problem is that our qualifier accessors
(getQualifiers, getCVRQualifiers, isConstQualified, etc.) only look at
the current QualType and not at any qualifiers that come from sugared
types, meaning that we won't see these qualifiers through, e.g.,
typedefs:
typedef const int CInt;
typedef CInt Self;
Self.isConstQualified() currently returns false!
Various bugs (e.g., PR5383) have cropped up all over the front end due
to such problems. I'm addressing this problem by splitting each
qualifier accessor into two versions:
- the "local" version only returns qualifiers on this particular
QualType instance
- the "normal" version that will eventually combine qualifiers from this
QualType instance with the qualifiers on the canonical type to
produce the full set of qualifiers.
This commit adds the local versions and switches a few callers from
the "normal" version (e.g., isConstQualified) over to the "local"
version (e.g., isLocalConstQualified) when that is the right thing to
do, e.g., because we're printing or serializing the qualifiers. Also,
switch a bunch of
Context.getCanonicalType(T1).getUnqualifiedType() == Context.getCanonicalType(T2).getQualifiedType()
expressions over to
Context.hasSameUnqualifiedType(T1, T2)
llvm-svn: 88969
2009-11-17 05:35:15 +08:00
|
|
|
bool IsSubstitutable = T.hasLocalQualifiers() || !isa<BuiltinType>(T);
|
2009-09-17 08:43:46 +08:00
|
|
|
if (IsSubstitutable && mangleSubstitution(T))
|
|
|
|
return;
|
|
|
|
|
First part of changes to eliminate problems with cv-qualifiers and
sugared types. The basic problem is that our qualifier accessors
(getQualifiers, getCVRQualifiers, isConstQualified, etc.) only look at
the current QualType and not at any qualifiers that come from sugared
types, meaning that we won't see these qualifiers through, e.g.,
typedefs:
typedef const int CInt;
typedef CInt Self;
Self.isConstQualified() currently returns false!
Various bugs (e.g., PR5383) have cropped up all over the front end due
to such problems. I'm addressing this problem by splitting each
qualifier accessor into two versions:
- the "local" version only returns qualifiers on this particular
QualType instance
- the "normal" version that will eventually combine qualifiers from this
QualType instance with the qualifiers on the canonical type to
produce the full set of qualifiers.
This commit adds the local versions and switches a few callers from
the "normal" version (e.g., isConstQualified) over to the "local"
version (e.g., isLocalConstQualified) when that is the right thing to
do, e.g., because we're printing or serializing the qualifiers. Also,
switch a bunch of
Context.getCanonicalType(T1).getUnqualifiedType() == Context.getCanonicalType(T2).getQualifiedType()
expressions over to
Context.hasSameUnqualifiedType(T1, T2)
llvm-svn: 88969
2009-11-17 05:35:15 +08:00
|
|
|
if (Qualifiers Quals = T.getLocalQualifiers()) {
|
2009-09-25 03:53:00 +08:00
|
|
|
mangleQualifiers(Quals);
|
|
|
|
// Recurse: even if the qualified type isn't yet substitutable,
|
|
|
|
// the unqualified type might be.
|
First part of changes to eliminate problems with cv-qualifiers and
sugared types. The basic problem is that our qualifier accessors
(getQualifiers, getCVRQualifiers, isConstQualified, etc.) only look at
the current QualType and not at any qualifiers that come from sugared
types, meaning that we won't see these qualifiers through, e.g.,
typedefs:
typedef const int CInt;
typedef CInt Self;
Self.isConstQualified() currently returns false!
Various bugs (e.g., PR5383) have cropped up all over the front end due
to such problems. I'm addressing this problem by splitting each
qualifier accessor into two versions:
- the "local" version only returns qualifiers on this particular
QualType instance
- the "normal" version that will eventually combine qualifiers from this
QualType instance with the qualifiers on the canonical type to
produce the full set of qualifiers.
This commit adds the local versions and switches a few callers from
the "normal" version (e.g., isConstQualified) over to the "local"
version (e.g., isLocalConstQualified) when that is the right thing to
do, e.g., because we're printing or serializing the qualifiers. Also,
switch a bunch of
Context.getCanonicalType(T1).getUnqualifiedType() == Context.getCanonicalType(T2).getQualifiedType()
expressions over to
Context.hasSameUnqualifiedType(T1, T2)
llvm-svn: 88969
2009-11-17 05:35:15 +08:00
|
|
|
mangleType(T.getLocalUnqualifiedType());
|
2009-09-17 08:43:46 +08:00
|
|
|
} else {
|
|
|
|
switch (T->getTypeClass()) {
|
2009-09-05 15:56:18 +08:00
|
|
|
#define ABSTRACT_TYPE(CLASS, PARENT)
|
|
|
|
#define NON_CANONICAL_TYPE(CLASS, PARENT) \
|
2009-09-17 08:43:46 +08:00
|
|
|
case Type::CLASS: \
|
2009-12-12 13:05:38 +08:00
|
|
|
llvm_unreachable("can't mangle non-canonical type " #CLASS "Type"); \
|
2009-09-17 08:43:46 +08:00
|
|
|
return;
|
2009-09-05 15:56:18 +08:00
|
|
|
#define TYPE(CLASS, PARENT) \
|
2009-09-17 08:43:46 +08:00
|
|
|
case Type::CLASS: \
|
2009-09-25 03:53:00 +08:00
|
|
|
mangleType(static_cast<const CLASS##Type*>(T.getTypePtr())); \
|
2009-09-17 08:43:46 +08:00
|
|
|
break;
|
2009-09-05 15:56:18 +08:00
|
|
|
#include "clang/AST/TypeNodes.def"
|
2009-09-17 08:43:46 +08:00
|
|
|
}
|
2009-03-11 01:07:44 +08:00
|
|
|
}
|
2009-09-17 08:43:46 +08:00
|
|
|
|
|
|
|
// Add the substitution.
|
|
|
|
if (IsSubstitutable)
|
|
|
|
addSubstitution(T);
|
2009-02-13 08:10:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const BuiltinType *T) {
|
2009-09-05 15:56:18 +08:00
|
|
|
// <type> ::= <builtin-type>
|
2009-02-13 08:10:09 +08:00
|
|
|
// <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)
|
2009-07-14 14:30:34 +08:00
|
|
|
// ::= Di # char32_t
|
|
|
|
// ::= Ds # char16_t
|
2009-02-13 08:10:09 +08:00
|
|
|
// ::= u <source-name> # vendor extended type
|
2009-05-11 02:38:11 +08:00
|
|
|
// 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.
|
2009-02-13 08:10:09 +08:00
|
|
|
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;
|
2009-04-30 10:43:43 +08:00
|
|
|
case BuiltinType::UInt128: Out << 'o'; break;
|
2009-02-13 08:10:09 +08:00
|
|
|
case BuiltinType::SChar: Out << 'a'; break;
|
|
|
|
case BuiltinType::WChar: Out << 'w'; break;
|
2009-07-14 14:30:34 +08:00
|
|
|
case BuiltinType::Char16: Out << "Ds"; break;
|
|
|
|
case BuiltinType::Char32: Out << "Di"; break;
|
2009-02-13 08:10:09 +08:00
|
|
|
case BuiltinType::Short: Out << 's'; break;
|
|
|
|
case BuiltinType::Int: Out << 'i'; break;
|
|
|
|
case BuiltinType::Long: Out << 'l'; break;
|
|
|
|
case BuiltinType::LongLong: Out << 'x'; break;
|
2009-04-30 10:43:43 +08:00
|
|
|
case BuiltinType::Int128: Out << 'n'; break;
|
2009-02-13 08:10:09 +08:00
|
|
|
case BuiltinType::Float: Out << 'f'; break;
|
|
|
|
case BuiltinType::Double: Out << 'd'; break;
|
|
|
|
case BuiltinType::LongDouble: Out << 'e'; break;
|
2009-05-11 02:38:11 +08:00
|
|
|
case BuiltinType::NullPtr: Out << "St9nullptr_t"; break;
|
2009-02-13 08:10:09 +08:00
|
|
|
|
|
|
|
case BuiltinType::Overload:
|
|
|
|
case BuiltinType::Dependent:
|
2009-09-09 23:08:12 +08:00
|
|
|
assert(false &&
|
2009-02-13 08:10:09 +08:00
|
|
|
"Overloaded and dependent types shouldn't get to name mangling");
|
|
|
|
break;
|
2009-06-27 02:41:36 +08:00
|
|
|
case BuiltinType::UndeducedAuto:
|
|
|
|
assert(0 && "Should not see undeduced auto here");
|
|
|
|
break;
|
2009-07-23 01:14:51 +08:00
|
|
|
case BuiltinType::ObjCId: Out << "11objc_object"; break;
|
|
|
|
case BuiltinType::ObjCClass: Out << "10objc_class"; break;
|
2009-11-22 03:53:08 +08:00
|
|
|
case BuiltinType::ObjCSel: Out << "13objc_selector"; break;
|
2009-02-13 08:10:09 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-05 15:56:18 +08:00
|
|
|
// <type> ::= <function-type>
|
|
|
|
// <function-type> ::= F [Y] <bare-function-type> E
|
|
|
|
void CXXNameMangler::mangleType(const FunctionProtoType *T) {
|
2009-02-13 08:10:09 +08:00
|
|
|
Out << 'F';
|
2009-05-16 15:57:57 +08:00
|
|
|
// FIXME: We don't have enough information in the AST to produce the 'Y'
|
|
|
|
// encoding for extern "C" function types.
|
2009-02-13 08:10:09 +08:00
|
|
|
mangleBareFunctionType(T, /*MangleReturnType=*/true);
|
|
|
|
Out << 'E';
|
|
|
|
}
|
2009-09-05 15:56:18 +08:00
|
|
|
void CXXNameMangler::mangleType(const FunctionNoProtoType *T) {
|
2009-12-12 13:05:38 +08:00
|
|
|
llvm_unreachable("Can't mangle K&R function prototypes");
|
2009-09-05 15:56:18 +08:00
|
|
|
}
|
2009-02-13 08:10:09 +08:00
|
|
|
void CXXNameMangler::mangleBareFunctionType(const FunctionType *T,
|
|
|
|
bool MangleReturnType) {
|
2009-09-05 15:56:18 +08:00
|
|
|
// We should never be mangling something without a prototype.
|
|
|
|
const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
|
|
|
|
|
2009-02-13 08:10:09 +08:00
|
|
|
// <bare-function-type> ::= <signature type>+
|
|
|
|
if (MangleReturnType)
|
2009-09-05 15:56:18 +08:00
|
|
|
mangleType(Proto->getResultType());
|
2009-02-13 08:10:09 +08:00
|
|
|
|
2009-04-01 08:15:23 +08:00
|
|
|
if (Proto->getNumArgs() == 0) {
|
|
|
|
Out << 'v';
|
|
|
|
return;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-27 07:50:07 +08:00
|
|
|
for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
|
2009-09-09 23:08:12 +08:00
|
|
|
ArgEnd = Proto->arg_type_end();
|
2009-02-13 08:10:09 +08:00
|
|
|
Arg != ArgEnd; ++Arg)
|
|
|
|
mangleType(*Arg);
|
2009-02-13 09:28:03 +08:00
|
|
|
|
|
|
|
// <builtin-type> ::= z # ellipsis
|
|
|
|
if (Proto->isVariadic())
|
|
|
|
Out << 'z';
|
2009-02-13 08:10:09 +08:00
|
|
|
}
|
|
|
|
|
2009-12-05 06:46:56 +08:00
|
|
|
// <type> ::= <class-enum-type>
|
|
|
|
// <class-enum-type> ::= <name>
|
|
|
|
void CXXNameMangler::mangleType(const UnresolvedUsingType *T) {
|
|
|
|
mangleName(T->getDecl());
|
|
|
|
}
|
|
|
|
|
2009-09-05 15:56:18 +08:00
|
|
|
// <type> ::= <class-enum-type>
|
2009-09-09 23:08:12 +08:00
|
|
|
// <class-enum-type> ::= <name>
|
2009-09-05 15:56:18 +08:00
|
|
|
void CXXNameMangler::mangleType(const EnumType *T) {
|
|
|
|
mangleType(static_cast<const TagType*>(T));
|
|
|
|
}
|
|
|
|
void CXXNameMangler::mangleType(const RecordType *T) {
|
|
|
|
mangleType(static_cast<const TagType*>(T));
|
|
|
|
}
|
2009-02-13 08:10:09 +08:00
|
|
|
void CXXNameMangler::mangleType(const TagType *T) {
|
2009-12-12 02:00:57 +08:00
|
|
|
mangleName(T->getDecl());
|
2009-02-13 08:10:09 +08:00
|
|
|
}
|
|
|
|
|
2009-09-05 15:56:18 +08:00
|
|
|
// <type> ::= <array-type>
|
|
|
|
// <array-type> ::= A <positive dimension number> _ <element type>
|
|
|
|
// ::= A [<dimension expression>] _ <element type>
|
|
|
|
void CXXNameMangler::mangleType(const ConstantArrayType *T) {
|
|
|
|
Out << 'A' << T->getSize() << '_';
|
|
|
|
mangleType(T->getElementType());
|
|
|
|
}
|
|
|
|
void CXXNameMangler::mangleType(const VariableArrayType *T) {
|
2009-02-13 08:10:09 +08:00
|
|
|
Out << 'A';
|
2009-09-05 15:56:18 +08:00
|
|
|
mangleExpression(T->getSizeExpr());
|
2009-02-13 08:10:09 +08:00
|
|
|
Out << '_';
|
|
|
|
mangleType(T->getElementType());
|
|
|
|
}
|
2009-09-05 15:56:18 +08:00
|
|
|
void CXXNameMangler::mangleType(const DependentSizedArrayType *T) {
|
|
|
|
Out << 'A';
|
|
|
|
mangleExpression(T->getSizeExpr());
|
|
|
|
Out << '_';
|
|
|
|
mangleType(T->getElementType());
|
|
|
|
}
|
|
|
|
void CXXNameMangler::mangleType(const IncompleteArrayType *T) {
|
|
|
|
Out << 'A' << '_';
|
|
|
|
mangleType(T->getElementType());
|
|
|
|
}
|
2009-02-13 08:10:09 +08:00
|
|
|
|
2009-09-05 15:56:18 +08:00
|
|
|
// <type> ::= <pointer-to-member-type>
|
|
|
|
// <pointer-to-member-type> ::= M <class type> <member type>
|
2009-02-13 08:10:09 +08:00
|
|
|
void CXXNameMangler::mangleType(const MemberPointerType *T) {
|
|
|
|
Out << 'M';
|
|
|
|
mangleType(QualType(T->getClass(), 0));
|
2009-05-18 01:41:20 +08:00
|
|
|
QualType PointeeType = T->getPointeeType();
|
|
|
|
if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(PointeeType)) {
|
2009-09-25 03:53:00 +08:00
|
|
|
mangleQualifiers(Qualifiers::fromCVRMask(FPT->getTypeQuals()));
|
2009-05-18 01:41:20 +08:00
|
|
|
mangleType(FPT);
|
2009-09-09 23:08:12 +08:00
|
|
|
} else
|
2009-05-18 01:41:20 +08:00
|
|
|
mangleType(PointeeType);
|
2009-02-13 08:10:09 +08:00
|
|
|
}
|
|
|
|
|
2009-09-05 15:56:18 +08:00
|
|
|
// <type> ::= <template-param>
|
2009-02-13 08:10:09 +08:00
|
|
|
void CXXNameMangler::mangleType(const TemplateTypeParmType *T) {
|
2009-09-27 08:38:53 +08:00
|
|
|
mangleTemplateParameter(T->getIndex());
|
2009-02-13 08:10:09 +08:00
|
|
|
}
|
|
|
|
|
2009-09-05 15:56:18 +08:00
|
|
|
// FIXME: <type> ::= <template-template-param> <template-args>
|
|
|
|
|
|
|
|
// <type> ::= P <type> # pointer-to
|
|
|
|
void CXXNameMangler::mangleType(const PointerType *T) {
|
|
|
|
Out << 'P';
|
|
|
|
mangleType(T->getPointeeType());
|
|
|
|
}
|
|
|
|
void CXXNameMangler::mangleType(const ObjCObjectPointerType *T) {
|
|
|
|
Out << 'P';
|
|
|
|
mangleType(T->getPointeeType());
|
|
|
|
}
|
|
|
|
|
|
|
|
// <type> ::= R <type> # reference-to
|
|
|
|
void CXXNameMangler::mangleType(const LValueReferenceType *T) {
|
|
|
|
Out << 'R';
|
|
|
|
mangleType(T->getPointeeType());
|
|
|
|
}
|
|
|
|
|
|
|
|
// <type> ::= O <type> # rvalue reference-to (C++0x)
|
|
|
|
void CXXNameMangler::mangleType(const RValueReferenceType *T) {
|
|
|
|
Out << 'O';
|
|
|
|
mangleType(T->getPointeeType());
|
|
|
|
}
|
|
|
|
|
|
|
|
// <type> ::= C <type> # complex pair (C 2000)
|
|
|
|
void CXXNameMangler::mangleType(const ComplexType *T) {
|
|
|
|
Out << 'C';
|
|
|
|
mangleType(T->getElementType());
|
|
|
|
}
|
|
|
|
|
|
|
|
// GNU extension: vector types
|
|
|
|
void CXXNameMangler::mangleType(const VectorType *T) {
|
|
|
|
Out << "U8__vector";
|
|
|
|
mangleType(T->getElementType());
|
|
|
|
}
|
|
|
|
void CXXNameMangler::mangleType(const ExtVectorType *T) {
|
|
|
|
mangleType(static_cast<const VectorType*>(T));
|
|
|
|
}
|
|
|
|
void CXXNameMangler::mangleType(const DependentSizedExtVectorType *T) {
|
|
|
|
Out << "U8__vector";
|
|
|
|
mangleType(T->getElementType());
|
|
|
|
}
|
|
|
|
|
2009-03-08 06:03:21 +08:00
|
|
|
void CXXNameMangler::mangleType(const ObjCInterfaceType *T) {
|
|
|
|
mangleSourceName(T->getDecl()->getIdentifier());
|
|
|
|
}
|
|
|
|
|
2009-09-05 15:56:18 +08:00
|
|
|
void CXXNameMangler::mangleType(const BlockPointerType *T) {
|
|
|
|
assert(false && "can't mangle block pointer types yet");
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const FixedWidthIntType *T) {
|
|
|
|
assert(false && "can't mangle arbitary-precision integer type yet");
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const TemplateSpecializationType *T) {
|
2009-09-18 10:42:01 +08:00
|
|
|
TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl();
|
|
|
|
assert(TD && "FIXME: Support dependent template names!");
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-18 10:42:01 +08:00
|
|
|
mangleName(TD, T->getArgs(), T->getNumArgs());
|
2009-09-05 15:56:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const TypenameType *T) {
|
2009-09-26 10:26:02 +08:00
|
|
|
// Typename types are always nested
|
|
|
|
Out << 'N';
|
|
|
|
|
|
|
|
const Type *QTy = T->getQualifier()->getAsType();
|
2009-11-21 17:05:47 +08:00
|
|
|
if (const TemplateSpecializationType *TST =
|
2009-09-26 10:26:02 +08:00
|
|
|
dyn_cast<TemplateSpecializationType>(QTy)) {
|
2009-09-27 09:06:07 +08:00
|
|
|
if (!mangleSubstitution(QualType(TST, 0))) {
|
|
|
|
TemplateDecl *TD = TST->getTemplateName().getAsTemplateDecl();
|
2009-09-26 10:26:02 +08:00
|
|
|
|
2009-09-27 09:06:07 +08:00
|
|
|
mangleTemplatePrefix(TD);
|
|
|
|
mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
|
|
|
|
addSubstitution(QualType(TST, 0));
|
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
} else if (const TemplateTypeParmType *TTPT =
|
2009-09-27 08:38:53 +08:00
|
|
|
dyn_cast<TemplateTypeParmType>(QTy)) {
|
|
|
|
// We use the QualType mangle type variant here because it handles
|
|
|
|
// substitutions.
|
|
|
|
mangleType(QualType(TTPT, 0));
|
2009-09-26 10:26:02 +08:00
|
|
|
} else
|
|
|
|
assert(false && "Unhandled type!");
|
|
|
|
|
|
|
|
mangleSourceName(T->getIdentifier());
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-26 10:26:02 +08:00
|
|
|
Out << 'E';
|
2009-09-05 15:56:18 +08:00
|
|
|
}
|
|
|
|
|
2009-12-14 09:45:37 +08:00
|
|
|
void CXXNameMangler::mangleIntegerLiteral(QualType T,
|
|
|
|
const llvm::APSInt &Value) {
|
|
|
|
// <expr-primary> ::= L <type> <value number> E # integer literal
|
|
|
|
Out << 'L';
|
|
|
|
|
|
|
|
mangleType(T);
|
|
|
|
if (T->isBooleanType()) {
|
|
|
|
// Boolean values are encoded as 0/1.
|
|
|
|
Out << (Value.getBoolValue() ? '1' : '0');
|
|
|
|
} else {
|
|
|
|
if (Value.isNegative())
|
|
|
|
Out << 'n';
|
|
|
|
Value.abs().print(Out, false);
|
|
|
|
}
|
|
|
|
Out << 'E';
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-09-21 09:21:10 +08:00
|
|
|
void CXXNameMangler::mangleExpression(const Expr *E) {
|
|
|
|
// <expression> ::= <unary operator-name> <expression>
|
|
|
|
// ::= <binary operator-name> <expression> <expression>
|
|
|
|
// ::= <trinary operator-name> <expression> <expression> <expression>
|
|
|
|
// ::= cl <expression>* E # call
|
|
|
|
// ::= cv <type> expression # conversion with one argument
|
|
|
|
// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
|
|
|
|
// ::= st <type> # sizeof (a type)
|
|
|
|
// ::= at <type> # alignof (a type)
|
|
|
|
// ::= <template-param>
|
|
|
|
// ::= <function-param>
|
|
|
|
// ::= sr <type> <unqualified-name> # dependent name
|
|
|
|
// ::= sr <type> <unqualified-name> <template-args> # dependent template-id
|
|
|
|
// ::= sZ <template-param> # size of a parameter pack
|
|
|
|
// ::= <expr-primary>
|
|
|
|
switch (E->getStmtClass()) {
|
|
|
|
default: assert(false && "Unhandled expression kind!");
|
2009-11-06 10:50:19 +08:00
|
|
|
|
2009-12-14 09:45:37 +08:00
|
|
|
case Expr::UnaryOperatorClass: {
|
|
|
|
const UnaryOperator *UO = cast<UnaryOperator>(E);
|
|
|
|
mangleOperatorName(UnaryOperator::getOverloadedOperator(UO->getOpcode()),
|
|
|
|
/*Arity=*/1);
|
|
|
|
mangleExpression(UO->getSubExpr());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case Expr::BinaryOperatorClass: {
|
|
|
|
const BinaryOperator *BO = cast<BinaryOperator>(E);
|
|
|
|
mangleOperatorName(BinaryOperator::getOverloadedOperator(BO->getOpcode()),
|
|
|
|
/*Arity=*/2);
|
|
|
|
mangleExpression(BO->getLHS());
|
|
|
|
mangleExpression(BO->getRHS());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case Expr::ConditionalOperatorClass: {
|
|
|
|
const ConditionalOperator *CO = cast<ConditionalOperator>(E);
|
|
|
|
mangleOperatorName(OO_Conditional, /*Arity=*/3);
|
|
|
|
mangleExpression(CO->getCond());
|
|
|
|
mangleExpression(CO->getLHS());
|
|
|
|
mangleExpression(CO->getRHS());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-12-16 13:48:46 +08:00
|
|
|
case Expr::CXXOperatorCallExprClass: {
|
|
|
|
const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E);
|
|
|
|
unsigned NumArgs = CE->getNumArgs();
|
|
|
|
mangleOperatorName(CE->getOperator(), /*Arity=*/NumArgs);
|
|
|
|
// Mangle the arguments.
|
|
|
|
for (unsigned i = 0; i != NumArgs; ++i)
|
|
|
|
mangleExpression(CE->getArg(i));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-11-06 10:50:19 +08:00
|
|
|
case Expr::ParenExprClass:
|
|
|
|
mangleExpression(cast<ParenExpr>(E)->getSubExpr());
|
|
|
|
break;
|
|
|
|
|
2009-09-21 09:21:10 +08:00
|
|
|
case Expr::DeclRefExprClass: {
|
|
|
|
const Decl *D = cast<DeclRefExpr>(E)->getDecl();
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-21 09:21:10 +08:00
|
|
|
switch (D->getKind()) {
|
|
|
|
default: assert(false && "Unhandled decl kind!");
|
|
|
|
case Decl::NonTypeTemplateParm: {
|
|
|
|
const NonTypeTemplateParmDecl *PD = cast<NonTypeTemplateParmDecl>(D);
|
2009-09-27 08:38:53 +08:00
|
|
|
mangleTemplateParameter(PD->getIndex());
|
2009-09-21 09:21:10 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-28 04:11:34 +08:00
|
|
|
break;
|
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-11-20 06:55:06 +08:00
|
|
|
case Expr::DependentScopeDeclRefExprClass: {
|
|
|
|
const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
|
2009-09-28 04:11:34 +08:00
|
|
|
const Type *QTy = DRE->getQualifier()->getAsType();
|
|
|
|
assert(QTy && "Qualifier was not type!");
|
|
|
|
|
|
|
|
// ::= sr <type> <unqualified-name> # dependent name
|
|
|
|
Out << "sr";
|
|
|
|
mangleType(QualType(QTy, 0));
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-28 04:11:34 +08:00
|
|
|
assert(DRE->getDeclName().getNameKind() == DeclarationName::Identifier &&
|
|
|
|
"Unhandled decl name kind!");
|
|
|
|
mangleSourceName(DRE->getDeclName().getAsIdentifierInfo());
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-28 04:11:34 +08:00
|
|
|
break;
|
2009-09-21 09:21:10 +08:00
|
|
|
}
|
2009-09-28 04:11:34 +08:00
|
|
|
|
2009-12-14 09:45:37 +08:00
|
|
|
case Expr::IntegerLiteralClass:
|
|
|
|
mangleIntegerLiteral(E->getType(),
|
|
|
|
llvm::APSInt(cast<IntegerLiteral>(E)->getValue()));
|
|
|
|
break;
|
|
|
|
|
2009-09-21 09:21:10 +08:00
|
|
|
}
|
2009-02-13 08:10:09 +08:00
|
|
|
}
|
|
|
|
|
2009-09-05 15:56:18 +08:00
|
|
|
// FIXME: <type> ::= G <type> # imaginary (C 2000)
|
|
|
|
// FIXME: <type> ::= U <source-name> <type> # vendor extended type qualifier
|
|
|
|
|
2009-04-15 13:36:58 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-17 09:58:57 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-24 03:30:55 +08:00
|
|
|
void CXXNameMangler::mangleTemplateArgs(const TemplateArgumentList &L) {
|
2009-05-16 00:09:15 +08:00
|
|
|
// <template-args> ::= I <template-arg>+ E
|
|
|
|
Out << "I";
|
2009-11-21 17:17:15 +08:00
|
|
|
for (unsigned i = 0, e = L.size(); i != e; ++i)
|
2009-12-24 03:30:55 +08:00
|
|
|
mangleTemplateArg(L[i]);
|
2009-05-16 00:09:15 +08:00
|
|
|
Out << "E";
|
|
|
|
}
|
|
|
|
|
2009-09-18 10:42:01 +08:00
|
|
|
void CXXNameMangler::mangleTemplateArgs(const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs) {
|
|
|
|
// <template-args> ::= I <template-arg>+ E
|
|
|
|
Out << "I";
|
2009-11-21 17:17:15 +08:00
|
|
|
for (unsigned i = 0; i != NumTemplateArgs; ++i)
|
2009-12-24 03:30:55 +08:00
|
|
|
mangleTemplateArg(TemplateArgs[i]);
|
2009-09-18 10:42:01 +08:00
|
|
|
Out << "E";
|
|
|
|
}
|
|
|
|
|
2009-12-24 03:30:55 +08:00
|
|
|
void CXXNameMangler::mangleTemplateArg(const TemplateArgument &A) {
|
2009-09-09 23:08:12 +08:00
|
|
|
// <template-arg> ::= <type> # type or template
|
2009-05-16 00:09:15 +08:00
|
|
|
// ::= 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;
|
2009-12-24 03:30:55 +08:00
|
|
|
case TemplateArgument::Template:
|
|
|
|
mangleName(A.getAsTemplate().getAsTemplateDecl());
|
|
|
|
break;
|
2009-09-21 09:21:10 +08:00
|
|
|
case TemplateArgument::Expression:
|
|
|
|
Out << 'X';
|
|
|
|
mangleExpression(A.getAsExpr());
|
|
|
|
Out << 'E';
|
|
|
|
break;
|
2009-12-14 09:45:37 +08:00
|
|
|
case TemplateArgument::Integral:
|
|
|
|
mangleIntegerLiteral(A.getIntegralType(), *A.getAsIntegral());
|
2009-11-21 17:17:15 +08:00
|
|
|
break;
|
|
|
|
case TemplateArgument::Declaration: {
|
|
|
|
// <expr-primary> ::= L <mangled-name> E # external name
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-21 17:17:15 +08:00
|
|
|
// FIXME: Clang produces AST's where pointer-to-member-function expressions
|
|
|
|
// and pointer-to-function expressions are represented as a declaration not
|
|
|
|
// an expression; this is not how gcc represents them and this changes the
|
|
|
|
// mangling.
|
|
|
|
Out << 'L';
|
|
|
|
// References to external entities use the mangled name; if the name would
|
|
|
|
// not normally be manged then mangle it as unqualified.
|
|
|
|
//
|
|
|
|
// FIXME: The ABI specifies that external names here should have _Z, but
|
|
|
|
// gcc leaves this off.
|
|
|
|
mangle(cast<NamedDecl>(A.getAsDecl()), "Z");
|
2009-05-16 00:09:15 +08:00
|
|
|
Out << 'E';
|
|
|
|
break;
|
|
|
|
}
|
2009-11-21 17:17:15 +08:00
|
|
|
}
|
2009-05-16 00:09:15 +08:00
|
|
|
}
|
|
|
|
|
2009-09-27 08:38:53 +08:00
|
|
|
void CXXNameMangler::mangleTemplateParameter(unsigned Index) {
|
|
|
|
// <template-param> ::= T_ # first template parameter
|
|
|
|
// ::= T <parameter-2 non-negative number> _
|
|
|
|
if (Index == 0)
|
|
|
|
Out << "T_";
|
|
|
|
else
|
|
|
|
Out << 'T' << (Index - 1) << '_';
|
|
|
|
}
|
|
|
|
|
2009-09-17 08:43:46 +08:00
|
|
|
// <substitution> ::= S <seq-id> _
|
|
|
|
// ::= S_
|
2009-09-17 12:16:28 +08:00
|
|
|
bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) {
|
2009-09-27 04:53:44 +08:00
|
|
|
// Try one of the standard substitutions first.
|
|
|
|
if (mangleStandardSubstitution(ND))
|
|
|
|
return true;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-11-07 12:26:04 +08:00
|
|
|
ND = cast<NamedDecl>(ND->getCanonicalDecl());
|
2009-09-17 12:16:28 +08:00
|
|
|
return mangleSubstitution(reinterpret_cast<uintptr_t>(ND));
|
|
|
|
}
|
|
|
|
|
2009-09-17 08:43:46 +08:00
|
|
|
bool CXXNameMangler::mangleSubstitution(QualType T) {
|
2009-09-26 11:55:37 +08:00
|
|
|
if (!T.getCVRQualifiers()) {
|
|
|
|
if (const RecordType *RT = T->getAs<RecordType>())
|
|
|
|
return mangleSubstitution(RT->getDecl());
|
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-17 08:43:46 +08:00
|
|
|
uintptr_t TypePtr = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
|
|
|
|
|
2009-09-17 11:53:28 +08:00
|
|
|
return mangleSubstitution(TypePtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CXXNameMangler::mangleSubstitution(uintptr_t Ptr) {
|
2009-11-21 17:05:47 +08:00
|
|
|
llvm::DenseMap<uintptr_t, unsigned>::iterator I =
|
2009-09-17 11:53:28 +08:00
|
|
|
Substitutions.find(Ptr);
|
2009-09-17 08:43:46 +08:00
|
|
|
if (I == Substitutions.end())
|
|
|
|
return false;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-17 08:43:46 +08:00
|
|
|
unsigned SeqID = I->second;
|
|
|
|
if (SeqID == 0)
|
|
|
|
Out << "S_";
|
|
|
|
else {
|
|
|
|
SeqID--;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-17 08:43:46 +08:00
|
|
|
// <seq-id> is encoded in base-36, using digits and upper case letters.
|
|
|
|
char Buffer[10];
|
|
|
|
char *BufferPtr = Buffer + 9;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-17 08:43:46 +08:00
|
|
|
*BufferPtr = 0;
|
|
|
|
if (SeqID == 0) *--BufferPtr = '0';
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-17 08:43:46 +08:00
|
|
|
while (SeqID) {
|
|
|
|
assert(BufferPtr > Buffer && "Buffer overflow!");
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-17 08:43:46 +08:00
|
|
|
unsigned char c = static_cast<unsigned char>(SeqID) % 36;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-17 08:43:46 +08:00
|
|
|
*--BufferPtr = (c < 10 ? '0' + c : 'A' + c - 10);
|
|
|
|
SeqID /= 36;
|
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-17 08:43:46 +08:00
|
|
|
Out << 'S' << BufferPtr << '_';
|
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-17 08:43:46 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-09-27 08:12:57 +08:00
|
|
|
static bool isCharType(QualType T) {
|
|
|
|
if (T.isNull())
|
|
|
|
return false;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-27 08:12:57 +08:00
|
|
|
return T->isSpecificBuiltinType(BuiltinType::Char_S) ||
|
|
|
|
T->isSpecificBuiltinType(BuiltinType::Char_U);
|
|
|
|
}
|
|
|
|
|
2009-11-21 17:05:47 +08:00
|
|
|
/// isCharSpecialization - Returns whether a given type is a template
|
2009-09-27 08:12:57 +08:00
|
|
|
/// specialization of a given name with a single argument of type char.
|
|
|
|
static bool isCharSpecialization(QualType T, const char *Name) {
|
|
|
|
if (T.isNull())
|
|
|
|
return false;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-27 08:12:57 +08:00
|
|
|
const RecordType *RT = T->getAs<RecordType>();
|
|
|
|
if (!RT)
|
|
|
|
return false;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
|
|
|
const ClassTemplateSpecializationDecl *SD =
|
2009-09-27 08:12:57 +08:00
|
|
|
dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
|
|
|
|
if (!SD)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!isStdNamespace(SD->getDeclContext()))
|
|
|
|
return false;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-27 08:12:57 +08:00
|
|
|
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
|
|
|
|
if (TemplateArgs.size() != 1)
|
|
|
|
return false;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-27 08:12:57 +08:00
|
|
|
if (!isCharType(TemplateArgs[0].getAsType()))
|
|
|
|
return false;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-10-19 05:17:35 +08:00
|
|
|
return SD->getIdentifier()->getName() == Name;
|
2009-09-27 08:12:57 +08:00
|
|
|
}
|
|
|
|
|
2009-12-08 03:56:42 +08:00
|
|
|
template <std::size_t StrLen>
|
|
|
|
bool isStreamCharSpecialization(const ClassTemplateSpecializationDecl *SD,
|
|
|
|
const char (&Str)[StrLen]) {
|
|
|
|
if (!SD->getIdentifier()->isStr(Str))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
|
|
|
|
if (TemplateArgs.size() != 2)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!isCharType(TemplateArgs[0].getAsType()))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-09-27 04:53:44 +08:00
|
|
|
bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
|
|
|
|
// <substitution> ::= St # ::std::
|
2009-09-27 07:10:05 +08:00
|
|
|
if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
|
2009-12-04 14:23:23 +08:00
|
|
|
if (isStd(NS)) {
|
2009-09-27 07:10:05 +08:00
|
|
|
Out << "St";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const ClassTemplateDecl *TD = dyn_cast<ClassTemplateDecl>(ND)) {
|
|
|
|
if (!isStdNamespace(TD->getDeclContext()))
|
|
|
|
return false;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-27 07:10:05 +08:00
|
|
|
// <substitution> ::= Sa # ::std::allocator
|
|
|
|
if (TD->getIdentifier()->isStr("allocator")) {
|
|
|
|
Out << "Sa";
|
|
|
|
return true;
|
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-27 07:14:39 +08:00
|
|
|
// <<substitution> ::= Sb # ::std::basic_string
|
|
|
|
if (TD->getIdentifier()->isStr("basic_string")) {
|
|
|
|
Out << "Sb";
|
|
|
|
return true;
|
|
|
|
}
|
2009-09-27 07:10:05 +08:00
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
|
|
|
|
if (const ClassTemplateSpecializationDecl *SD =
|
2009-09-27 08:12:57 +08:00
|
|
|
dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
|
|
|
|
// <substitution> ::= Ss # ::std::basic_string<char,
|
|
|
|
// ::std::char_traits<char>,
|
|
|
|
// ::std::allocator<char> >
|
|
|
|
if (SD->getIdentifier()->isStr("basic_string")) {
|
|
|
|
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-27 08:12:57 +08:00
|
|
|
if (TemplateArgs.size() != 3)
|
|
|
|
return false;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-27 08:12:57 +08:00
|
|
|
if (!isCharType(TemplateArgs[0].getAsType()))
|
|
|
|
return false;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-27 08:12:57 +08:00
|
|
|
if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))
|
|
|
|
return false;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-27 08:12:57 +08:00
|
|
|
if (!isCharSpecialization(TemplateArgs[2].getAsType(), "allocator"))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Out << "Ss";
|
|
|
|
return true;
|
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-12-08 03:56:42 +08:00
|
|
|
// <substitution> ::= Si # ::std::basic_istream<char,
|
2009-10-09 01:20:26 +08:00
|
|
|
// ::std::char_traits<char> >
|
2009-12-08 03:56:42 +08:00
|
|
|
if (isStreamCharSpecialization(SD, "basic_istream")) {
|
|
|
|
Out << "Si";
|
|
|
|
return true;
|
|
|
|
}
|
2009-10-09 01:20:26 +08:00
|
|
|
|
2009-12-08 03:56:42 +08:00
|
|
|
// <substitution> ::= So # ::std::basic_ostream<char,
|
|
|
|
// ::std::char_traits<char> >
|
|
|
|
if (isStreamCharSpecialization(SD, "basic_ostream")) {
|
2009-10-09 01:20:26 +08:00
|
|
|
Out << "So";
|
|
|
|
return true;
|
|
|
|
}
|
2009-12-08 03:56:42 +08:00
|
|
|
|
|
|
|
// <substitution> ::= Sd # ::std::basic_iostream<char,
|
|
|
|
// ::std::char_traits<char> >
|
|
|
|
if (isStreamCharSpecialization(SD, "basic_iostream")) {
|
|
|
|
Out << "Sd";
|
|
|
|
return true;
|
|
|
|
}
|
2009-09-27 08:12:57 +08:00
|
|
|
}
|
2009-09-27 07:10:05 +08:00
|
|
|
return false;
|
2009-09-27 04:53:44 +08:00
|
|
|
}
|
|
|
|
|
2009-09-17 08:43:46 +08:00
|
|
|
void CXXNameMangler::addSubstitution(QualType T) {
|
2009-09-26 11:55:37 +08:00
|
|
|
if (!T.getCVRQualifiers()) {
|
|
|
|
if (const RecordType *RT = T->getAs<RecordType>()) {
|
|
|
|
addSubstitution(RT->getDecl());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-17 08:43:46 +08:00
|
|
|
uintptr_t TypePtr = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
|
2009-09-17 11:53:28 +08:00
|
|
|
addSubstitution(TypePtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::addSubstitution(uintptr_t Ptr) {
|
2009-09-17 08:43:46 +08:00
|
|
|
unsigned SeqID = Substitutions.size();
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-17 11:53:28 +08:00
|
|
|
assert(!Substitutions.count(Ptr) && "Substitution already exists!");
|
2009-11-21 17:05:47 +08:00
|
|
|
Substitutions[Ptr] = SeqID;
|
2009-09-17 08:43:46 +08:00
|
|
|
}
|
|
|
|
|
2009-11-21 17:06:10 +08:00
|
|
|
//
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-21 17:06:10 +08:00
|
|
|
/// \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.
|
2009-11-21 17:14:52 +08:00
|
|
|
void MangleContext::mangleName(const NamedDecl *D,
|
2009-11-21 17:06:22 +08:00
|
|
|
llvm::SmallVectorImpl<char> &Res) {
|
2009-11-21 17:14:44 +08:00
|
|
|
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!");
|
2009-11-21 17:06:10 +08:00
|
|
|
|
|
|
|
PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
|
|
|
|
getASTContext().getSourceManager(),
|
|
|
|
"Mangling declaration");
|
|
|
|
|
2009-11-21 17:06:22 +08:00
|
|
|
CXXNameMangler Mangler(*this, Res);
|
|
|
|
return Mangler.mangle(D);
|
2009-11-21 17:06:10 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-21 17:12:13 +08:00
|
|
|
void MangleContext::mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
|
|
|
|
llvm::SmallVectorImpl<char> &Res) {
|
|
|
|
CXXNameMangler Mangler(*this, Res, D, Type);
|
|
|
|
Mangler.mangle(D);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MangleContext::mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
|
|
|
|
llvm::SmallVectorImpl<char> &Res) {
|
|
|
|
CXXNameMangler Mangler(*this, Res, D, Type);
|
|
|
|
Mangler.mangle(D);
|
|
|
|
}
|
|
|
|
|
2009-11-21 17:06:10 +08:00
|
|
|
/// \brief Mangles the a thunk with the offset n for the declaration D and
|
|
|
|
/// emits that name to the given output stream.
|
2009-11-26 10:32:05 +08:00
|
|
|
void MangleContext::mangleThunk(const FunctionDecl *FD,
|
2009-11-26 10:49:32 +08:00
|
|
|
const ThunkAdjustment &ThisAdjustment,
|
2009-11-21 17:06:22 +08:00
|
|
|
llvm::SmallVectorImpl<char> &Res) {
|
2009-11-21 17:06:10 +08:00
|
|
|
assert(!isa<CXXDestructorDecl>(FD) &&
|
|
|
|
"Use mangleCXXDtor for destructor decls!");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-21 17:12:13 +08:00
|
|
|
// <special-name> ::= T <call-offset> <base encoding>
|
|
|
|
// # base is the nominal target function of thunk
|
2009-11-21 17:06:22 +08:00
|
|
|
CXXNameMangler Mangler(*this, Res);
|
2009-11-21 17:12:13 +08:00
|
|
|
Mangler.getStream() << "_ZT";
|
2009-11-26 10:49:32 +08:00
|
|
|
Mangler.mangleCallOffset(ThisAdjustment);
|
2009-11-21 17:12:13 +08:00
|
|
|
Mangler.mangleFunctionEncoding(FD);
|
2009-11-21 17:06:10 +08:00
|
|
|
}
|
2009-04-14 02:02:10 +08:00
|
|
|
|
2009-12-03 08:03:05 +08:00
|
|
|
void MangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *D,
|
|
|
|
CXXDtorType Type,
|
|
|
|
const ThunkAdjustment &ThisAdjustment,
|
|
|
|
llvm::SmallVectorImpl<char> &Res) {
|
|
|
|
// <special-name> ::= T <call-offset> <base encoding>
|
|
|
|
// # base is the nominal target function of thunk
|
|
|
|
CXXNameMangler Mangler(*this, Res, D, Type);
|
|
|
|
Mangler.getStream() << "_ZT";
|
|
|
|
Mangler.mangleCallOffset(ThisAdjustment);
|
|
|
|
Mangler.mangleFunctionEncoding(D);
|
|
|
|
}
|
|
|
|
|
2009-11-21 17:06:10 +08:00
|
|
|
/// \brief Mangles the a covariant thunk for the declaration D and emits that
|
|
|
|
/// name to the given output stream.
|
2009-11-26 11:09:37 +08:00
|
|
|
void
|
|
|
|
MangleContext::mangleCovariantThunk(const FunctionDecl *FD,
|
|
|
|
const CovariantThunkAdjustment& Adjustment,
|
|
|
|
llvm::SmallVectorImpl<char> &Res) {
|
2009-11-21 17:06:10 +08:00
|
|
|
assert(!isa<CXXDestructorDecl>(FD) &&
|
2009-12-03 08:03:05 +08:00
|
|
|
"No such thing as a covariant thunk for a destructor!");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-21 17:12:13 +08:00
|
|
|
// <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
|
|
|
|
// # base is the nominal target function of thunk
|
|
|
|
// # first call-offset is 'this' adjustment
|
|
|
|
// # second call-offset is result adjustment
|
2009-11-21 17:06:22 +08:00
|
|
|
CXXNameMangler Mangler(*this, Res);
|
2009-11-21 17:12:13 +08:00
|
|
|
Mangler.getStream() << "_ZTc";
|
2009-11-26 11:09:37 +08:00
|
|
|
Mangler.mangleCallOffset(Adjustment.ThisAdjustment);
|
|
|
|
Mangler.mangleCallOffset(Adjustment.ReturnAdjustment);
|
2009-11-21 17:12:13 +08:00
|
|
|
Mangler.mangleFunctionEncoding(FD);
|
2009-11-21 17:06:10 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-21 17:06:10 +08:00
|
|
|
/// mangleGuardVariable - Returns the mangled name for a guard variable
|
|
|
|
/// for the passed in VarDecl.
|
|
|
|
void MangleContext::mangleGuardVariable(const VarDecl *D,
|
2009-11-21 17:06:22 +08:00
|
|
|
llvm::SmallVectorImpl<char> &Res) {
|
2009-11-21 17:12:13 +08:00
|
|
|
// <special-name> ::= GV <object name> # Guard variable for one-time
|
|
|
|
// # initialization
|
2009-11-21 17:06:22 +08:00
|
|
|
CXXNameMangler Mangler(*this, Res);
|
2009-11-21 17:12:13 +08:00
|
|
|
Mangler.getStream() << "_ZGV";
|
|
|
|
Mangler.mangleName(D);
|
2009-11-21 17:06:10 +08:00
|
|
|
}
|
2009-08-01 07:15:31 +08:00
|
|
|
|
2009-11-21 17:06:10 +08:00
|
|
|
void MangleContext::mangleCXXVtable(const CXXRecordDecl *RD,
|
2009-11-21 17:06:22 +08:00
|
|
|
llvm::SmallVectorImpl<char> &Res) {
|
2009-11-21 17:12:13 +08:00
|
|
|
// <special-name> ::= TV <type> # virtual table
|
2009-11-21 17:06:22 +08:00
|
|
|
CXXNameMangler Mangler(*this, Res);
|
2009-11-21 17:12:13 +08:00
|
|
|
Mangler.getStream() << "_ZTV";
|
|
|
|
Mangler.mangleName(RD);
|
2009-11-21 17:06:10 +08:00
|
|
|
}
|
2009-11-10 09:58:37 +08:00
|
|
|
|
2009-11-21 17:06:10 +08:00
|
|
|
void MangleContext::mangleCXXVTT(const CXXRecordDecl *RD,
|
2009-11-21 17:06:22 +08:00
|
|
|
llvm::SmallVectorImpl<char> &Res) {
|
2009-11-21 17:12:13 +08:00
|
|
|
// <special-name> ::= TT <type> # VTT structure
|
2009-11-21 17:06:22 +08:00
|
|
|
CXXNameMangler Mangler(*this, Res);
|
2009-11-21 17:12:13 +08:00
|
|
|
Mangler.getStream() << "_ZTT";
|
|
|
|
Mangler.mangleName(RD);
|
2009-11-21 17:06:10 +08:00
|
|
|
}
|
2009-11-10 09:41:59 +08:00
|
|
|
|
2009-11-21 17:06:10 +08:00
|
|
|
void MangleContext::mangleCXXCtorVtable(const CXXRecordDecl *RD, int64_t Offset,
|
|
|
|
const CXXRecordDecl *Type,
|
2009-11-21 17:06:22 +08:00
|
|
|
llvm::SmallVectorImpl<char> &Res) {
|
2009-11-21 17:12:13 +08:00
|
|
|
// <special-name> ::= TC <type> <offset number> _ <base type>
|
2009-11-21 17:06:22 +08:00
|
|
|
CXXNameMangler Mangler(*this, Res);
|
2009-11-21 17:12:13 +08:00
|
|
|
Mangler.getStream() << "_ZTC";
|
|
|
|
Mangler.mangleName(RD);
|
|
|
|
Mangler.getStream() << Offset;
|
|
|
|
Mangler.getStream() << "_";
|
|
|
|
Mangler.mangleName(Type);
|
2009-11-21 17:06:10 +08:00
|
|
|
}
|
2009-11-14 08:14:13 +08:00
|
|
|
|
2009-12-03 02:57:08 +08:00
|
|
|
void MangleContext::mangleCXXRTTI(QualType Ty,
|
2009-11-21 17:06:22 +08:00
|
|
|
llvm::SmallVectorImpl<char> &Res) {
|
2009-11-21 17:12:13 +08:00
|
|
|
// <special-name> ::= TI <type> # typeinfo structure
|
2009-12-24 06:04:40 +08:00
|
|
|
assert(!Ty.hasQualifiers() && "RTTI info cannot have top-level qualifiers");
|
2009-11-21 17:06:22 +08:00
|
|
|
CXXNameMangler Mangler(*this, Res);
|
2009-11-21 17:12:13 +08:00
|
|
|
Mangler.getStream() << "_ZTI";
|
|
|
|
Mangler.mangleType(Ty);
|
2009-11-21 17:06:10 +08:00
|
|
|
}
|
|
|
|
|
2009-12-03 02:57:08 +08:00
|
|
|
void MangleContext::mangleCXXRTTIName(QualType Ty,
|
2009-11-21 17:06:22 +08:00
|
|
|
llvm::SmallVectorImpl<char> &Res) {
|
2009-11-21 17:12:13 +08:00
|
|
|
// <special-name> ::= TS <type> # typeinfo name (null terminated byte string)
|
2009-11-21 17:06:22 +08:00
|
|
|
CXXNameMangler Mangler(*this, Res);
|
2009-11-21 17:12:13 +08:00
|
|
|
Mangler.getStream() << "_ZTS";
|
|
|
|
Mangler.mangleType(Ty);
|
2009-08-01 02:25:34 +08:00
|
|
|
}
|