[cfe-commits] r130824 - in /cfe/trunk: lib/AST/ItaniumMangle.cpp test/CodeGenCXX/mangle.cpp

John McCall rjmccall at apple.com
Tue May 3 18:45:19 PDT 2011


Author: rjmccall
Date: Tue May  3 20:45:19 2011
New Revision: 130824

URL: http://llvm.org/viewvc/llvm-project?rev=130824&view=rev
Log:
Type prefixes of unresolved-names should only be mangled as unresolved-types
if they match that production, i.e. if they're template type parameters
or decltypes (or, as an obvious case not yet described in the ABI document,
if they're template template parameters applied to template arguments).


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=130824&r1=130823&r2=130824&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Tue May  3 20:45:19 2011
@@ -255,7 +255,8 @@
                             DeclarationName name,
                             unsigned KnownArity = UnknownArity);
 
-  void mangleUnresolvedType(QualType type);
+  static bool isUnresolvedType(const Type *type);
+  void mangleUnresolvedType(const Type *type);
 
   void mangleName(const TemplateDecl *TD,
                   const TemplateArgument *TemplateArgs,
@@ -277,6 +278,7 @@
                         unsigned NumTemplateArgs);
   void manglePrefix(NestedNameSpecifier *qualifier);
   void manglePrefix(const DeclContext *DC, bool NoFunction=false);
+  void manglePrefix(QualType type);
   void mangleTemplatePrefix(const TemplateDecl *ND);
   void mangleTemplatePrefix(TemplateName Template);
   void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
@@ -317,6 +319,8 @@
   void mangleTemplateArgs(const TemplateParameterList &PL,
                           const TemplateArgumentList &AL);
   void mangleTemplateArg(const NamedDecl *P, const TemplateArgument &A);
+  void mangleUnresolvedTemplateArgs(const TemplateArgument *args,
+                                    unsigned numArgs);
 
   void mangleTemplateParameter(unsigned Index);
 
@@ -667,7 +671,7 @@
   Out << '_';
 }
 
-void CXXNameMangler::mangleUnresolvedType(QualType type) {
+void CXXNameMangler::manglePrefix(QualType type) {
   if (const TemplateSpecializationType *TST =
         type->getAs<TemplateSpecializationType>()) {
     if (!mangleSubstitution(QualType(TST, 0))) {
@@ -698,6 +702,31 @@
   }
 }
 
+/// Returns true if the given type, appearing within an
+/// unresolved-name, should be mangled as an unresolved-type.
+bool CXXNameMangler::isUnresolvedType(const Type *type) {
+  // <unresolved-type> ::= <template-param>
+  //                   ::= <decltype>
+  //                   ::= <template-template-param> <template-args>
+  // (this last is not official yet)
+
+  if (isa<TemplateTypeParmType>(type)) return true;
+  if (isa<DecltypeType>(type)) return true;
+  // typeof?
+  if (const TemplateSpecializationType *tst =
+        dyn_cast<TemplateSpecializationType>(type)) {
+    TemplateDecl *temp = tst->getTemplateName().getAsTemplateDecl();
+    if (temp && isa<TemplateTemplateParmDecl>(temp))
+      return true;
+  }
+  return false;
+}
+
+void CXXNameMangler::mangleUnresolvedType(const Type *type) {
+  // This seems to be do everything we want.
+  mangleType(QualType(type, 0));
+}
+
 /// Mangle everything prior to the base-unresolved-name in an unresolved-name.
 ///
 /// \param firstQualifierLookup - the entity found by unqualified lookup
@@ -752,17 +781,60 @@
 
   case NestedNameSpecifier::TypeSpec:
   case NestedNameSpecifier::TypeSpecWithTemplate: {
-    // Both cases want this.
-    Out << "sr";
+    const Type *type = qualifier->getAsType();
 
-    // We only get here recursively if we're followed by identifiers.
-    if (recursive) Out << 'N';
+    // We only want to use an unresolved-type encoding if this is one of:
+    //   - a decltype
+    //   - a template type parameter
+    //   - a template template parameter with arguments
+    // In all of these cases, we should have no prefix.
+    if (qualifier->getPrefix()) {
+      mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
+                             /*recursive*/ true);
+    } else {
+      // Otherwise, all the cases want this.
+      Out << "sr";
+
+      if (isUnresolvedType(type)) {
+        // We only get here recursively if we're followed by identifiers.
+        if (recursive) Out << 'N';
+        mangleUnresolvedType(type);
+
+        // We never want to print 'E' directly after an unresolved-type,
+        // so we return directly.
+        return;
+      }
+    }
 
-    mangleUnresolvedType(QualType(qualifier->getAsType(), 0));
+    assert(!isUnresolvedType(type));
 
-    // We never want to print 'E' directly after an unresolved-type,
-    // so we return directly.
-    return;
+    // Only certain other types are valid as prefixes;  enumerate them.
+    // FIXME: can we get ElaboratedTypes here?
+    // FIXME: SubstTemplateTypeParmType?
+    if (const TagType *t = dyn_cast<TagType>(type)) {
+      mangleSourceName(t->getDecl()->getIdentifier());
+    } else if (const TypedefType *t = dyn_cast<TypedefType>(type)) {
+      mangleSourceName(t->getDecl()->getIdentifier());
+    } else if (const UnresolvedUsingType *t
+                 = dyn_cast<UnresolvedUsingType>(type)) {
+      mangleSourceName(t->getDecl()->getIdentifier());
+    } else if (const DependentNameType *t
+                 = dyn_cast<DependentNameType>(type)) {
+      mangleSourceName(t->getIdentifier());
+    } else if (const TemplateSpecializationType *tst
+                 = dyn_cast<TemplateSpecializationType>(type)) {
+      TemplateDecl *temp = tst->getTemplateName().getAsTemplateDecl();
+      assert(temp && "no template for template specialization type");
+      mangleSourceName(temp->getIdentifier());
+      mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs());
+    } else if (const DependentTemplateSpecializationType *tst
+                 = dyn_cast<DependentTemplateSpecializationType>(type)) {
+      mangleSourceName(tst->getIdentifier());
+      mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs());
+    } else {
+      llvm_unreachable("unexpected type in nested name specifier!");
+    }
+    break;
   }
 
   case NestedNameSpecifier::Identifier:
@@ -1097,7 +1169,7 @@
 
   case NestedNameSpecifier::TypeSpec:
   case NestedNameSpecifier::TypeSpecWithTemplate:
-    mangleUnresolvedType(QualType(qualifier->getAsType(), 0));
+    manglePrefix(QualType(qualifier->getAsType(), 0));
     return;
 
   case NestedNameSpecifier::Identifier:
@@ -2552,8 +2624,8 @@
                           const ExplicitTemplateArgumentList &TemplateArgs) {
   // <template-args> ::= I <template-arg>+ E
   Out << 'I';
-  for (unsigned I = 0, E = TemplateArgs.NumTemplateArgs; I != E; ++I)
-    mangleTemplateArg(0, TemplateArgs.getTemplateArgs()[I].getArgument());
+  for (unsigned i = 0, e = TemplateArgs.NumTemplateArgs; i != e; ++i)
+    mangleTemplateArg(0, TemplateArgs.getTemplateArgs()[i].getArgument());
   Out << 'E';
 }
 
@@ -2564,10 +2636,15 @@
     return mangleTemplateArgs(*TD->getTemplateParameters(), TemplateArgs,
                               NumTemplateArgs);
   
+  mangleUnresolvedTemplateArgs(TemplateArgs, NumTemplateArgs);
+}
+
+void CXXNameMangler::mangleUnresolvedTemplateArgs(const TemplateArgument *args,
+                                                  unsigned numArgs) {
   // <template-args> ::= I <template-arg>+ E
   Out << 'I';
-  for (unsigned i = 0; i != NumTemplateArgs; ++i)
-    mangleTemplateArg(0, TemplateArgs[i]);
+  for (unsigned i = 0; i != numArgs; ++i)
+    mangleTemplateArg(0, args[i]);
   Out << 'E';
 }
 

Modified: cfe/trunk/test/CodeGenCXX/mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle.cpp?rev=130824&r1=130823&r2=130824&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle.cpp Tue May  3 20:45:19 2011
@@ -397,16 +397,16 @@
   struct Path2 : AmbiguousBase { double p; };
   struct Derived : Path1, Path2 { };
 
-  // CHECK: define linkonce_odr i32 @_ZN5test38get_ab_1INS_7DerivedEEEDtptcvPT_Li0EsrNS_5Path1E2abERS2_(
+  // CHECK: define linkonce_odr i32 @_ZN5test38get_ab_1INS_7DerivedEEEDtptcvPT_Li0Esr5Path1E2abERS2_(
   template <class T> decltype(((T*) 0)->Path1::ab) get_ab_1(T &ref) { return ref.Path1::ab; }
 
-  // CHECK: define linkonce_odr i32 @_ZN5test38get_ab_2INS_7DerivedEEEDtptcvPT_Li0EsrNS_5Path2E2abERS2_(
+  // CHECK: define linkonce_odr i32 @_ZN5test38get_ab_2INS_7DerivedEEEDtptcvPT_Li0Esr5Path2E2abERS2_(
   template <class T> decltype(((T*) 0)->Path2::ab) get_ab_2(T &ref) { return ref.Path2::ab; }
 
-  // CHECK: define linkonce_odr float @_ZN5test37get_p_1INS_7DerivedEEEDtptcvPT_Li0EsrNS_5Path1E1pERS2_(
+  // CHECK: define linkonce_odr float @_ZN5test37get_p_1INS_7DerivedEEEDtptcvPT_Li0Esr5Path1E1pERS2_(
   template <class T> decltype(((T*) 0)->Path1::p) get_p_1(T &ref) { return ref.Path1::p; }
 
-  // CHECK: define linkonce_odr double @_ZN5test37get_p_2INS_7DerivedEEEDtptcvPT_Li0EsrNS_5Path2E1pERS2_(
+  // CHECK: define linkonce_odr double @_ZN5test37get_p_2INS_7DerivedEEEDtptcvPT_Li0Esr5Path2E1pERS2_(
   template <class T> decltype(((T*) 0)->Path2::p) get_p_2(T &ref) { return ref.Path2::p; }
 
   Derived obj;
@@ -676,3 +676,38 @@
     A<foo>::call();
   }
 }
+
+namespace test26 {
+  template <template <class> class T> void foo(decltype(T<float>::object) &object) {}
+
+  template <class T> struct holder { static T object; };
+
+  void test() {
+    float f;
+
+    // CHECK: call void @_ZN6test263fooINS_6holderEEEvRDtsrT_IfE6objectE(
+    foo<holder>(f);
+  }
+}
+
+namespace test27 {
+  struct A {
+    struct inner {
+      float object;
+    };
+
+    float meth();
+  };
+  typedef A Alias;
+
+  template <class T> void a(decltype(T::inner::object) &object) {}
+  template <class T> void b(decltype(T().Alias::meth()) &object) {}
+
+  void test() {
+    float f;
+    // CHECK: call void @_ZN6test271aINS_1AEEEvRDtsrNT_5innerE6objectE(
+    a<A>(f);
+    // CHECK: call void @_ZN6test271bINS_1AEEEvRDTcldtcvT__Esr5AliasE4methEE(
+    b<A>(f);
+  }
+}





More information about the cfe-commits mailing list