r229615 - Itanium ABI: Improve our mangling of <destructor-name>

David Majnemer david.majnemer at gmail.com
Tue Feb 17 18:28:02 PST 2015


Author: majnemer
Date: Tue Feb 17 20:28:01 2015
New Revision: 229615

URL: http://llvm.org/viewvc/llvm-project?rev=229615&view=rev
Log:
Itanium ABI: Improve our mangling of <destructor-name>

Our mangling of <destructor-name> wasn't quite right: we'd introduce
mangling substitutions where one shouldn't be possible.  We also didn't
correctly handle the case where the destroyed type was not dependent but
still a TemplateSpecializationType.

N.B. There isn't a mangling for a template-template parameter showing up
as the destroyed type.  We do the 'obvious' thing and mangle the index
of the parameter.

Modified:
    cfe/trunk/lib/AST/ItaniumMangle.cpp
    cfe/trunk/test/CodeGenCXX/mangle-subst.cpp
    cfe/trunk/test/CodeGenCXX/mangle.cpp

Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=229615&r1=229614&r2=229615&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Tue Feb 17 20:28:01 2015
@@ -352,6 +352,8 @@ private:
   void manglePrefix(QualType type);
   void mangleTemplatePrefix(const TemplateDecl *ND, bool NoFunction=false);
   void mangleTemplatePrefix(TemplateName Template);
+  void mangleDestructorName(QualType DestroyedType);
+  void mangleOperatorName(DeclarationName Name, unsigned Arity);
   void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
   void mangleQualifiers(Qualifiers Quals);
   void mangleRefQualifier(RefQualifierKind RefQualifier);
