]> granicus.if.org Git - clang/commitdiff
Improve name mangling for dependent template names (e.g., typename
authorDouglas Gregor <dgregor@apple.com>
Wed, 28 Apr 2010 05:58:56 +0000 (05:58 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 28 Apr 2010 05:58:56 +0000 (05:58 +0000)
T::template apply<U>), handling a few cases where we previously failed
and performing substitutions on such dependent names. Fixes a crash in
Boost.PropertyTree.

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

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

index cb32570bd43cd8e41b6b13e02bc961b8fab595d9..8658cfb0282cc5e343befda1e97b17084e2812dc 100644 (file)
@@ -111,6 +111,7 @@ public:
 private:
   bool mangleSubstitution(const NamedDecl *ND);
   bool mangleSubstitution(QualType T);
+  bool mangleSubstitution(TemplateName Template);
   bool mangleSubstitution(uintptr_t Ptr);
 
   bool mangleStandardSubstitution(const NamedDecl *ND);
@@ -121,6 +122,7 @@ private:
     addSubstitution(reinterpret_cast<uintptr_t>(ND));
   }
   void addSubstitution(QualType T);
+  void addSubstitution(TemplateName Template);
   void addSubstitution(uintptr_t Ptr);
 
   void mangleUnresolvedScope(NestedNameSpecifier *Qualifier);
@@ -138,6 +140,7 @@ private:
                              unsigned KnownArity);
   void mangleUnscopedName(const NamedDecl *ND);
   void mangleUnscopedTemplateName(const TemplateDecl *ND);
+  void mangleUnscopedTemplateName(TemplateName);
   void mangleSourceName(const IdentifierInfo *II);
   void mangleLocalName(const NamedDecl *ND);
   void mangleNestedName(const NamedDecl *ND, const DeclContext *DC,
@@ -431,6 +434,31 @@ void CXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *ND) {
   addSubstitution(ND);
 }
 
+void CXXNameMangler::mangleUnscopedTemplateName(TemplateName Template) {
+  //     <unscoped-template-name> ::= <unscoped-name>
+  //                              ::= <substitution>
+  if (TemplateDecl *TD = Template.getAsTemplateDecl())
+    return mangleUnscopedTemplateName(TD);
+  
+  if (mangleSubstitution(Template))
+    return;
+
+  // FIXME: How to cope with operators here?
+  DependentTemplateName *Dependent = Template.getAsDependentTemplateName();
+  assert(Dependent && "Not a dependent template name?");
+  if (!Dependent->isIdentifier()) {
+    // FIXME: We can't possibly know the arity of the operator here!
+    Diagnostic &Diags = Context.getDiags();
+    unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error,
+                                      "cannot mangle dependent operator name");
+    Diags.Report(FullSourceLoc(), DiagID);
+    return;
+  }
+  
+  mangleSourceName(Dependent->getIdentifier());
+  addSubstitution(Template);
+}
+
 void CXXNameMangler::mangleNumber(int64_t Number) {
   //  <number> ::= [n] <non-negative decimal integer>
   if (Number < 0) {
@@ -764,15 +792,7 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) {
   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 of the operator here!
-    Diagnostic &Diags = Context.getDiags();
-    unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error,
-                                 "cannot mangle dependent operator name");
-    Diags.Report(FullSourceLoc(), DiagID);
-  }
+  mangleUnscopedTemplateName(Template);
 }
 
 void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND) {
@@ -1199,17 +1219,42 @@ void CXXNameMangler::mangleType(const InjectedClassNameType *T) {
 }
 
 void CXXNameMangler::mangleType(const TemplateSpecializationType *T) {
-  TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl();
-  assert(TD && "FIXME: Support dependent template names!");
-
-  mangleName(TD, T->getArgs(), T->getNumArgs());
+  if (TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl()) {
+    mangleName(TD, T->getArgs(), T->getNumArgs());
+  } else {
+    if (mangleSubstitution(QualType(T, 0)))
+      return;
+    
+    mangleTemplatePrefix(T->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(T->getTemplateName(), T->getArgs(), T->getNumArgs());
+    addSubstitution(QualType(T, 0));
+  }
 }
 
 void CXXNameMangler::mangleType(const DependentNameType *T) {
   // Typename types are always nested
   Out << 'N';
-  mangleUnresolvedScope(T->getQualifier());
-  mangleSourceName(T->getIdentifier());
+  if (T->getIdentifier()) {
+    mangleUnresolvedScope(T->getQualifier());
+    mangleSourceName(T->getIdentifier());
+  } else {
+    const TemplateSpecializationType *TST = T->getTemplateId();
+    if (!mangleSubstitution(QualType(TST, 0))) {
+      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));
+    }
+  }
+    
   Out << 'E';
 }
 
@@ -1743,6 +1788,15 @@ bool CXXNameMangler::mangleSubstitution(QualType T) {
   return mangleSubstitution(TypePtr);
 }
 
+bool CXXNameMangler::mangleSubstitution(TemplateName Template) {
+  if (TemplateDecl *TD = Template.getAsTemplateDecl())
+    return mangleSubstitution(TD);
+  
+  Template = Context.getASTContext().getCanonicalTemplateName(Template);
+  return mangleSubstitution(
+                      reinterpret_cast<uintptr_t>(Template.getAsVoidPointer()));
+}
+
 bool CXXNameMangler::mangleSubstitution(uintptr_t Ptr) {
   llvm::DenseMap<uintptr_t, unsigned>::iterator I = Substitutions.find(Ptr);
   if (I == Substitutions.end())
@@ -1921,6 +1975,14 @@ void CXXNameMangler::addSubstitution(QualType T) {
   addSubstitution(TypePtr);
 }
 
+void CXXNameMangler::addSubstitution(TemplateName Template) {
+  if (TemplateDecl *TD = Template.getAsTemplateDecl())
+    return addSubstitution(TD);
+  
+  Template = Context.getASTContext().getCanonicalTemplateName(Template);
+  addSubstitution(reinterpret_cast<uintptr_t>(Template.getAsVoidPointer()));
+}
+
 void CXXNameMangler::addSubstitution(uintptr_t Ptr) {
   unsigned SeqID = Substitutions.size();
 
index 8b097ff69fc17e53937a4bafe9f4ce706a72d244..6a2994407167ed9891d4c102d33fb8788629a93b 100644 (file)
@@ -127,3 +127,20 @@ namespace test9 {
     f<int, X>();
   }
 }
+
+namespace test10 {
+  template<typename T>
+  struct X {
+    template<typename U>
+    struct definition {
+    };
+  };
+
+  // CHECK: _ZN6test101fIidEENS_1XIT_E10definitionIT0_EES2_S5_
+  template<typename T, typename U>
+  typename X<T>::template definition<U> f(T, U) { }
+
+  void g(int i, double d) {
+    f(i, d);
+  }
+}