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/Compiler.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2009-09-05 15:56:18 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2009-02-13 08:10:09 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
|
|
|
namespace {
|
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)
|
|
|
|
: Context(C), Out(Res), Structor(D), StructorType(Type) { }
|
|
|
|
CXXNameMangler(MangleContext &C, llvm::SmallVectorImpl<char> &Res,
|
|
|
|
const CXXDestructorDecl *D, CXXDtorType Type)
|
|
|
|
: Context(C), Out(Res), Structor(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:14:52 +08:00
|
|
|
void mangle(const NamedDecl *D);
|
2009-11-21 17:06:10 +08:00
|
|
|
void mangleCalloffset(int64_t nv, int64_t v);
|
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);
|
|
|
|
|
|
|
|
bool mangleFunctionDecl(const FunctionDecl *FD);
|
|
|
|
|
|
|
|
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);
|
|
|
|
void mangleNestedName(const NamedDecl *ND);
|
|
|
|
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);
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
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);
|
|
|
|
void mangleTemplateArgumentList(const TemplateArgumentList &L);
|
|
|
|
void mangleTemplateArgument(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;
|
|
|
|
|
|
|
|
// C functions, "main", and variables at global scope are not
|
|
|
|
// mangled.
|
|
|
|
if ((FD && FD->isMain()) ||
|
|
|
|
(!FD && D->getDeclContext()->isTranslationUnit()) ||
|
|
|
|
isInCLinkageSpecification(D))
|
|
|
|
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:14:52 +08:00
|
|
|
void CXXNameMangler::mangle(const NamedDecl *D) {
|
|
|
|
assert(Context.shouldMangleDeclName(D) && "Invalid mangle call!");
|
|
|
|
|
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:14:52 +08:00
|
|
|
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
|
|
|
// If we get here, mangle the decl name!
|
|
|
|
Out << "_Z";
|
|
|
|
mangleFunctionEncoding(FD);
|
|
|
|
} else {
|
|
|
|
const VarDecl *VD = cast<VarDecl>(D);
|
|
|
|
Out << "_Z";
|
|
|
|
mangleName(VD);
|
|
|
|
}
|
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-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-11-21 17:11:45 +08:00
|
|
|
static bool isStdNamespace(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-11-21 17:11:45 +08:00
|
|
|
static bool isStdNamespace(const DeclContext *DC) {
|
|
|
|
return DC->isNamespace() && DC->getParent()->isTranslationUnit() &&
|
|
|
|
isStdNamespace(cast<NamespaceDecl>(DC));
|
|
|
|
}
|
|
|
|
|
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-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);
|
|
|
|
mangleTemplateArgumentList(*TemplateArgs);
|
|
|
|
return;
|
2009-09-18 12:29:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
mangleUnscopedName(ND);
|
|
|
|
return;
|
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-18 12:29:09 +08:00
|
|
|
if (isa<FunctionDecl>(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-09-18 12:29:09 +08:00
|
|
|
mangleNestedName(ND);
|
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) {
|
|
|
|
const DeclContext *DC = TD->getDeclContext();
|
|
|
|
while (isa<LinkageSpecDecl>(DC)) {
|
2009-11-21 17:05:47 +08:00
|
|
|
assert(cast<LinkageSpecDecl>(DC)->getLanguage() ==
|
2009-09-18 10:42:01 +08:00
|
|
|
LinkageSpecDecl::lang_cxx && "Unexpected linkage decl!");
|
|
|
|
DC = DC->getParent();
|
|
|
|
}
|
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-09-05 15:20:32 +08:00
|
|
|
void CXXNameMangler::mangleCalloffset(int64_t nv, int64_t v) {
|
2009-09-02 08:25:38 +08:00
|
|
|
// <call-offset> ::= h <nv-offset> _
|
|
|
|
// ::= v <v-offset> _
|
|
|
|
// <nv-offset> ::= <offset number> # non-virtual base override
|
|
|
|
// <v-offset> ::= <offset nubmer> _ <virtual offset number>
|
|
|
|
// # virtual base override, with vcall offset
|
2009-09-05 15:20:32 +08:00
|
|
|
if (v == 0) {
|
2009-09-02 08:56:18 +08:00
|
|
|
Out << "h";
|
2009-09-02 08:25:38 +08:00
|
|
|
if (nv < 0) {
|
|
|
|
Out << "n";
|
|
|
|
nv = -nv;
|
|
|
|
}
|
|
|
|
Out << nv;
|
|
|
|
} else {
|
2009-09-02 08:56:18 +08:00
|
|
|
Out << "v";
|
2009-09-02 08:25:38 +08:00
|
|
|
if (nv < 0) {
|
|
|
|
Out << "n";
|
|
|
|
nv = -nv;
|
|
|
|
}
|
|
|
|
Out << nv;
|
|
|
|
Out << "_";
|
|
|
|
if (v < 0) {
|
|
|
|
Out << "n";
|
|
|
|
v = -v;
|
|
|
|
}
|
|
|
|
Out << v;
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
|
|
|
|
case DeclarationName::CXXOperatorName:
|
|
|
|
mangleOperatorName(Name.getCXXOverloadedOperator(),
|
|
|
|
cast<FunctionDecl>(ND)->getNumParams());
|
|
|
|
break;
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleNestedName(const NamedDecl *ND) {
|
|
|
|
// <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);
|
|
|
|
mangleTemplateArgumentList(*TemplateArgs);
|
2009-09-18 12:29:09 +08:00
|
|
|
} else {
|
|
|
|
manglePrefix(ND->getDeclContext());
|
|
|
|
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';
|
|
|
|
mangleFunctionEncoding(cast<FunctionDecl>(ND->getDeclContext()));
|
|
|
|
Out << 'E';
|
|
|
|
mangleSourceName(ND->getIdentifier());
|
|
|
|
}
|
|
|
|
|
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>
|
|
|
|
// FIXME: We only handle mangling of namespaces and classes at the moment.
|
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);
|
|
|
|
mangleTemplateArgumentList(*TemplateArgs);
|
|
|
|
} 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 # +
|
|
|
|
case OO_Plus: Out << (Arity == 1? "ps" : "pl"); break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= ng # - (unary)
|
|
|
|
// ::= mi # -
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_Minus: Out << (Arity == 1? "ng" : "mi"); break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= ad # & (unary)
|
|
|
|
// ::= an # &
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_Amp: Out << (Arity == 1? "ad" : "an"); break;
|
2009-04-17 01:51:27 +08:00
|
|
|
// ::= de # * (unary)
|
|
|
|
// ::= ml # *
|
2009-02-13 08:10:09 +08:00
|
|
|
case OO_Star: 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;
|
|
|
|
// UNSUPPORTED: ::= qu # ?
|
|
|
|
|
2009-04-17 01:51:27 +08:00
|
|
|
case OO_None:
|
|
|
|
case OO_Conditional:
|
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
|
|
|
}
|
|
|
|
|
|
|
|
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: \
|
|
|
|
llvm::llvm_unreachable("can't mangle non-canonical type " #CLASS "Type"); \
|
|
|
|
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-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) {
|
|
|
|
llvm::llvm_unreachable("Can't mangle K&R function prototypes");
|
|
|
|
}
|
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-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-03-11 01:07:44 +08:00
|
|
|
if (!T->getDecl()->getIdentifier())
|
|
|
|
mangleName(T->getDecl()->getTypedefForAnonDecl());
|
|
|
|
else
|
|
|
|
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-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
|
|
|
|
|
|
|
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-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-09-17 13:31:47 +08:00
|
|
|
void CXXNameMangler::mangleTemplateArgumentList(const TemplateArgumentList &L) {
|
2009-05-16 00:09:15 +08:00
|
|
|
// <template-args> ::= I <template-arg>+ E
|
|
|
|
Out << "I";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-16 00:09:15 +08:00
|
|
|
for (unsigned i = 0, e = L.size(); i != e; ++i) {
|
|
|
|
const TemplateArgument &A = L[i];
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-17 13:31:47 +08:00
|
|
|
mangleTemplateArgument(A);
|
2009-05-16 00:09:15 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
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:05:47 +08:00
|
|
|
|
2009-09-18 10:42:01 +08:00
|
|
|
for (unsigned i = 0; i != NumTemplateArgs; ++i) {
|
|
|
|
mangleTemplateArgument(TemplateArgs[i]);
|
|
|
|
}
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-09-18 10:42:01 +08:00
|
|
|
Out << "E";
|
|
|
|
}
|
|
|
|
|
2009-09-17 13:31:47 +08:00
|
|
|
void CXXNameMangler::mangleTemplateArgument(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-09-21 09:21:10 +08:00
|
|
|
case TemplateArgument::Expression:
|
|
|
|
Out << 'X';
|
|
|
|
mangleExpression(A.getAsExpr());
|
|
|
|
Out << 'E';
|
|
|
|
break;
|
2009-05-16 00:09:15 +08:00
|
|
|
case TemplateArgument::Integral:
|
|
|
|
// <expr-primary> ::= L <type> <value number> E # integer literal
|
|
|
|
|
|
|
|
Out << 'L';
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-16 00:09:15 +08:00
|
|
|
mangleType(A.getIntegralType());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-16 00:09:15 +08:00
|
|
|
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);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-16 00:09:15 +08:00
|
|
|
Out << 'E';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-09-27 04:53:44 +08:00
|
|
|
bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
|
|
|
|
// <substitution> ::= St # ::std::
|
2009-11-15 16:09:41 +08:00
|
|
|
// FIXME: type_info == comes out as __ZNK3std9type_infoeqERKS0_ instead of
|
|
|
|
// __ZNKSt9type_infoeqERKS_
|
2009-09-27 07:10:05 +08:00
|
|
|
if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
|
2009-10-01 08:25:31 +08:00
|
|
|
if (isStdNamespace(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
|
|
|
|
|
|
|
// <substitution> ::= So # ::std::basic_ostream<char,
|
2009-10-09 01:20:26 +08:00
|
|
|
// ::std::char_traits<char> >
|
|
|
|
if (SD->getIdentifier()->isStr("basic_ostream")) {
|
|
|
|
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-10-09 01:20:26 +08:00
|
|
|
if (TemplateArgs.size() != 2)
|
|
|
|
return false;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-10-09 01:20:26 +08:00
|
|
|
if (!isCharType(TemplateArgs[0].getAsType()))
|
|
|
|
return false;
|
2009-11-21 17:05:47 +08:00
|
|
|
|
2009-10-09 01:20:26 +08:00
|
|
|
if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Out << "So";
|
|
|
|
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.
|
|
|
|
void MangleContext::mangleThunk(const FunctionDecl *FD, int64_t nv, int64_t v,
|
2009-11-21 17:06:22 +08:00
|
|
|
llvm::SmallVectorImpl<char> &Res) {
|
2009-11-21 17:06:10 +08:00
|
|
|
// FIXME: Hum, we might have to thunk these, fix.
|
|
|
|
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";
|
|
|
|
Mangler.mangleCalloffset(nv, v);
|
|
|
|
Mangler.mangleFunctionEncoding(FD);
|
2009-11-21 17:06:10 +08:00
|
|
|
}
|
2009-04-14 02:02:10 +08:00
|
|
|
|
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.
|
|
|
|
void MangleContext::mangleCovariantThunk(const FunctionDecl *FD, int64_t nv_t,
|
|
|
|
int64_t v_t, int64_t nv_r, int64_t v_r,
|
2009-11-21 17:06:22 +08:00
|
|
|
llvm::SmallVectorImpl<char> &Res) {
|
2009-11-21 17:06:10 +08:00
|
|
|
// FIXME: Hum, we might have to thunk these, fix.
|
|
|
|
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> ::= 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";
|
|
|
|
Mangler.mangleCalloffset(nv_t, v_t);
|
|
|
|
Mangler.mangleCalloffset(nv_r, v_r);
|
|
|
|
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-11-21 17:06:22 +08:00
|
|
|
void MangleContext::mangleCXXRtti(QualType Ty,
|
|
|
|
llvm::SmallVectorImpl<char> &Res) {
|
2009-11-21 17:12:13 +08:00
|
|
|
// <special-name> ::= TI <type> # typeinfo structure
|
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-11-21 17:06:22 +08:00
|
|
|
void MangleContext::mangleCXXRttiName(QualType Ty,
|
|
|
|
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
|
|
|
}
|