]> granicus.if.org Git - clang/commitdiff
Type prefixes of unresolved-names should only be mangled as unresolved-types
authorJohn McCall <rjmccall@apple.com>
Wed, 4 May 2011 01:45:19 +0000 (01:45 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 4 May 2011 01:45:19 +0000 (01:45 +0000)
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).

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

lib/AST/ItaniumMangle.cpp
test/CodeGenCXX/mangle.cpp

index c460929c461d754f2964da63e0bd4688126b58eb..e368c8927f70efd0548c3771a1ef1c2f1ae5b4ce 100644 (file)
@@ -255,7 +255,8 @@ private:
                             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 @@ private:
                         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 @@ private:
   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 @@ void CXXNameMangler::mangleCallOffset(int64_t NonVirtual, int64_t Virtual) {
   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 @@ void CXXNameMangler::mangleUnresolvedType(QualType type) {
   }
 }
 
+/// 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 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
 
   case NestedNameSpecifier::TypeSpec:
   case NestedNameSpecifier::TypeSpecWithTemplate: {
-    // Both cases want this.
-    Out << "sr";
+    const Type *type = qualifier->getAsType();
+
+    // 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";
 
-    // We only get here recursively if we're followed by identifiers.
-    if (recursive) Out << 'N';
+      if (isUnresolvedType(type)) {
+        // We only get here recursively if we're followed by identifiers.
+        if (recursive) Out << 'N';
+        mangleUnresolvedType(type);
 
-    mangleUnresolvedType(QualType(qualifier->getAsType(), 0));
+        // We never want to print 'E' directly after an unresolved-type,
+        // so we return directly.
+        return;
+      }
+    }
 
-    // We never want to print 'E' directly after an unresolved-type,
-    // so we return directly.
-    return;
+    assert(!isUnresolvedType(type));
+
+    // 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 @@ void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) {
 
   case NestedNameSpecifier::TypeSpec:
   case NestedNameSpecifier::TypeSpecWithTemplate:
-    mangleUnresolvedType(QualType(qualifier->getAsType(), 0));
+    manglePrefix(QualType(qualifier->getAsType(), 0));
     return;
 
   case NestedNameSpecifier::Identifier:
@@ -2552,8 +2624,8 @@ void CXXNameMangler::mangleTemplateArgs(
                           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 @@ void CXXNameMangler::mangleTemplateArgs(TemplateName Template,
     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';
 }
 
index 27777a51c4f1f1a2ea315785730d7a355398aa1d..01dcf8b2305afa86671c5f27ec14117e565c8c0d 100644 (file)
@@ -397,16 +397,16 @@ namespace test3 {
   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 @@ namespace test25 {
     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);
+  }
+}