Change the mangling of enclosing template template parameters
that serve as the base template name of an unresolved-name to
be mangled as a substitution.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134213 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 9e647ad..205e887 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -237,6 +237,9 @@
   bool mangleSubstitution(TemplateName Template);
   bool mangleSubstitution(uintptr_t Ptr);
 
+  void mangleExistingSubstitution(QualType type);
+  void mangleExistingSubstitution(TemplateName name);
+
   bool mangleStandardSubstitution(const NamedDecl *ND);
 
   void addSubstitution(const NamedDecl *ND) {
@@ -770,8 +773,6 @@
     }
 
     // Only certain other types are valid as prefixes;  enumerate them.
-    // FIXME: can we get ElaboratedTypes here?
-    // FIXME: SubstTemplateTypeParmType?
     switch (type->getTypeClass()) {
     case Type::Builtin:
     case Type::Complex:
@@ -795,12 +796,19 @@
     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");
 
+    case Type::SubstTemplateTypeParmPack:
+      // FIXME: not clear how to mangle this!
+      // template <class T...> class A {
+      //   template <class U...> void foo(decltype(T::foo(U())) x...);
+      // };
+      Out << "_SUBSTPACK_";
+      break;
+
     // <unresolved-type> ::= <template-param>
     //                   ::= <decltype>
     //                   ::= <template-template-param> <template-args>
@@ -828,10 +836,7 @@
     // <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;
+      mangleExistingSubstitution(QualType(type, 0));
       return;
     }
 
@@ -851,14 +856,42 @@
     case Type::TemplateSpecialization: {
       const TemplateSpecializationType *tst
         = cast<TemplateSpecializationType>(type);
-      TemplateDecl *temp = tst->getTemplateName().getAsTemplateDecl();
+      TemplateName name = tst->getTemplateName();
+      switch (name.getKind()) {
+      case TemplateName::Template:
+      case TemplateName::QualifiedTemplate: {
+        TemplateDecl *temp = name.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;
+        // 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());
+        mangleSourceName(temp->getIdentifier());
+        break;
+      }
+
+      case TemplateName::OverloadedTemplate:
+      case TemplateName::DependentTemplate:
+        llvm_unreachable("invalid base for a template specialization type");
+
+      case TemplateName::SubstTemplateTemplateParm: {
+        SubstTemplateTemplateParmStorage *subst
+          = name.getAsSubstTemplateTemplateParm();
+        mangleExistingSubstitution(subst->getReplacement());
+        break;
+      }
+
+      case TemplateName::SubstTemplateTemplateParmPack: {
+        // FIXME: not clear how to mangle this!
+        // template <template <class U> class T...> class A {
+        //   template <class U...> void foo(decltype(T<U>::foo) x...);
+        // };
+        Out << "_SUBSTPACK_";
+        break;
+      }
+      }
+
       mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs());
       break;
     }
@@ -1381,9 +1414,11 @@
   }
 
   case TemplateName::SubstTemplateTemplateParmPack: {
-    SubstTemplateTemplateParmPackStorage *SubstPack
-      = TN.getAsSubstTemplateTemplateParmPack();
-    mangleTemplateParameter(SubstPack->getParameterPack()->getIndex());
+    // FIXME: not clear how to mangle this!
+    // template <template <class> class T...> class A {
+    //   template <template <class> class U...> void foo(B<T,U> x...);
+    // };
+    Out << "_SUBSTPACK_";
     break;
   }
   }
@@ -1827,7 +1862,11 @@
 
 // <type>           ::= <template-param>
 void CXXNameMangler::mangleType(const SubstTemplateTypeParmPackType *T) {
-  mangleTemplateParameter(T->getReplacedParameter()->getIndex());
+  // FIXME: not clear how to mangle this!
+  // template <class T...> class A {
+  //   template <class U...> void foo(T(*)(U) x...);
+  // };
+  Out << "_SUBSTPACK_";
 }
 
 // <type> ::= P <type>   # pointer-to
@@ -2511,8 +2550,11 @@
   }
 
   case Expr::SubstNonTypeTemplateParmPackExprClass:
-    mangleTemplateParameter(
-     cast<SubstNonTypeTemplateParmPackExpr>(E)->getParameterPack()->getIndex());
+    // FIXME: not clear how to mangle this!
+    // template <unsigned N...> class A {
+    //   template <class U...> void foo(U (&x)[N]...);
+    // };
+    Out << "_SUBSTPACK_";
     break;
       
   case Expr::DependentScopeDeclRefExprClass: {
@@ -2872,6 +2914,18 @@
     Out << 'T' << (Index - 1) << '_';
 }
 
+void CXXNameMangler::mangleExistingSubstitution(QualType type) {
+  bool result = mangleSubstitution(type);
+  assert(result && "no existing substitution for type");
+  (void) result;
+}
+
+void CXXNameMangler::mangleExistingSubstitution(TemplateName tname) {
+  bool result = mangleSubstitution(tname);
+  assert(result && "no existing substitution for template name");
+  (void) result;
+}
+
 // <substitution> ::= S <seq-id> _
 //                ::= S_
 bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) {