@@ -752,8 +754,7 @@ void CXXNameMangler::mangleCallOffset(in
 }
 
 void CXXNameMangler::manglePrefix(QualType type) {
-  if (const TemplateSpecializationType *TST =
-        type->getAs<TemplateSpecializationType>()) {
+  if (const auto *TST = type->getAs<TemplateSpecializationType>()) {
     if (!mangleSubstitution(QualType(TST, 0))) {
       mangleTemplatePrefix(TST->getTemplateName());
         
@@ -763,17 +764,19 @@ void CXXNameMangler::manglePrefix(QualTy
       mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
       addSubstitution(QualType(TST, 0));
     }
-  } else if (const DependentTemplateSpecializationType *DTST
-               = type->getAs<DependentTemplateSpecializationType>()) {
-    TemplateName Template
-      = getASTContext().getDependentTemplateName(DTST->getQualifier(), 
-                                                 DTST->getIdentifier());
-    mangleTemplatePrefix(Template);
+  } else if (const auto *DTST =
+                 type->getAs<DependentTemplateSpecializationType>()) {
+    if (!mangleSubstitution(QualType(DTST, 0))) {
+      TemplateName Template = getASTContext().getDependentTemplateName(
+          DTST->getQualifier(), DTST->getIdentifier());
+      mangleTemplatePrefix(Template);
 
-    // 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(DTST->getArgs(), DTST->getNumArgs());
+      // 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(DTST->getArgs(), DTST->getNumArgs());
+      addSubstitution(QualType(DTST, 0));
+    }
   } else {
     // We use the QualType mangle type variant here because it handles
     // substitutions.
@@ -1054,15 +1057,20 @@ void CXXNameMangler::mangleUnresolvedNam
   switch (name.getNameKind()) {
     // <base-unresolved-name> ::= <simple-id>
     case DeclarationName::Identifier:
+      mangleSourceName(name.getAsIdentifierInfo());
+      break;
+    // <base-unresolved-name> ::= dn <destructor-name>
+    case DeclarationName::CXXDestructorName:
+      Out << "dn";
+      mangleDestructorName(name.getCXXNameType());
       break;
     // <base-unresolved-name> ::= on <operator-name>
     case DeclarationName::CXXConversionFunctionName:
     case DeclarationName::CXXLiteralOperatorName:
     case DeclarationName::CXXOperatorName:
       Out << "on";
+      mangleOperatorName(name, knownArity);
       break;
-    case DeclarationName::CXXDestructorName:
-      llvm_unreachable("Can't mangle a constructor name!");
     case DeclarationName::CXXConstructorName:
       llvm_unreachable("Can't mangle a constructor name!");
     case DeclarationName::CXXUsingDirective:
@@ -1072,12 +1080,12 @@ void CXXNameMangler::mangleUnresolvedNam
     case DeclarationName::ObjCZeroArgSelector:
       llvm_unreachable("Can't mangle Objective-C selector names here!");
   }
-  mangleUnqualifiedName(nullptr, name, knownArity);
 }
 
 void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
                                            DeclarationName Name,
                                            unsigned KnownArity) {
+  unsigned Arity = KnownArity;
   //  <unqualified-name> ::= <operator-name>
   //                     ::= <ctor-dtor-name>
   //                     ::= <source-name>
@@ -1219,33 +1227,19 @@ void CXXNameMangler::mangleUnqualifiedNa
       mangleCXXDtorType(Dtor_Complete);
     break;
 
-  case DeclarationName::CXXConversionFunctionName:
-    // <operator-name> ::= cv <type>    # (cast)
-    Out << "cv";
-    mangleType(Name.getCXXNameType());
-    break;
-
-  case DeclarationName::CXXOperatorName: {
-    unsigned Arity;
-    if (ND) {
+  case DeclarationName::CXXOperatorName:
+    if (ND && Arity == UnknownArity) {
       Arity = cast<FunctionDecl>(ND)->getNumParams();
 
-      // If we have a C++ member function, we need to include the 'this' pointer.
-      // FIXME: This does not make sense for operators that are static, but their
-      // names stay the same regardless of the arity (operator new for instance).
-      if (isa<CXXMethodDecl>(ND))
-        Arity++;
-    } else
-      Arity = KnownArity;
-
-    mangleOperatorName(Name.getCXXOverloadedOperator(), Arity);
-    break;
-  }
-
+      // If we have a member function, we need to include the 'this' pointer.
+      if (const auto *MD = dyn_cast<CXXMethodDecl>(ND))
+        if (!MD->isStatic())
+          Arity++;
+    }
+  // FALLTHROUGH
+  case DeclarationName::CXXConversionFunctionName:
   case DeclarationName::CXXLiteralOperatorName:
-    // FIXME: This mangling is not yet official.
-    Out << "li";
-    mangleSourceName(Name.getCXXLiteralIdentifier());
+    mangleOperatorName(Name, Arity);
     break;
 
   case DeclarationName::CXXUsingDirective:
@@ -1646,6 +1640,61 @@ void CXXNameMangler::mangleType(Template
   addSubstitution(TN);
 }
 
+void CXXNameMangler::mangleDestructorName(QualType DestroyedType) {
+  // <destructor-name> ::= <unresolved-type>
+  //                   ::= <simple-id>
+  if (const auto *TST = DestroyedType->getAs<TemplateSpecializationType>()) {
+    TemplateName TN = TST->getTemplateName();
+    const auto *TD = TN.getAsTemplateDecl();
+    if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TD)) {
+      // Proposed to cxx-abi-dev on 2015-02-17.
+      mangleTemplateParameter(TTP->getIndex());
+    } else {
+      mangleUnscopedName(TD->getTemplatedDecl());
+    }
+    mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
+  } else if (const auto *DTST =
+                 DestroyedType->getAs<DependentTemplateSpecializationType>()) {
+    const IdentifierInfo *II = DTST->getIdentifier();
+    mangleSourceName(II);
+    mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
+  } else {
+    // We use the QualType mangle type variant here because it handles
+    // substitutions.
+    mangleType(DestroyedType);
+  }
+}
+
+void CXXNameMangler::mangleOperatorName(DeclarationName Name, unsigned Arity) {
+  switch (Name.getNameKind()) {
+  case DeclarationName::CXXConstructorName:
+  case DeclarationName::CXXDestructorName:
+  case DeclarationName::CXXUsingDirective:
+  case DeclarationName::Identifier:
+  case DeclarationName::ObjCMultiArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCZeroArgSelector:
+    llvm_unreachable("Not an operator name");
+
+  case DeclarationName::CXXConversionFunctionName:
+    // <operator-name> ::= cv <type>    # (cast)
+    Out << "cv";
+    mangleType(Name.getCXXNameType());
+    break;
+
+  case DeclarationName::CXXLiteralOperatorName:
+    Out << "li";
+    mangleSourceName(Name.getCXXLiteralIdentifier());
+    return;
+
+  case DeclarationName::CXXOperatorName:
+    mangleOperatorName(Name.getCXXOverloadedOperator(), Arity);
+    break;
+  }
+}
+
+
+
 void
 CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
   switch (OO) {
@@ -2841,9 +2890,8 @@ recurse:
       mangleUnresolvedPrefix(Qualifier, /*FirstQualifierLookup=*/nullptr);
     // <base-unresolved-name> ::= dn <destructor-name>
     Out << "dn";
-    // <destructor-name> ::= <unresolved-type>
-    //                   ::= <simple-id>
-    manglePrefix(PDE->getDestroyedType());
+    QualType DestroyedType = PDE->getDestroyedType();
+    mangleDestructorName(DestroyedType);
     break;
   }
 

Modified: cfe/trunk/test/CodeGenCXX/mangle-subst.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-subst.cpp?rev=229615&r1=229614&r2=229615&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-subst.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-subst.cpp Tue Feb 17 20:28:01 2015
@@ -80,3 +80,19 @@ void f(void (B::*)(), A, A) { }
 void f(void (B::*)(), A, A, void (B::*)(A), void (A::*)()) { }
 
 }
