зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
2ecc28a772
Коммит
d3d49bb27c
|
@ -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_.
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче