aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Type.h7
-rw-r--r--lib/AST/ItaniumMangle.cpp66
-rw-r--r--lib/AST/Type.cpp20
-rw-r--r--test/CodeGenCXX/mangle.cpp9
4 files changed, 87 insertions, 15 deletions
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index d8a92272c8..ef0dbdae03 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -757,6 +757,13 @@ public:
return getSplitDesugaredType(*this);
}
+ /// \brief Return the specified type with one level of "sugar" removed from
+ /// the type.
+ ///
+ /// This routine takes off the first typedef, typeof, etc. If the outer level
+ /// of the type is already concrete, it returns it unmodified.
+ QualType getSingleStepDesugaredType(const ASTContext &Context) const;
+
/// IgnoreParens - Returns the specified type after dropping any
/// outer-level parentheses.
QualType IgnoreParens() const {
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 5b247f2cdd..b07e962871 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -319,7 +319,7 @@ private:
unsigned NumTemplateArgs);
void mangleTemplateArgs(const TemplateParameterList &PL,
const TemplateArgumentList &AL);
- void mangleTemplateArg(const NamedDecl *P, const TemplateArgument &A);
+ void mangleTemplateArg(const NamedDecl *P, TemplateArgument A);
void mangleUnresolvedTemplateArgs(const TemplateArgument *args,
unsigned numArgs);
@@ -1596,26 +1596,59 @@ void CXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {
Context.mangleObjCMethodName(MD, Out);
}
-void CXXNameMangler::mangleType(QualType nonCanon) {
- // Only operate on the canonical type!
- QualType canon = nonCanon.getCanonicalType();
-
- SplitQualType split = canon.split();
+void CXXNameMangler::mangleType(QualType T) {
+ // If our type is instantiation-dependent but not dependent, we mangle
+ // it as it was written in the source, removing any top-level sugar.
+ // Otherwise, use the canonical type.
+ //
+ // FIXME: This is an approximation of the instantiation-dependent name
+ // mangling rules, since we should really be using the type as written and
+ // augmented via semantic analysis (i.e., with implicit conversions and
+ // default template arguments) for any instantiation-dependent type.
+ // Unfortunately, that requires several changes to our AST:
+ // - Instantiation-dependent TemplateSpecializationTypes will need to be
+ // uniqued, so that we can handle substitutions properly
+ // - Default template arguments will need to be represented in the
+ // TemplateSpecializationType, since they need to be mangled even though
+ // they aren't written.
+ // - Conversions on non-type template arguments need to be expressed, since
+ // they can affect the mangling of sizeof/alignof.
+ if (!T->isInstantiationDependentType() || T->isDependentType())
+ T = T.getCanonicalType();
+ else {
+ // Desugar any types that are purely sugar.
+ do {
+ // Don't desugar through template specialization types that aren't
+ // type aliases. We need to mangle the template arguments as written.
+ if (const TemplateSpecializationType *TST
+ = dyn_cast<TemplateSpecializationType>(T))
+ if (!TST->isTypeAlias())
+ break;
+
+ QualType Desugared
+ = T.getSingleStepDesugaredType(Context.getASTContext());
+ if (Desugared == T)
+ break;
+
+ T = Desugared;
+ } while (true);
+ }
+ SplitQualType split = T.split();
Qualifiers quals = split.second;
const Type *ty = split.first;
- bool isSubstitutable = quals || !isa<BuiltinType>(ty);
- if (isSubstitutable && mangleSubstitution(canon))
+ bool isSubstitutable = quals || !isa<BuiltinType>(T);
+ if (isSubstitutable && mangleSubstitution(T))
return;
// If we're mangling a qualified array type, push the qualifiers to
// the element type.
- if (quals && isa<ArrayType>(ty)) {
- ty = Context.getASTContext().getAsArrayType(canon);
+ if (quals && isa<ArrayType>(T)) {
+ ty = Context.getASTContext().getAsArrayType(T);
quals = Qualifiers();
- // Note that we don't update canon: we want to add the
- // substitution at the canonical type.
+ // Note that we don't update T: we want to add the
+ // substitution at the original type.
}
if (quals) {
@@ -1640,7 +1673,7 @@ void CXXNameMangler::mangleType(QualType nonCanon) {
// Add the substitution.
if (isSubstitutable)
- addSubstitution(canon);
+ addSubstitution(T);
}
void CXXNameMangler::mangleNameOrStandardSubstitution(const NamedDecl *ND) {
@@ -2826,12 +2859,15 @@ void CXXNameMangler::mangleTemplateArgs(const TemplateParameterList &PL,
}
void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
- const TemplateArgument &A) {
+ TemplateArgument A) {
// <template-arg> ::= <type> # type or template
// ::= X <expression> E # expression
// ::= <expr-primary> # simple expressions
// ::= J <template-arg>* E # argument pack
- // ::= sp <expression> # pack expansion of (C++0x)
+ // ::= sp <expression> # pack expansion of (C++0x)
+ if (!A.isInstantiationDependent() || A.isDependent())
+ A = Context.getASTContext().getCanonicalTemplateArgument(A);
+
switch (A.getKind()) {
case TemplateArgument::Null:
llvm_unreachable("Cannot mangle NULL template argument");
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 89c00eb850..1f0a37efac 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -180,6 +180,26 @@ QualType QualType::getDesugaredType(QualType T, const ASTContext &Context) {
return Context.getQualifiedType(split.first, split.second);
}
+QualType QualType::getSingleStepDesugaredType(const ASTContext &Context) const {
+ QualifierCollector Qs;
+
+ const Type *CurTy = Qs.strip(*this);
+ switch (CurTy->getTypeClass()) {
+#define ABSTRACT_TYPE(Class, Parent)
+#define TYPE(Class, Parent) \
+ case Type::Class: { \
+ const Class##Type *Ty = cast<Class##Type>(CurTy); \
+ if (!Ty->isSugared()) \
+ return *this; \
+ return Context.getQualifiedType(Ty->desugar(), Qs); \
+ break; \
+ }
+#include "clang/AST/TypeNodes.def"
+ }
+
+ return *this;
+}
+
SplitQualType QualType::getSplitDesugaredType(QualType T) {
QualifierCollector Qs;
diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp
index 0b3ba639af..453b7b713a 100644
--- a/test/CodeGenCXX/mangle.cpp
+++ b/test/CodeGenCXX/mangle.cpp
@@ -825,6 +825,15 @@ namespace test34 {
// CHECK: define weak_odr void @_ZN6test342f3ILy4EEEvRAplT_Ly8E_i
template void f3<4>(int (&)[4 + sizeof(int*)]);
+
+ // Mangling for instantiation-dependent sizeof() expressions as
+ // template arguments.
+ template<unsigned> struct A { };
+
+ template<typename T> void f4(::test34::A<sizeof(sizeof(decltype(T() + T())))>) { }
+
+ // CHECK: define weak_odr void @_ZN6test342f4IiEEvNS_1AIXszstDTplcvT__EcvS2__EEEEE
+ template void f4<int>(A<sizeof(sizeof(int))>);
}
namespace test35 {