]> granicus.if.org Git - clang/commitdiff
Fix the mangling of template template arguments, which do not always
authorJohn McCall <rjmccall@apple.com>
Wed, 14 Jul 2010 06:43:17 +0000 (06:43 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 14 Jul 2010 06:43:17 +0000 (06:43 +0000)
follow <name>;  instead they follow <type>, which has <name> as a subset.

Fixes PR7446.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108326 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/Mangle.cpp
test/CodeGenCXX/mangle.cpp

index 41178c2a24d5ce699fe8d3f1819bd8bc23f28cbc..30ee541c00fa03780f34a869396af9c7d431bc6d 100644 (file)
@@ -232,6 +232,7 @@ private:
 #include "clang/AST/TypeNodes.def"
 
   void mangleType(const TagType*);
+  void mangleType(TemplateName);
   void mangleBareFunctionType(const FunctionType *T,
                               bool MangleReturnType);
 
@@ -956,6 +957,53 @@ void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND) {
   addSubstitution(ND);
 }
 
+/// Mangles a template name under the production <type>.  Required for
+/// template template arguments.
+///   <type> ::= <class-enum-type>
+///          ::= <template-param>
+///          ::= <substitution>
+void CXXNameMangler::mangleType(TemplateName TN) {
+  if (mangleSubstitution(TN))
+    return;
+      
+  TemplateDecl *TD = 0;
+
+  switch (TN.getKind()) {
+  case TemplateName::QualifiedTemplate:
+    TD = TN.getAsQualifiedTemplateName()->getTemplateDecl();
+    goto HaveDecl;
+
+  case TemplateName::Template:
+    TD = TN.getAsTemplateDecl();
+    goto HaveDecl;
+
+  HaveDecl:
+    if (isa<TemplateTemplateParmDecl>(TD))
+      mangleTemplateParameter(cast<TemplateTemplateParmDecl>(TD)->getIndex());
+    else
+      mangleName(TD);
+    break;
+
+  case TemplateName::OverloadedTemplate:
+    llvm_unreachable("can't mangle an overloaded template name as a <type>");
+    break;
+
+  case TemplateName::DependentTemplate: {
+    const DependentTemplateName *Dependent = TN.getAsDependentTemplateName();
+    assert(Dependent->isIdentifier());
+
+    // <class-enum-type> ::= <name>
+    // <name> ::= <nested-name>
+    mangleUnresolvedScope(Dependent->getQualifier());
+    mangleSourceName(Dependent->getIdentifier());
+    break;
+  }
+
+  }
+
+  addSubstitution(TN);
+}
+
 void
 CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
   switch (OO) {
@@ -2034,9 +2082,8 @@ void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
     mangleType(A.getAsType());
     break;
   case TemplateArgument::Template:
-    assert(A.getAsTemplate().getAsTemplateDecl() &&
-           "Can't get dependent template names here");
-    mangleName(A.getAsTemplate().getAsTemplateDecl());
+    // This is mangled as <type>.
+    mangleType(A.getAsTemplate());
     break;
   case TemplateArgument::Expression:
     Out << 'X';
index 54a4060352e0a732a60dc563c757553ed5cb75e6..814a7592fad0157a17beeb3539d8671fb2a7cc98 100644 (file)
@@ -495,4 +495,15 @@ namespace test12 {
   // CHECK: _ZN6test121fENS_1AILt33000EEE
   template <unsigned short> struct A { };
   void f(A<33000>) { }
-}
\ No newline at end of file
+}
+
+// PR7446
+namespace test13 {
+  template <template <class> class T> class A {};
+  template <class U> class B {};
+
+  template <template<class> class T> void foo(const A<T> &a) {}
+
+  // CHECK: define weak_odr void @_ZN6test133fooINS_1BEEEvRKNS_1AIT_EE(
+  template void foo(const A<B> &a);
+}