+
+namespace ManglePrefix {
+template <typename>
+struct X {
+  template <typename>
+  struct Y {
+    typedef int type;
+    typedef int type2;
+  };
+};
+template <typename T>
+typename X<T>::template Y<T>::type f(typename X<T>::template Y<T>::type2) { return 0; }
+
+// CHECK: @_ZN12ManglePrefix1fIiEENS_1XIT_E1YIS2_E4typeENS5_5type2E
+template int f<int>(int);
+}

Modified: cfe/trunk/test/CodeGenCXX/mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle.cpp?rev=229615&r1=229614&r2=229615&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle.cpp Tue Feb 17 20:28:01 2015
@@ -1030,10 +1030,21 @@ namespace test51 {
   decltype(U().~S1<T>()) fun2() {}
   template <typename U, typename T>
   decltype(S1<T>().~U()) fun3() {}
+  template <typename T>
+  decltype(S1<T>().~S1<T>(), S1<T>().~S1<T>()) fun4() {};
+  template <typename T>
+  decltype(S1<int>().~S1<T>()) fun5(){};
+  template <template <typename T> class U>
+  decltype(S1<int>().~U<int>()) fun6(){};
   template void fun1<int>();
   // CHECK-LABEL: @_ZN6test514fun1IiEEDTcldtcv2S1IT_E_Edn2S1IS2_EEEv
   template void fun2<S1<int>, int>();
   // CHECK-LABEL: @_ZN6test514fun2I2S1IiEiEEDTcldtcvT__Edn2S1IT0_EEEv
   template void fun3<S1<int>, int>();
   // CHECK-LABEL: @_ZN6test514fun3I2S1IiEiEEDTcldtcvS1_IT0_E_EdnT_EEv
+  template void fun4<int>();
+  // CHECK-LABEL: @_ZN6test514fun4IiEEDTcmcldtcv2S1IT_E_Edn2S1IS2_EEcldtcvS3__Edn2S1IS2_EEEv
+  template void fun5<int>();
+  // CHECK-LABEL: @_ZN6test514fun6I2S1EEDTcldtcvS1_IiE_EdnT_IiEEEv
+  template void fun6<S1>();
 }





More information about the cfe-commits mailing list