зеркало из https://github.com/microsoft/clang.git
Add mangling support for calls, sizeof/alignof, constructor calls,
float literals, and unresolved lookups (which required hand-wavey extensions). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95273 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
40c37e1a62
Коммит
1dd7383dc4
|
@ -1602,11 +1602,24 @@ public:
|
|||
arg_iterator arg_begin() { return reinterpret_cast<Expr**>(this + 1); }
|
||||
arg_iterator arg_end() { return arg_begin() + NumArgs; }
|
||||
|
||||
typedef const Expr* const * const_arg_iterator;
|
||||
const_arg_iterator arg_begin() const {
|
||||
return reinterpret_cast<const Expr* const *>(this + 1);
|
||||
}
|
||||
const_arg_iterator arg_end() const {
|
||||
return arg_begin() + NumArgs;
|
||||
}
|
||||
|
||||
Expr *getArg(unsigned I) {
|
||||
assert(I < NumArgs && "Argument index out-of-range");
|
||||
return *(arg_begin() + I);
|
||||
}
|
||||
|
||||
const Expr *getArg(unsigned I) const {
|
||||
assert(I < NumArgs && "Argument index out-of-range");
|
||||
return *(arg_begin() + I);
|
||||
}
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(TyBeginLoc, RParenLoc);
|
||||
}
|
||||
|
|
|
@ -44,6 +44,8 @@ static const CXXMethodDecl *getStructor(const CXXMethodDecl *MD) {
|
|||
|
||||
return MD;
|
||||
}
|
||||
|
||||
static const unsigned UnknownArity = ~0U;
|
||||
|
||||
/// CXXNameMangler - Manage the mangling of a single name.
|
||||
class CXXNameMangler {
|
||||
|
@ -55,6 +57,8 @@ class CXXNameMangler {
|
|||
|
||||
llvm::DenseMap<uintptr_t, unsigned> Substitutions;
|
||||
|
||||
ASTContext &getASTContext() const { return Context.getASTContext(); }
|
||||
|
||||
public:
|
||||
CXXNameMangler(MangleContext &C, llvm::SmallVectorImpl<char> &Res)
|
||||
: Context(C), Out(Res), Structor(0), StructorType(0) { }
|
||||
|
@ -89,10 +93,19 @@ private:
|
|||
void addSubstitution(QualType T);
|
||||
void addSubstitution(uintptr_t Ptr);
|
||||
|
||||
void mangleUnresolvedScope(NestedNameSpecifier *Qualifier);
|
||||
void mangleUnresolvedName(NestedNameSpecifier *Qualifier,
|
||||
DeclarationName Name,
|
||||
unsigned KnownArity = UnknownArity);
|
||||
|
||||
void mangleName(const TemplateDecl *TD,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
unsigned NumTemplateArgs);
|
||||
void mangleUnqualifiedName(const NamedDecl *ND);
|
||||
void mangleUnqualifiedName(const NamedDecl *ND) {
|
||||
mangleUnqualifiedName(ND, ND->getDeclName(), UnknownArity);
|
||||
}
|
||||
void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name,
|
||||
unsigned KnownArity);
|
||||
void mangleUnscopedName(const NamedDecl *ND);
|
||||
void mangleUnscopedTemplateName(const TemplateDecl *ND);
|
||||
void mangleSourceName(const IdentifierInfo *II);
|
||||
|
@ -119,6 +132,7 @@ private:
|
|||
bool MangleReturnType);
|
||||
|
||||
void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value);
|
||||
void mangleCalledExpression(const Expr *E, unsigned KnownArity);
|
||||
void mangleExpression(const Expr *E);
|
||||
void mangleCXXCtorType(CXXCtorType T);
|
||||
void mangleCXXDtorType(CXXDtorType T);
|
||||
|
@ -398,28 +412,50 @@ void CXXNameMangler::mangleCallOffset(const ThunkAdjustment &Adjustment) {
|
|||
Out << '_';
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
|
||||
void CXXNameMangler::mangleUnresolvedScope(NestedNameSpecifier *Qualifier) {
|
||||
Qualifier = getASTContext().getCanonicalNestedNameSpecifier(Qualifier);
|
||||
switch (Qualifier->getKind()) {
|
||||
case NestedNameSpecifier::Global:
|
||||
// nothing
|
||||
break;
|
||||
case NestedNameSpecifier::Namespace:
|
||||
mangleName(Qualifier->getAsNamespace());
|
||||
break;
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
mangleType(QualType(Qualifier->getAsType(), 0));
|
||||
break;
|
||||
case NestedNameSpecifier::Identifier:
|
||||
mangleUnresolvedScope(Qualifier->getPrefix());
|
||||
mangleSourceName(Qualifier->getAsIdentifier());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// Mangles a name which was not resolved to a specific entity.
|
||||
void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *Qualifier,
|
||||
DeclarationName Name,
|
||||
unsigned KnownArity) {
|
||||
if (Qualifier)
|
||||
mangleUnresolvedScope(Qualifier);
|
||||
// FIXME: ambiguity of unqualified lookup with ::
|
||||
|
||||
mangleUnqualifiedName(0, Name, KnownArity);
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
|
||||
DeclarationName Name,
|
||||
unsigned KnownArity) {
|
||||
// <unqualified-name> ::= <operator-name>
|
||||
// ::= <ctor-dtor-name>
|
||||
// ::= <source-name>
|
||||
DeclarationName Name = ND->getDeclName();
|
||||
switch (Name.getNameKind()) {
|
||||
case DeclarationName::Identifier: {
|
||||
if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
|
||||
// We must avoid conflicts between internally- and externally-
|
||||
// linked names in the same TU. This naming convention is the
|
||||
// same as that followed by GCC, though it shouldn't actually matter.
|
||||
if (ND->getLinkage() == InternalLinkage &&
|
||||
if (ND && ND->getLinkage() == InternalLinkage &&
|
||||
ND->getDeclContext()->isFileContext())
|
||||
Out << 'L';
|
||||
|
||||
|
@ -427,6 +463,17 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
|
|||
break;
|
||||
}
|
||||
|
||||
// Otherwise, an anonymous entity. We must have a declaration.
|
||||
assert(ND && "mangling empty name without declaration");
|
||||
|
||||
if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
|
||||
if (NS->isAnonymousNamespace()) {
|
||||
// This is how gcc mangles these names.
|
||||
Out << "12_GLOBAL__N_1";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We must have an anonymous struct.
|
||||
const TagDecl *TD = cast<TagDecl>(ND);
|
||||
if (const TypedefDecl *D = TD->getTypedefForAnonDecl()) {
|
||||
|
@ -488,13 +535,18 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
|
|||
break;
|
||||
|
||||
case DeclarationName::CXXOperatorName: {
|
||||
unsigned Arity = cast<FunctionDecl>(ND)->getNumParams();
|
||||
unsigned Arity;
|
||||
if (ND) {
|
||||
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++;
|
||||
// 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++;
|
||||
} else
|
||||
Arity = KnownArity;
|
||||
|
||||
mangleOperatorName(Name.getCXXOverloadedOperator(), Arity);
|
||||
break;
|
||||
}
|
||||
|
@ -1053,6 +1105,19 @@ void CXXNameMangler::mangleIntegerLiteral(QualType T,
|
|||
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleCalledExpression(const Expr *E, unsigned Arity) {
|
||||
if (E->getType() != getASTContext().OverloadTy)
|
||||
mangleExpression(E);
|
||||
|
||||
llvm::PointerIntPair<OverloadExpr*,1> R
|
||||
= OverloadExpr::find(const_cast<Expr*>(E));
|
||||
if (R.getInt())
|
||||
Out << "an"; // &
|
||||
const OverloadExpr *Ovl = R.getPointer();
|
||||
|
||||
mangleUnresolvedName(Ovl->getQualifier(), Ovl->getName(), Arity);
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleExpression(const Expr *E) {
|
||||
// <expression> ::= <unary operator-name> <expression>
|
||||
// ::= <binary operator-name> <expression> <expression>
|
||||
|
@ -1068,25 +1133,68 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
|
|||
// ::= sr <type> <unqualified-name> <template-args> # dependent template-id
|
||||
// ::= sZ <template-param> # size of a parameter pack
|
||||
// ::= <expr-primary>
|
||||
// <expr-primary> ::= L <type> <value number> E # integer literal
|
||||
// ::= L <type <value float> E # floating literal
|
||||
// ::= L <mangled-name> E # external name
|
||||
switch (E->getStmtClass()) {
|
||||
default:
|
||||
llvm_unreachable("unexpected statement kind");
|
||||
break;
|
||||
|
||||
case Expr::CallExprClass:
|
||||
// FIXME: implement
|
||||
llvm_unreachable("mangling not implemented for calls");
|
||||
case Expr::CallExprClass: {
|
||||
const CallExpr *CE = cast<CallExpr>(E);
|
||||
Out << "cl";
|
||||
mangleCalledExpression(CE->getCallee(), CE->getNumArgs());
|
||||
for (unsigned I = 0, N = CE->getNumArgs(); I != N; ++I)
|
||||
mangleExpression(CE->getArg(I));
|
||||
Out << "E";
|
||||
break;
|
||||
}
|
||||
|
||||
case Expr::CXXConstructExprClass:
|
||||
// FIXME: implement
|
||||
llvm_unreachable("mangling not implemented for construct exprs");
|
||||
case Expr::UnresolvedLookupExprClass: {
|
||||
const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
|
||||
mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), UnknownArity);
|
||||
break;
|
||||
}
|
||||
|
||||
case Expr::CXXUnresolvedConstructExprClass: {
|
||||
const CXXUnresolvedConstructExpr *CE = cast<CXXUnresolvedConstructExpr>(E);
|
||||
unsigned N = CE->arg_size();
|
||||
|
||||
Out << "cv";
|
||||
mangleType(CE->getType());
|
||||
if (N != 1) Out << "_";
|
||||
for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I));
|
||||
if (N != 1) Out << "E";
|
||||
break;
|
||||
}
|
||||
|
||||
case Expr::SizeOfAlignOfExprClass:
|
||||
// FIXME: implement
|
||||
llvm_unreachable("mangling not implemented for sizeof/alignof");
|
||||
case Expr::CXXTemporaryObjectExprClass:
|
||||
case Expr::CXXConstructExprClass: {
|
||||
const CXXConstructExpr *CE = cast<CXXConstructExpr>(E);
|
||||
unsigned N = CE->getNumArgs();
|
||||
|
||||
Out << "cv";
|
||||
mangleType(CE->getType());
|
||||
if (N != 1) Out << "_";
|
||||
for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I));
|
||||
if (N != 1) Out << "E";
|
||||
break;
|
||||
}
|
||||
|
||||
case Expr::SizeOfAlignOfExprClass: {
|
||||
const SizeOfAlignOfExpr *SAE = cast<SizeOfAlignOfExpr>(E);
|
||||
if (SAE->isSizeOf()) Out << "s";
|
||||
else Out << "a";
|
||||
if (SAE->isArgumentType()) {
|
||||
Out << "t";
|
||||
mangleType(SAE->getArgumentType());
|
||||
} else {
|
||||
Out << "z";
|
||||
mangleExpression(SAE->getArgumentExpr());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Expr::UnaryOperatorClass: {
|
||||
const UnaryOperator *UO = cast<UnaryOperator>(E);
|
||||
|
@ -1178,6 +1286,20 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
|
|||
break;
|
||||
}
|
||||
|
||||
case Expr::FloatingLiteralClass: {
|
||||
const FloatingLiteral *FL = cast<FloatingLiteral>(E);
|
||||
Out << "L";
|
||||
mangleType(FL->getType());
|
||||
|
||||
// TODO: avoid this copy with careful stream management.
|
||||
llvm::SmallVector<char,20> Buffer;
|
||||
FL->getValue().bitcastToAPInt().toString(Buffer, 16, false);
|
||||
Out.write(Buffer.data(), Buffer.size());
|
||||
|
||||
Out << "E";
|
||||
break;
|
||||
}
|
||||
|
||||
case Expr::IntegerLiteralClass:
|
||||
mangleIntegerLiteral(E->getType(),
|
||||
llvm::APSInt(cast<IntegerLiteral>(E)->getValue()));
|
||||
|
|
|
@ -322,3 +322,38 @@ static int pr5966_i;
|
|||
void pr5966_bar() {
|
||||
pr5966_i = 0;
|
||||
}
|
||||
|
||||
namespace test0 {
|
||||
int ovl(int x);
|
||||
char ovl(double x);
|
||||
|
||||
template <class T> void f(T, char (&buffer)[sizeof(ovl(T()))]) {}
|
||||
|
||||
void test0() {
|
||||
char buffer[1];
|
||||
f(0.0, buffer);
|
||||
}
|
||||
// CHECK: define void @_ZN5test05test0Ev()
|
||||
// CHECK: define linkonce_odr void @_ZN5test01fIdEEvT_RAszcl3ovlcvS1__EE_c(
|
||||
|
||||
void test1() {
|
||||
char buffer[sizeof(int)];
|
||||
f(1, buffer);
|
||||
}
|
||||
// CHECK: define void @_ZN5test05test1Ev()
|
||||
// CHECK: define linkonce_odr void @_ZN5test01fIiEEvT_RAszcl3ovlcvS1__EE_c(
|
||||
|
||||
template <class T> void g(char (&buffer)[sizeof(T() + 5.0f)]) {}
|
||||
void test2() {
|
||||
char buffer[sizeof(float)];
|
||||
g<float>(buffer);
|
||||
}
|
||||
// CHECK: define linkonce_odr void @_ZN5test01gIfEEvRAszplcvT__ELf40A00000E_c(
|
||||
|
||||
template <class T> void h(char (&buffer)[sizeof(T() + 5.0)]) {}
|
||||
void test3() {
|
||||
char buffer[sizeof(double)];
|
||||
h<float>(buffer);
|
||||
}
|
||||
// CHECK: define linkonce_odr void @_ZN5test01hIfEEvRAszplcvT__ELd4014000000000000E_c(
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче