r229809 - Itanium ABI: Properly qualify the destructor-name

David Majnemer david.majnemer at gmail.com
Wed Feb 18 18:16:17 PST 2015


Author: majnemer
Date: Wed Feb 18 20:16:16 2015
New Revision: 229809

URL: http://llvm.org/viewvc/llvm-project?rev=229809&view=rev
Log:
Itanium ABI: Properly qualify the destructor-name

We didn't have enough qualificaiton before the scope specifier and we
had too much qualification in the destructor name itself.

Modified:
    cfe/trunk/lib/AST/ItaniumMangle.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=229809&r1=229808&r2=229809&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Wed Feb 18 20:16:16 2015
@@ -327,10 +327,8 @@ private:
   void addSubstitution(uintptr_t Ptr);
 
   void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
-                              NamedDecl *firstQualifierLookup,
                               bool recursive = false);
   void mangleUnresolvedName(NestedNameSpecifier *qualifier,
-                            NamedDecl *firstQualifierLookup,
                             DeclarationName name,
                             unsigned KnownArity = UnknownArity);
 
@@ -360,7 +358,8 @@ private:
   void manglePrefix(QualType type);
   void mangleTemplatePrefix(const TemplateDecl *ND, bool NoFunction=false);
   void mangleTemplatePrefix(TemplateName Template);
-  void mangleDestructorName(QualType DestroyedType);
+  bool mangleUnresolvedTypeOrSimpleId(QualType DestroyedType,
+                                      StringRef Prefix = "");
   void mangleOperatorName(DeclarationName Name, unsigned Arity);
   void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
   void mangleQualifiers(Qualifiers Quals);
@@ -799,7 +798,6 @@ void CXXNameMangler::manglePrefix(QualTy
 /// \param recursive - true if this is being called recursively,
 ///   i.e. if there is more prefix "to the right".
 void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
-                                            NamedDecl *firstQualifierLookup,
                                             bool recursive) {
 
   // x, ::x
@@ -832,7 +830,7 @@ void CXXNameMangler::mangleUnresolvedPre
 
   case NestedNameSpecifier::Namespace:
     if (qualifier->getPrefix())
-      mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
+      mangleUnresolvedPrefix(qualifier->getPrefix(),
                              /*recursive*/ true);
     else
       Out << "sr";
@@ -840,7 +838,7 @@ void CXXNameMangler::mangleUnresolvedPre
     break;
   case NestedNameSpecifier::NamespaceAlias:
     if (qualifier->getPrefix())
-      mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
+      mangleUnresolvedPrefix(qualifier->getPrefix(),
                              /*recursive*/ true);
     else
       Out << "sr";
@@ -857,193 +855,26 @@ void CXXNameMangler::mangleUnresolvedPre
     //   - a template template parameter with arguments
     // In all of these cases, we should have no prefix.
     if (qualifier->getPrefix()) {
-      mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
+      mangleUnresolvedPrefix(qualifier->getPrefix(),
                              /*recursive*/ true);
     } else {
       // Otherwise, all the cases want this.
       Out << "sr";
     }
 
-    // Only certain other types are valid as prefixes;  enumerate them.
-    switch (type->getTypeClass()) {
-    case Type::Builtin:
-    case Type::Complex:
-    case Type::Adjusted:
-    case Type::Decayed:
-    case Type::Pointer:
-    case Type::BlockPointer:
-    case Type::LValueReference:
-    case Type::RValueReference:
-    case Type::MemberPointer:
-    case Type::ConstantArray:
-    case Type::IncompleteArray:
-    case Type::VariableArray:
-    case Type::DependentSizedArray:
-    case Type::DependentSizedExtVector:
-    case Type::Vector:
-    case Type::ExtVector:
-    case Type::FunctionProto:
-    case Type::FunctionNoProto:
-    case Type::Enum:
-    case Type::Paren:
-    case Type::Elaborated:
-    case Type::Attributed:
-    case Type::Auto:
-    case Type::PackExpansion:
-    case Type::ObjCObject:
-    case Type::ObjCInterface:
-    case Type::ObjCObjectPointer:
-    case Type::Atomic:
-      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>
-    // (this last is not official yet)
-    case Type::TypeOfExpr:
-    case Type::TypeOf:
-    case Type::Decltype:
-    case Type::TemplateTypeParm:
-    case Type::UnaryTransform:
-    case Type::SubstTemplateTypeParm:
-    unresolvedType:
-      assert(!qualifier->getPrefix());
-
-      // We only get here recursively if we're followed by identifiers.
-      if (recursive) Out << 'N';
-
-      // This seems to do everything we want.  It's not really
-      // sanctioned for a substituted template parameter, though.
-      mangleType(QualType(type, 0));
-
-      // We never want to print 'E' directly after an unresolved-type,
-      // so we return directly.
+    if (mangleUnresolvedTypeOrSimpleId(QualType(type, 0), recursive ? "N" : ""))
       return;
 
-    case Type::Typedef:
-      mangleSourceName(cast<TypedefType>(type)->getDecl()->getIdentifier());
-      break;
-
-    case Type::UnresolvedUsing:
-      mangleSourceName(cast<UnresolvedUsingType>(type)->getDecl()
-                         ->getIdentifier());
-      break;
-
-    case Type::Record:
-      mangleSourceName(cast<RecordType>(type)->getDecl()->getIdentifier());
-      break;
-
-    case Type::TemplateSpecialization: {
-      const TemplateSpecializationType *tst
-        = cast<TemplateSpecializationType>(type);
-      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;
-
-        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;
-      }
-      }
-
-      mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());
-      break;
-    }
-
-    case Type::InjectedClassName:
-      mangleSourceName(cast<InjectedClassNameType>(type)->getDecl()
-                         ->getIdentifier());
-      break;
-
-    case Type::DependentName:
-      mangleSourceName(cast<DependentNameType>(type)->getIdentifier());
-      break;
-
-    case Type::DependentTemplateSpecialization: {
-      const DependentTemplateSpecializationType *tst
-        = cast<DependentTemplateSpecializationType>(type);
-      mangleSourceName(tst->getIdentifier());
-      mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());
-      break;
-    }
-    }
     break;
   }
 
   case NestedNameSpecifier::Identifier:
     // Member expressions can have these without prefixes.
-    if (qualifier->getPrefix()) {
-      mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
+    if (qualifier->getPrefix())
+      mangleUnresolvedPrefix(qualifier->getPrefix(),
                              /*recursive*/ true);
-    } else if (firstQualifierLookup) {
-
-      // Try to make a proper qualifier out of the lookup result, and
-      // then just recurse on that.
-      NestedNameSpecifier *newQualifier;
-      if (TypeDecl *typeDecl = dyn_cast<TypeDecl>(firstQualifierLookup)) {
-        QualType type = getASTContext().getTypeDeclType(typeDecl);
-
-        // Pretend we had a different nested name specifier.
-        newQualifier = NestedNameSpecifier::Create(getASTContext(),
-                                                   /*prefix*/ nullptr,
-                                                   /*template*/ false,
-                                                   type.getTypePtr());
-      } else if (NamespaceDecl *nspace =
-                   dyn_cast<NamespaceDecl>(firstQualifierLookup)) {
-        newQualifier = NestedNameSpecifier::Create(getASTContext(),
-                                                   /*prefix*/ nullptr,
-                                                   nspace);
-      } else if (NamespaceAliasDecl *alias =
-                   dyn_cast<NamespaceAliasDecl>(firstQualifierLookup)) {
-        newQualifier = NestedNameSpecifier::Create(getASTContext(),
-                                                   /*prefix*/ nullptr,
-                                                   alias);
-      } else {
-        // No sensible mangling to do here.
-        newQualifier = nullptr;
-      }
-
-      if (newQualifier)
-        return mangleUnresolvedPrefix(newQualifier, /*lookup*/ nullptr,
-                                      recursive);
-
-    } else {
+    else
       Out << "sr";
-    }
 
     mangleSourceName(qualifier->getAsIdentifier());
     break;
@@ -1058,10 +889,9 @@ void CXXNameMangler::mangleUnresolvedPre
 /// Mangle an unresolved-name, which is generally used for names which
 /// weren't resolved to specific entities.
 void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier,
-                                          NamedDecl *firstQualifierLookup,
                                           DeclarationName name,
                                           unsigned knownArity) {
-  if (qualifier) mangleUnresolvedPrefix(qualifier, firstQualifierLookup);
+  if (qualifier) mangleUnresolvedPrefix(qualifier);
   switch (name.getNameKind()) {
     // <base-unresolved-name> ::= <simple-id>
     case DeclarationName::Identifier:
@@ -1070,7 +900,7 @@ void CXXNameMangler::mangleUnresolvedNam
     // <base-unresolved-name> ::= dn <destructor-name>
     case DeclarationName::CXXDestructorName:
       Out << "dn";
-      mangleDestructorName(name.getCXXNameType());
+      mangleUnresolvedTypeOrSimpleId(name.getCXXNameType());
       break;
     // <base-unresolved-name> ::= on <operator-name>
     case DeclarationName::CXXConversionFunctionName:
@@ -1648,29 +1478,149 @@ void CXXNameMangler::mangleType(Template
   addSubstitution(TN);
 }
 
-void CXXNameMangler::mangleDestructorName(QualType DestroyedType) {
-  // <destructor-name> ::= <unresolved-type>
-  //                   ::= <simple-id>
-  if (const auto *TST = DestroyedType->getAs<TemplateSpecializationType>()) {
+bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
+                                                    StringRef Prefix) {
+  // Only certain other types are valid as prefixes;  enumerate them.
+  switch (Ty->getTypeClass()) {
+  case Type::Builtin:
+  case Type::Complex:
+  case Type::Adjusted:
+  case Type::Decayed:
+  case Type::Pointer:
+  case Type::BlockPointer:
+  case Type::LValueReference:
+  case Type::RValueReference:
+  case Type::MemberPointer:
+  case Type::ConstantArray:
+  case Type::IncompleteArray:
+  case Type::VariableArray:
+  case Type::DependentSizedArray:
+  case Type::DependentSizedExtVector:
+  case Type::Vector:
+  case Type::ExtVector:
+  case Type::FunctionProto:
+  case Type::FunctionNoProto:
+  case Type::Paren:
+  case Type::Attributed:
+  case Type::Auto:
+  case Type::PackExpansion:
+  case Type::ObjCObject:
+  case Type::ObjCInterface:
+  case Type::ObjCObjectPointer:
+  case Type::Atomic:
+    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>
+  // (this last is not official yet)
+  case Type::TypeOfExpr:
+  case Type::TypeOf:
+  case Type::Decltype:
+  case Type::TemplateTypeParm:
+  case Type::UnaryTransform:
+  case Type::SubstTemplateTypeParm:
+  unresolvedType:
+    // Some callers want a prefix before the mangled type.
+    Out << Prefix;
+
+    // This seems to do everything we want.  It's not really
+    // sanctioned for a substituted template parameter, though.
+    mangleType(Ty);
+
+    // We never want to print 'E' directly after an unresolved-type,
+    // so we return directly.
+    return true;
+
+  case Type::Typedef:
+    mangleSourceName(cast<TypedefType>(Ty)->getDecl()->getIdentifier());
+    break;
+
+  case Type::UnresolvedUsing:
+    mangleSourceName(
+        cast<UnresolvedUsingType>(Ty)->getDecl()->getIdentifier());
+    break;
+
+  case Type::Enum:
+  case Type::Record:
+    mangleSourceName(cast<TagType>(Ty)->getDecl()->getIdentifier());
+    break;
+
+  case Type::TemplateSpecialization: {
+    const TemplateSpecializationType *TST =
+        cast<TemplateSpecializationType>(Ty);
     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());
+    switch (TN.getKind()) {
+    case TemplateName::Template:
+    case TemplateName::QualifiedTemplate: {
+      TemplateDecl *TD = TN.getAsTemplateDecl();
+
+      // If the base is a template template parameter, this is an
+      // unresolved type.
+      assert(TD && "no template for template specialization type");
+      if (isa<TemplateTemplateParmDecl>(TD))
+        goto unresolvedType;
+
+      mangleSourceName(TD->getIdentifier());
+      break;
+    }
+
+    case TemplateName::OverloadedTemplate:
+    case TemplateName::DependentTemplate:
+      llvm_unreachable("invalid base for a template specialization type");
+
+    case TemplateName::SubstTemplateTemplateParm: {
+      SubstTemplateTemplateParmStorage *subst =
+          TN.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;
+    }
+    }
+
     mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
-  } else if (const auto *DTST =
-                 DestroyedType->getAs<DependentTemplateSpecializationType>()) {
-    const IdentifierInfo *II = DTST->getIdentifier();
-    mangleSourceName(II);
+    break;
+  }
+
+  case Type::InjectedClassName:
+    mangleSourceName(
+        cast<InjectedClassNameType>(Ty)->getDecl()->getIdentifier());
+    break;
+
+  case Type::DependentName:
+    mangleSourceName(cast<DependentNameType>(Ty)->getIdentifier());
+    break;
+
+  case Type::DependentTemplateSpecialization: {
+    const DependentTemplateSpecializationType *DTST =
+        cast<DependentTemplateSpecializationType>(Ty);
+    mangleSourceName(DTST->getIdentifier());
     mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
-  } else {
-    // We use the QualType mangle type variant here because it handles
-    // substitutions.
-    mangleType(DestroyedType);
+    break;
   }
+
+  case Type::Elaborated:
+    return mangleUnresolvedTypeOrSimpleId(
+        cast<ElaboratedType>(Ty)->getNamedType(), Prefix);
+  }
+
+  return false;
 }
 
 void CXXNameMangler::mangleOperatorName(DeclarationName Name, unsigned Arity) {
@@ -2636,7 +2586,7 @@ void CXXNameMangler::mangleMemberExpr(co
   //              ::= pt <expression> <unresolved-name>
   if (base)
     mangleMemberExprBase(base, isArrow);
-  mangleUnresolvedName(qualifier, firstQualifierLookup, member, arity);
+  mangleUnresolvedName(qualifier, member, arity);
 }
 
 /// Look at the callee of the given call expression and determine if
@@ -2894,12 +2844,26 @@ recurse:
     const auto *PDE = cast<CXXPseudoDestructorExpr>(E);
     if (const Expr *Base = PDE->getBase())
       mangleMemberExprBase(Base, PDE->isArrow());
-    if (NestedNameSpecifier *Qualifier = PDE->getQualifier())
-      mangleUnresolvedPrefix(Qualifier, /*FirstQualifierLookup=*/nullptr);
+    NestedNameSpecifier *Qualifier = PDE->getQualifier();
+    QualType ScopeType;
+    if (TypeSourceInfo *ScopeInfo = PDE->getScopeTypeInfo()) {
+      if (Qualifier) {
+        mangleUnresolvedPrefix(Qualifier,
+                               /*Recursive=*/true);
+        mangleUnresolvedTypeOrSimpleId(ScopeInfo->getType());
+        Out << 'E';
+      } else {
+        Out << "sr";
+        if (!mangleUnresolvedTypeOrSimpleId(ScopeInfo->getType()))
+          Out << 'E';
+      }
+    } else if (Qualifier) {
+      mangleUnresolvedPrefix(Qualifier);
+    }
     // <base-unresolved-name> ::= dn <destructor-name>
     Out << "dn";
     QualType DestroyedType = PDE->getDestroyedType();
-    mangleDestructorName(DestroyedType);
+    mangleUnresolvedTypeOrSimpleId(DestroyedType);
     break;
   }
 
@@ -2934,7 +2898,7 @@ recurse:
 
   case Expr::UnresolvedLookupExprClass: {
     const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
-    mangleUnresolvedName(ULE->getQualifier(), nullptr, ULE->getName(), Arity);
+    mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), Arity);
 
     // All the <unresolved-name> productions end in a
     // base-unresolved-name, where <template-args> are just tacked
@@ -3248,8 +3212,7 @@ recurse:
 
   case Expr::DependentScopeDeclRefExprClass: {
     const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
-    mangleUnresolvedName(DRE->getQualifier(), nullptr, DRE->getDeclName(),
-                         Arity);
+    mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(), Arity);
 
     // All the <unresolved-name> productions end in a
     // base-unresolved-name, where <template-args> are just tacked

Modified: cfe/trunk/test/CodeGenCXX/mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle.cpp?rev=229809&r1=229808&r2=229809&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle.cpp Wed Feb 18 20:16:16 2015
@@ -1024,6 +1024,12 @@ namespace test51 {
   template void fun<S1<int> >();
   // CHECK-LABEL: @_ZN6test513funI2S1IiEEEDTcldtcvT__EdnS3_EEv
 
+  enum E {};
+  template <typename T>
+  struct X {
+    struct Y {};
+  };
+
   template <typename T>
   decltype(S1<T>().~S1<T>()) fun1() {};
   template <typename U, typename T>
@@ -1036,6 +1042,10 @@ namespace test51 {
   decltype(S1<int>().~S1<T>()) fun5(){};
   template <template <typename T> class U>
   decltype(S1<int>().~U<int>()) fun6(){};
+  template <typename T>
+  decltype(E().E::~T()) fun7() {}
+  template <template <typename> class U>
+  decltype(X<int>::Y().U<int>::Y::~Y()) fun8() {}
   template void fun1<int>();
   // CHECK-LABEL: @_ZN6test514fun1IiEEDTcldtcv2S1IT_E_Edn2S1IS2_EEEv
   template void fun2<S1<int>, int>();
@@ -1045,6 +1055,10 @@ namespace test51 {
   template void fun4<int>();
   // CHECK-LABEL: @_ZN6test514fun4IiEEDTcmcldtcv2S1IT_E_Edn2S1IS2_EEcldtcvS3__Edn2S1IS2_EEEv
   template void fun5<int>();
-  // CHECK-LABEL: @_ZN6test514fun6I2S1EEDTcldtcvS1_IiE_EdnT_IiEEEv
+  // CHECK-LABEL: @_ZN6test514fun5IiEEDTcldtcv2S1IiE_Edn2S1IT_EEEv
   template void fun6<S1>();
+  // CHECK-LABEL: @_ZN6test514fun6I2S1EEDTcldtcvS1_IiE_EdnT_IiEEEv
+  template void fun7<E>();
+  // CHECK-LABEL: @_ZN6test514fun7INS_1EEEEDTcldtcvS1__Esr1EEdnT_EEv
+  template void fun8<X>();
 }





More information about the cfe-commits mailing list