Be more thorough about mangling unresolved types.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134011 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
John McCall 2011-06-28 16:49:23 +00:00
Родитель 2ecc28a772
Коммит d3d49bb27c
3 изменённых файлов: 144 добавлений и 57 удалений

Просмотреть файл

@ -753,7 +753,7 @@ ASTContext::getTypeInfo(const Type *T) const {
#define NON_CANONICAL_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
#include "clang/AST/TypeNodes.def"
assert(false && "Should not see dependent types");
llvm_unreachable("Should not see dependent types");
break;
case Type::FunctionNoProto:

Просмотреть файл

@ -256,9 +256,6 @@ private:
DeclarationName name,
unsigned KnownArity = UnknownArity);
static bool isUnresolvedType(const Type *type);
void mangleUnresolvedType(const Type *type);
void mangleName(const TemplateDecl *TD,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs);
@ -703,31 +700,6 @@ void CXXNameMangler::manglePrefix(QualType type) {
}
}
/// Returns true if the given type, appearing within an
/// unresolved-name, should be mangled as an unresolved-type.
bool CXXNameMangler::isUnresolvedType(const Type *type) {
// <unresolved-type> ::= <template-param>
// ::= <decltype>
// ::= <template-template-param> <template-args>
// (this last is not official yet)
if (isa<TemplateTypeParmType>(type)) return true;
if (isa<DecltypeType>(type)) return true;
// typeof?
if (const TemplateSpecializationType *tst =
dyn_cast<TemplateSpecializationType>(type)) {
TemplateDecl *temp = tst->getTemplateName().getAsTemplateDecl();
if (temp && isa<TemplateTemplateParmDecl>(temp))
return true;
}
return false;
}
void CXXNameMangler::mangleUnresolvedType(const Type *type) {
// This seems to be do everything we want.
mangleType(QualType(type, 0));
}
/// Mangle everything prior to the base-unresolved-name in an unresolved-name.
///
/// \param firstQualifierLookup - the entity found by unqualified lookup
@ -795,45 +767,118 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
} else {
// Otherwise, all the cases want this.
Out << "sr";
if (isUnresolvedType(type)) {
// We only get here recursively if we're followed by identifiers.
if (recursive) Out << 'N';
mangleUnresolvedType(type);
// We never want to print 'E' directly after an unresolved-type,
// so we return directly.
return;
}
}
assert(!isUnresolvedType(type));
// Only certain other types are valid as prefixes; enumerate them.
// FIXME: can we get ElaboratedTypes here?
// FIXME: SubstTemplateTypeParmType?
if (const TagType *t = dyn_cast<TagType>(type)) {
mangleSourceName(t->getDecl()->getIdentifier());
} else if (const TypedefType *t = dyn_cast<TypedefType>(type)) {
mangleSourceName(t->getDecl()->getIdentifier());
} else if (const UnresolvedUsingType *t
= dyn_cast<UnresolvedUsingType>(type)) {
mangleSourceName(t->getDecl()->getIdentifier());
} else if (const DependentNameType *t
= dyn_cast<DependentNameType>(type)) {
mangleSourceName(t->getIdentifier());
} else if (const TemplateSpecializationType *tst
= dyn_cast<TemplateSpecializationType>(type)) {
switch (type->getTypeClass()) {
case Type::Builtin:
case Type::Complex:
case Type::Pointer:
case Type::BlockPointer:
case Type::LValueReference:
case Type::RValueReference:
case Type::MemberPointer:
case Type::ConstantArray:
case Type::IncompleteArray:
case Type::VariableArray:
case Type::DependentSizedArray:
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:
case Type::FunctionProto:
case Type::FunctionNoProto:
case Type::Enum:
case Type::Paren:
case Type::Elaborated:
case Type::Attributed:
case Type::Auto:
case Type::PackExpansion:
case Type::SubstTemplateTypeParmPack:
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
llvm_unreachable("type is illegal as a nested name specifier");
// <unresolved-type> ::= <template-param>
// ::= <decltype>
// ::= <template-template-param> <template-args>
// (this last is not official yet)
case Type::TypeOfExpr:
case Type::TypeOf:
case Type::Decltype:
case Type::TemplateTypeParm:
case Type::UnaryTransform:
unresolvedType:
assert(!qualifier->getPrefix());
// We only get here recursively if we're followed by identifiers.
if (recursive) Out << 'N';
// This seems to do everything we want.
mangleType(QualType(type, 0));
// We never want to print 'E' directly after an unresolved-type,
// so we return directly.
return;
// Substituted template type parameters should only come up with
// enclosing templates.
// <unresolved-type> ::= <existing-substitution> [ <template-args> ]
case Type::SubstTemplateTypeParm: {
if (recursive) Out << 'N';
bool wasSubstituted = mangleSubstitution(QualType(type, 0));
assert(wasSubstituted && "no substitution for outer template argument?");
(void) wasSubstituted;
return;
}
case Type::Typedef:
mangleSourceName(cast<TypedefType>(type)->getDecl()->getIdentifier());
break;
case Type::UnresolvedUsing:
mangleSourceName(cast<UnresolvedUsingType>(type)->getDecl()
->getIdentifier());
break;
case Type::Record:
mangleSourceName(cast<RecordType>(type)->getDecl()->getIdentifier());
break;
case Type::TemplateSpecialization: {
const TemplateSpecializationType *tst
= cast<TemplateSpecializationType>(type);
TemplateDecl *temp = tst->getTemplateName().getAsTemplateDecl();
// If the base is a template template parameter, this is an
// unresolved type.
assert(temp && "no template for template specialization type");
if (isa<TemplateTemplateParmDecl>(temp)) goto unresolvedType;
mangleSourceName(temp->getIdentifier());
mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs());
} else if (const DependentTemplateSpecializationType *tst
= dyn_cast<DependentTemplateSpecializationType>(type)) {
break;
}
case Type::InjectedClassName:
mangleSourceName(cast<InjectedClassNameType>(type)->getDecl()
->getIdentifier());
break;
case Type::DependentName:
mangleSourceName(cast<DependentNameType>(type)->getIdentifier());
break;
case Type::DependentTemplateSpecialization: {
const DependentTemplateSpecializationType *tst
= cast<DependentTemplateSpecializationType>(type);
mangleSourceName(tst->getIdentifier());
mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs());
} else {
llvm_unreachable("unexpected type in nested name specifier!");
break;
}
}
break;
}

