Update the mangler for some of the "new" unresolved-name manglings.

I've sent off an email requesting clarification on a few things that
I wasn't sure how to handle.

This also necessitated making prefixes and unresolved-prefixes get
mangled separately.

llvm-svn: 130083
This commit is contained in:
John McCall 2011-04-24 08:23:24 +00:00
parent 0e7dde535d
commit 6dc0a2b467
2 changed files with 223 additions and 91 deletions

View File

@ -200,11 +200,16 @@ private:
void addSubstitution(TemplateName Template);
void addSubstitution(uintptr_t Ptr);
void mangleUnresolvedScope(NestedNameSpecifier *Qualifier);
void mangleUnresolvedName(NestedNameSpecifier *Qualifier,
DeclarationName Name,
void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
bool recursive = false);
void mangleUnresolvedName(NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
DeclarationName name,
unsigned KnownArity = UnknownArity);
void mangleUnresolvedType(QualType type);
void mangleName(const TemplateDecl *TD,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs);
@ -223,6 +228,7 @@ private:
void mangleNestedName(const TemplateDecl *TD,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs);
void manglePrefix(NestedNameSpecifier *qualifier);
void manglePrefix(const DeclContext *DC, bool NoFunction=false);
void mangleTemplatePrefix(const TemplateDecl *ND);
void mangleTemplatePrefix(TemplateName Template);
@ -245,10 +251,11 @@ private:
void mangleNeonVectorType(const VectorType *T);
void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value);
void mangleMemberExpr(const Expr *Base, bool IsArrow,
NestedNameSpecifier *Qualifier,
DeclarationName Name,
unsigned KnownArity);
void mangleMemberExpr(const Expr *base, bool isArrow,
NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
DeclarationName name,
unsigned knownArity);
void mangleExpression(const Expr *E, unsigned Arity = UnknownArity);
void mangleCXXCtorType(CXXCtorType T);
void mangleCXXDtorType(CXXDtorType T);
@ -611,70 +618,162 @@ void CXXNameMangler::mangleCallOffset(int64_t NonVirtual, int64_t Virtual) {
Out << '_';
}
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::NamespaceAlias:
mangleName(Qualifier->getAsNamespaceAlias()->getNamespace());
break;
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate: {
const Type *QTy = Qualifier->getAsType();
if (const TemplateSpecializationType *TST =
dyn_cast<TemplateSpecializationType>(QTy)) {
if (!mangleSubstitution(QualType(TST, 0))) {
mangleTemplatePrefix(TST->getTemplateName());
void CXXNameMangler::mangleUnresolvedType(QualType type) {
if (const TemplateSpecializationType *TST =
type->getAs<TemplateSpecializationType>()) {
if (!mangleSubstitution(QualType(TST, 0))) {
mangleTemplatePrefix(TST->getTemplateName());
// FIXME: GCC does not appear to mangle the template arguments when
// the template in question is a dependent template name. Should we
// emulate that badness?
mangleTemplateArgs(TST->getTemplateName(), TST->getArgs(),
TST->getNumArgs());
addSubstitution(QualType(TST, 0));
}
} else if (const DependentTemplateSpecializationType *DTST
= dyn_cast<DependentTemplateSpecializationType>(QTy)) {
TemplateName Template
= getASTContext().getDependentTemplateName(DTST->getQualifier(),
DTST->getIdentifier());
mangleTemplatePrefix(Template);
// FIXME: GCC does not appear to mangle the template arguments when
// the template in question is a dependent template name. Should we
// emulate that badness?
mangleTemplateArgs(Template, DTST->getArgs(), DTST->getNumArgs());
} else {
// We use the QualType mangle type variant here because it handles
// substitutions.
mangleType(QualType(QTy, 0));
mangleTemplateArgs(TST->getTemplateName(), TST->getArgs(),
TST->getNumArgs());
addSubstitution(QualType(TST, 0));
}
}
break;
case NestedNameSpecifier::Identifier:
// Member expressions can have these without prefixes.
if (Qualifier->getPrefix())
mangleUnresolvedScope(Qualifier->getPrefix());
mangleSourceName(Qualifier->getAsIdentifier());
break;
} else if (const DependentTemplateSpecializationType *DTST
= type->getAs<DependentTemplateSpecializationType>()) {
TemplateName Template
= getASTContext().getDependentTemplateName(DTST->getQualifier(),
DTST->getIdentifier());
mangleTemplatePrefix(Template);
// FIXME: GCC does not appear to mangle the template arguments when
// the template in question is a dependent template name. Should we
// emulate that badness?
mangleTemplateArgs(Template, DTST->getArgs(), DTST->getNumArgs());
} else {
// We use the QualType mangle type variant here because it handles
// substitutions.
mangleType(type);
}
}
/// 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 ::
/// Mangle everything prior to the base-unresolved-name in an unresolved-name.
///
/// \param firstQualifierLookup - the entity found by unqualified lookup
/// for the first name in the qualifier, if this is for a member expression
/// \param recursive - true if this is being called recursively,
/// i.e. if there is more prefix "to the right".
void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
bool recursive) {
mangleUnqualifiedName(0, Name, KnownArity);
// x, ::x
// <unresolved-name> ::= [gs] <base-unresolved-name>
// T::x / decltype(p)::x
// <unresolved-name> ::= sr <unresolved-type> <base-unresolved-name>
// T::N::x /decltype(p)::N::x
// <unresolved-name> ::= srN <unresolved-type> <unresolved-qualifier-level>+ E
// <base-unresolved-name>
// A::x, N::y, A<T>::z; "gs" means leading "::"
// <unresolved-name> ::= [gs] sr <unresolved-qualifier-level>+ E
// <base-unresolved-name>
switch (qualifier->getKind()) {
case NestedNameSpecifier::Global:
Out << "gs";
// We want an 'sr' unless this is the entire NNS.
if (recursive)
Out << "sr";
// We never want an 'E' here.
return;
case NestedNameSpecifier::Namespace:
if (qualifier->getPrefix())
mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
/*recursive*/ true);
else
Out << "sr";
mangleSourceName(qualifier->getAsNamespace()->getIdentifier());
break;
case NestedNameSpecifier::NamespaceAlias:
if (qualifier->getPrefix())
mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
/*recursive*/ true);
else
Out << "sr";
mangleSourceName(qualifier->getAsNamespaceAlias()->getIdentifier());
break;
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate: {
// Both cases want this.
Out << "sr";
// We only get here recursively if we're followed by identifiers.
if (recursive) Out << 'N';
mangleUnresolvedType(QualType(qualifier->getAsType(), 0));
// We never want to print 'E' directly after an unresolved-type,
// so we return directly.
return;
}
case NestedNameSpecifier::Identifier:
// Member expressions can have these without prefixes.
if (qualifier->getPrefix()) {
mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
/*recursive*/ true);
} else if (firstQualifierLookup) {
// Try to make a proper qualifier out of the lookup result, and
// then just recurse on that.
NestedNameSpecifier *newQualifier;
if (TypeDecl *typeDecl = dyn_cast<TypeDecl>(firstQualifierLookup)) {
QualType type = getASTContext().getTypeDeclType(typeDecl);
// Pretend we had a different nested name specifier.
newQualifier = NestedNameSpecifier::Create(getASTContext(),
/*prefix*/ 0,
/*template*/ false,
type.getTypePtr());
} else if (NamespaceDecl *nspace =
dyn_cast<NamespaceDecl>(firstQualifierLookup)) {
newQualifier = NestedNameSpecifier::Create(getASTContext(),
/*prefix*/ 0,
nspace);
} else if (NamespaceAliasDecl *alias =
dyn_cast<NamespaceAliasDecl>(firstQualifierLookup)) {
newQualifier = NestedNameSpecifier::Create(getASTContext(),
/*prefix*/ 0,
alias);
} else {
// No sensible mangling to do here.
newQualifier = 0;
}
if (newQualifier)
return mangleUnresolvedPrefix(newQualifier, /*lookup*/ 0, recursive);
} else {
Out << "sr";
}
mangleSourceName(qualifier->getAsIdentifier());
break;
}
// If this was the innermost part of the NNS, and we fell out to
// here, append an 'E'.
if (!recursive)
Out << 'E';
}
/// Mangle an unresolved-name, which is generally used for names which
/// weren't resolved to specific entities.
void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
DeclarationName name,
unsigned knownArity) {
if (qualifier) mangleUnresolvedPrefix(qualifier, firstQualifierLookup);
mangleUnqualifiedName(0, name, knownArity);
}
static const FieldDecl *FindFirstNamedDataMember(const RecordDecl *RD) {
@ -933,6 +1032,38 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) {
mangleUnqualifiedName(ND);
}
void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) {
switch (qualifier->getKind()) {
case NestedNameSpecifier::Global:
// nothing
return;
case NestedNameSpecifier::Namespace:
mangleName(qualifier->getAsNamespace());
return;
case NestedNameSpecifier::NamespaceAlias:
mangleName(qualifier->getAsNamespaceAlias()->getNamespace());
return;
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
mangleUnresolvedType(QualType(qualifier->getAsType(), 0));
return;
case NestedNameSpecifier::Identifier:
// Member expressions can have these without prefixes, but that
// should end up in mangleUnresolvedPrefix instead.
assert(qualifier->getPrefix());
manglePrefix(qualifier->getPrefix());
mangleSourceName(qualifier->getAsIdentifier());
return;
}
llvm_unreachable("unexpected nested name specifier");
}
void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
// <prefix> ::= <prefix> <unqualified-name>
// ::= <template-prefix> <template-args>
@ -986,7 +1117,7 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) {
return mangleTemplatePrefix(TD);
if (QualifiedTemplateName *Qualified = Template.getAsQualifiedTemplateName())
mangleUnresolvedScope(Qualified->getQualifier());
manglePrefix(Qualified->getQualifier());
if (OverloadedTemplateStorage *Overloaded
= Template.getAsOverloadedTemplate()) {
@ -997,7 +1128,7 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) {
DependentTemplateName *Dependent = Template.getAsDependentTemplateName();
assert(Dependent && "Unknown template name kind?");
mangleUnresolvedScope(Dependent->getQualifier());
manglePrefix(Dependent->getQualifier());
mangleUnscopedTemplateName(Template);
}
@ -1060,7 +1191,7 @@ void CXXNameMangler::mangleType(TemplateName TN) {
// <class-enum-type> ::= <name>
// <name> ::= <nested-name>
mangleUnresolvedScope(Dependent->getQualifier());
mangleUnresolvedPrefix(Dependent->getQualifier(), 0);
mangleSourceName(Dependent->getIdentifier());
break;
}
@ -1618,7 +1749,7 @@ void CXXNameMangler::mangleType(const TemplateSpecializationType *T) {
void CXXNameMangler::mangleType(const DependentNameType *T) {
// Typename types are always nested
Out << 'N';
mangleUnresolvedScope(T->getQualifier());
manglePrefix(T->getQualifier());
mangleSourceName(T->getIdentifier());
Out << 'E';
}
@ -1704,16 +1835,17 @@ void CXXNameMangler::mangleIntegerLiteral(QualType T,
/// Mangles a member expression. Implicit accesses are not handled,
/// but that should be okay, because you shouldn't be able to
/// make an implicit access in a function template declaration.
void CXXNameMangler::mangleMemberExpr(const Expr *Base,
bool IsArrow,
NestedNameSpecifier *Qualifier,
DeclarationName Member,
unsigned Arity) {
// gcc-4.4 uses 'dt' for dot expressions, which is reasonable.
// OTOH, gcc also mangles the name as an expression.
Out << (IsArrow ? "pt" : "dt");
mangleExpression(Base);
mangleUnresolvedName(Qualifier, Member, Arity);
void CXXNameMangler::mangleMemberExpr(const Expr *base,
bool isArrow,
NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
DeclarationName member,
unsigned arity) {
// <expression> ::= dt <expression> <unresolved-name>
// ::= pt <expression> <unresolved-name>
Out << (isArrow ? "pt" : "dt");
mangleExpression(base);
mangleUnresolvedName(qualifier, firstQualifierLookup, member, arity);
}
void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
@ -1844,7 +1976,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
case Expr::MemberExprClass: {
const MemberExpr *ME = cast<MemberExpr>(E);
mangleMemberExpr(ME->getBase(), ME->isArrow(),
ME->getQualifier(), ME->getMemberDecl()->getDeclName(),
ME->getQualifier(), 0, ME->getMemberDecl()->getDeclName(),
Arity);
break;
}
@ -1852,7 +1984,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
case Expr::UnresolvedMemberExprClass: {
const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E);
mangleMemberExpr(ME->getBase(), ME->isArrow(),
ME->getQualifier(), ME->getMemberName(),
ME->getQualifier(), 0, ME->getMemberName(),
Arity);
if (ME->hasExplicitTemplateArgs())
mangleTemplateArgs(ME->getExplicitTemplateArgs());
@ -1863,19 +1995,16 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
const CXXDependentScopeMemberExpr *ME
= cast<CXXDependentScopeMemberExpr>(E);
mangleMemberExpr(ME->getBase(), ME->isArrow(),
ME->getQualifier(), ME->getMember(),
Arity);
ME->getQualifier(), ME->getFirstQualifierFoundInScope(),
ME->getMember(), Arity);
if (ME->hasExplicitTemplateArgs())
mangleTemplateArgs(ME->getExplicitTemplateArgs());
break;
}
case Expr::UnresolvedLookupExprClass: {
// The ABI doesn't cover how to mangle overload sets, so we mangle
// using something as close as possible to the original lookup
// expression.
const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), Arity);
mangleUnresolvedName(ULE->getQualifier(), 0, ULE->getName(), Arity);
if (ULE->hasExplicitTemplateArgs())
mangleTemplateArgs(ULE->getExplicitTemplateArgs());
break;

View File

@ -390,26 +390,29 @@ namespace test2 {
// CHECK: define linkonce_odr i32 @_ZN5test211read_memberINS_1AEEEDtptcvPT_Li0E6memberERS2_(
}
// rdar://problem/9280586
namespace test3 {
struct AmbiguousBase { int ab; };
struct Path1 : AmbiguousBase { float p; };
struct Path2 : AmbiguousBase { double p; };
struct Derived : Path1, Path2 { };
//template <class T> decltype(((T*) 0)->Path1::ab) get_ab_1(T &ref) { return ref.Path1::ab; }
//template <class T> decltype(((T*) 0)->Path2::ab) get_ab_2(T &ref) { return ref.Path2::ab; }
// CHECK: define linkonce_odr i32 @_ZN5test38get_ab_1INS_7DerivedEEEDtptcvPT_Li0EsrNS_5Path1E2abERS2_(
template <class T> decltype(((T*) 0)->Path1::ab) get_ab_1(T &ref) { return ref.Path1::ab; }
// define weak_odr float @_ZN5test37get_p_1INS_7DerivedEEEDtptcvPT_Li0E5Path11pERS2_(
// CHECK: define linkonce_odr i32 @_ZN5test38get_ab_2INS_7DerivedEEEDtptcvPT_Li0EsrNS_5Path2E2abERS2_(
template <class T> decltype(((T*) 0)->Path2::ab) get_ab_2(T &ref) { return ref.Path2::ab; }
// CHECK: define linkonce_odr float @_ZN5test37get_p_1INS_7DerivedEEEDtptcvPT_Li0EsrNS_5Path1E1pERS2_(
template <class T> decltype(((T*) 0)->Path1::p) get_p_1(T &ref) { return ref.Path1::p; }
// define weak_odr double @_ZN5test37get_p_1INS_7DerivedEEEDtptcvPT_Li0E5Path21pERS2_(
// CHECK: define linkonce_odr double @_ZN5test37get_p_2INS_7DerivedEEEDtptcvPT_Li0EsrNS_5Path2E1pERS2_(
template <class T> decltype(((T*) 0)->Path2::p) get_p_2(T &ref) { return ref.Path2::p; }
Derived obj;
void test() {
// FIXME: uncomment these when we support diamonds competently
//get_ab_1(obj);
//get_ab_2(obj);
get_ab_1(obj);
get_ab_2(obj);
get_p_1(obj);
get_p_2(obj);
}