зеркало из 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 NON_CANONICAL_TYPE(Class, Base)
|
||||||
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
|
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
|
||||||
#include "clang/AST/TypeNodes.def"
|
#include "clang/AST/TypeNodes.def"
|
||||||
assert(false && "Should not see dependent types");
|
llvm_unreachable("Should not see dependent types");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Type::FunctionNoProto:
|
case Type::FunctionNoProto:
|
||||||
|
|
|
@ -256,9 +256,6 @@ private:
|
||||||
DeclarationName name,
|
DeclarationName name,
|
||||||
unsigned KnownArity = UnknownArity);
|
unsigned KnownArity = UnknownArity);
|
||||||
|
|
||||||
static bool isUnresolvedType(const Type *type);
|
|
||||||
void mangleUnresolvedType(const Type *type);
|
|
||||||
|
|
||||||
void mangleName(const TemplateDecl *TD,
|
void mangleName(const TemplateDecl *TD,
|
||||||
const TemplateArgument *TemplateArgs,
|
const TemplateArgument *TemplateArgs,
|
||||||
unsigned NumTemplateArgs);
|
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.
|
/// Mangle everything prior to the base-unresolved-name in an unresolved-name.
|
||||||
///
|
///
|
||||||
/// \param firstQualifierLookup - the entity found by unqualified lookup
|
/// \param firstQualifierLookup - the entity found by unqualified lookup
|
||||||
|
@ -795,45 +767,118 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, all the cases want this.
|
// Otherwise, all the cases want this.
|
||||||
Out << "sr";
|
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.
|
// Only certain other types are valid as prefixes; enumerate them.
|
||||||
// FIXME: can we get ElaboratedTypes here?
|
// FIXME: can we get ElaboratedTypes here?
|
||||||
// FIXME: SubstTemplateTypeParmType?
|
// FIXME: SubstTemplateTypeParmType?
|
||||||
if (const TagType *t = dyn_cast<TagType>(type)) {
|
switch (type->getTypeClass()) {
|
||||||
mangleSourceName(t->getDecl()->getIdentifier());
|
case Type::Builtin:
|
||||||
} else if (const TypedefType *t = dyn_cast<TypedefType>(type)) {
|
case Type::Complex:
|
||||||
mangleSourceName(t->getDecl()->getIdentifier());
|
case Type::Pointer:
|
||||||
} else if (const UnresolvedUsingType *t
|
case Type::BlockPointer:
|
||||||
= dyn_cast<UnresolvedUsingType>(type)) {
|
case Type::LValueReference:
|
||||||
mangleSourceName(t->getDecl()->getIdentifier());
|
case Type::RValueReference:
|
||||||
} else if (const DependentNameType *t
|
case Type::MemberPointer:
|
||||||
= dyn_cast<DependentNameType>(type)) {
|
case Type::ConstantArray:
|
||||||
mangleSourceName(t->getIdentifier());
|
case Type::IncompleteArray:
|
||||||
} else if (const TemplateSpecializationType *tst
|
case Type::VariableArray:
|
||||||
= dyn_cast<TemplateSpecializationType>(type)) {
|
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();
|
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");
|
assert(temp && "no template for template specialization type");
|
||||||
|
if (isa<TemplateTemplateParmDecl>(temp)) goto unresolvedType;
|
||||||
|
|
||||||
mangleSourceName(temp->getIdentifier());
|
mangleSourceName(temp->getIdentifier());
|
||||||
mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs());
|
mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs());
|
||||||
} else if (const DependentTemplateSpecializationType *tst
|
break;
|
||||||
= dyn_cast<DependentTemplateSpecializationType>(type)) {
|
}
|
||||||
|
|
||||||
|
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());
|
mangleSourceName(tst->getIdentifier());
|
||||||
mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs());
|
mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs());
|
||||||
} else {
|
break;
|
||||||
llvm_unreachable("unexpected type in nested name specifier!");
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -711,3 +711,45 @@ namespace test27 {
|
||||||
b<A>(f);
|
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_.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче