]> granicus.if.org Git - clang/commitdiff
Mangle dependent template names such as the nested-name-specifier in
authorDouglas Gregor <dgregor@apple.com>
Fri, 23 Apr 2010 03:10:43 +0000 (03:10 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 23 Apr 2010 03:10:43 +0000 (03:10 +0000)
  T::apply <U>::type

Fixes PR6899, although I want to dig a little deeper into the FIXME
for dependent template names that refer to operators.

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

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

index e7257bd8127324d7efb0a792b8538ccf27eac10e..168231277321b02a67fc1aee09c6a1c704448ad7 100644 (file)
@@ -147,6 +147,7 @@ private:
                         unsigned NumTemplateArgs);
   void manglePrefix(const DeclContext *DC, bool NoFunction=false);
   void mangleTemplatePrefix(const TemplateDecl *ND);
+  void mangleTemplatePrefix(TemplateName Template);
   void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
   void mangleQualifiers(Qualifiers Quals);
 
@@ -172,6 +173,9 @@ private:
   void mangleCXXCtorType(CXXCtorType T);
   void mangleCXXDtorType(CXXDtorType T);
 
+  void mangleTemplateArgs(TemplateName Template,
+                          const TemplateArgument *TemplateArgs,
+                          unsigned NumTemplateArgs);  
   void mangleTemplateArgs(const TemplateParameterList &PL,
                           const TemplateArgument *TemplateArgs,
                           unsigned NumTemplateArgs);
@@ -473,11 +477,12 @@ void CXXNameMangler::mangleUnresolvedScope(NestedNameSpecifier *Qualifier) {
     if (const TemplateSpecializationType *TST =
         dyn_cast<TemplateSpecializationType>(QTy)) {
       if (!mangleSubstitution(QualType(TST, 0))) {
-        TemplateDecl *TD = TST->getTemplateName().getAsTemplateDecl();
-        assert(TD && "FIXME: Support dependent template names");
-        mangleTemplatePrefix(TD);
-        TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
-        mangleTemplateArgs(*TemplateParameters, TST->getArgs(),
+        mangleTemplatePrefix(TST->getTemplateName());
+        
+        // FIXME: GCC does not appear to mangle the template arguments when
+        // the template in question is a dependent template name. Should we
+        // emulate that badness?
+        mangleTemplateArgs(TST->getTemplateName(), TST->getArgs(),
                            TST->getNumArgs());
         addSubstitution(QualType(TST, 0));
       }
@@ -739,6 +744,33 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
   addSubstitution(cast<NamedDecl>(DC));
 }
 
+void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) {
+  // <template-prefix> ::= <prefix> <template unqualified-name>
+  //                   ::= <template-param>
+  //                   ::= <substitution>
+  if (TemplateDecl *TD = Template.getAsTemplateDecl())
+    return mangleTemplatePrefix(TD);
+
+  if (QualifiedTemplateName *Qualified = Template.getAsQualifiedTemplateName())
+    mangleUnresolvedScope(Qualified->getQualifier());
+  
+  if (OverloadedTemplateStorage *Overloaded
+                                      = Template.getAsOverloadedTemplate()) {
+    mangleUnqualifiedName(0, (*Overloaded->begin())->getDeclName(), 
+                          UnknownArity);
+    return;
+  }
+   
+  DependentTemplateName *Dependent = Template.getAsDependentTemplateName();
+  assert(Dependent && "Unknown template name kind?");
+  mangleUnresolvedScope(Dependent->getQualifier());
+  if (Dependent->isIdentifier())
+    mangleSourceName(Dependent->getIdentifier());
+  else {
+    // FIXME: We can't possibly know the arity for mangling operators!
+  }
+}
+
 void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND) {
   // <template-prefix> ::= <prefix> <template unqualified-name>
   //                   ::= <template-param>
@@ -1574,6 +1606,20 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
   }
 }
 
+void CXXNameMangler::mangleTemplateArgs(TemplateName Template,
+                                        const TemplateArgument *TemplateArgs,
+                                        unsigned NumTemplateArgs) {
+  if (TemplateDecl *TD = Template.getAsTemplateDecl())
+    return mangleTemplateArgs(*TD->getTemplateParameters(), TemplateArgs,
+                              NumTemplateArgs);
+  
+  // <template-args> ::= I <template-arg>+ E
+  Out << 'I';
+  for (unsigned i = 0; i != NumTemplateArgs; ++i)
+    mangleTemplateArg(0, TemplateArgs[i]);
+  Out << 'E';
+}
+
 void CXXNameMangler::mangleTemplateArgs(const TemplateParameterList &PL,
                                         const TemplateArgumentList &AL) {
   // <template-args> ::= I <template-arg>+ E
@@ -1608,7 +1654,7 @@ void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
     break;
   case TemplateArgument::Template:
     assert(A.getAsTemplate().getAsTemplateDecl() &&
-           "FIXME: Support dependent template names");
+           "Can't get dependent template names here");
     mangleName(A.getAsTemplate().getAsTemplateDecl());
     break;
   case TemplateArgument::Expression:
@@ -1620,6 +1666,7 @@ void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
     mangleIntegerLiteral(A.getIntegralType(), *A.getAsIntegral());
     break;
   case TemplateArgument::Declaration: {
+    assert(P && "Missing template parameter for declaration argument");
     //  <expr-primary> ::= L <mangled-name> E # external name
 
     // Clang produces AST's where pointer-to-member-function expressions
index 22949da64ad863c9c67d3a3b7dc20ea5aa4bdda6..8b097ff69fc17e53937a4bafe9f4ce706a72d244 100644 (file)
@@ -104,3 +104,26 @@ namespace test8 {
   // CHECK: define weak_odr void @_ZN5test81fIiEEvNS_5int_cIXsrNS_4metaIT_E4typeE5valueEEE
   template void f<int>(int_c<sizeof(int)>);
 }
+
+namespace test9 {
+  template<typename T>
+  struct supermeta {
+    template<typename U>
+    struct apply {
+      typedef T U::*type;
+    };
+  };
+
+  struct X { };
+
+  template<typename T, typename U>
+  typename supermeta<T>::template apply<U>::type f();
+
+  void test_f() {
+    // CHECK: @_ZN5test91fIiNS_1XEEENS_9supermetaIT_E5applyIT0_E4typeEv()
+    // Note: GCC incorrectly mangles this as
+    // _ZN5test91fIiNS_1XEEENS_9supermetaIT_E5apply4typeEv, while EDG
+    // gets it right.
+    f<int, X>();
+  }
+}