Просмотреть файл

@ -711,3 +711,45 @@ namespace test27 {
b<A>(f);
}
}
// An injected class name type in a unresolved-name.
namespace test28 {
template <class T> struct A {
enum { bit };
};
template <class T> void foo(decltype(A<T>::A::bit) x);
void test() {
foo<char>(A<char>::bit);
// CHECK: call void @_ZN6test283fooIcEEvDtsr1AIT_E1AE3bitE(
}
}
// An enclosing template type parameter in an unresolved-name.
namespace test29 {
template <class T> struct A {
template <class U> static void foo(decltype(T::fn(U())) x);
};
struct B { static int fn(int); static long fn(long); };
void test() {
A<B>::foo<int>(0);
// CHECK: call void @_ZN6test291AINS_1BEE3fooIiEEvDTclsrS1_2fncvT__EEE(
}
}
// An enclosing template template parameter in an unresolved-name.
namespace test30 {
template <template <class> class T> struct A {
template <class U> static void foo(decltype(T<U>::fn()) x);
};
template <class T> struct B { static T fn(); };
void test() {
A<B>::foo<int>(0);
// FIXME: it's not clear what this mangling should be; maybe this?
// call void @_ZN6test301AINS_1BEE3fooIiEEvDTclsrS1_IT_EE2fnEE(
// Currently it's 1B instead of S1_.
}
}