Be more thorough about mangling unresolved types.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134011 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 81c6543..9f30f6e 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -256,9 +256,6 @@
                             DeclarationName name,
                             unsigned KnownArity = UnknownArity);
 
-  static bool isUnresolvedType(const Type *type);
-  void mangleUnresolvedType(const Type *type);
-
   void mangleName(const TemplateDecl *TD,
                   const TemplateArgument *TemplateArgs,
                   unsigned NumTemplateArgs);
@@ -703,31 +700,6 @@
   }
 }
 
-/// 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
@@ -795,45 +767,118 @@
     } 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;
-      }
     }
 
-    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)) {
+    switch (type->getTypeClass()) {
+    case Type::Builtin:
+    case Type::Complex:
+    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::SubstTemplateTypeParmPack:
+    case Type::ObjCObject:
+    case Type::ObjCInterface:
+    case Type::ObjCObjectPointer:
+      llvm_unreachable("type is illegal as a nested name specifier");
+
+    // <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:
+    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.
+      mangleType(QualType(type, 0));
+
+      // We never want to print 'E' directly after an unresolved-type,
+      // so we return directly.
+      return;
+
+    // Substituted template type parameters should only come up with
+    // enclosing templates.
+    // <unresolved-type> ::= <existing-substitution> [ <template-args> ]
+    case Type::SubstTemplateTypeParm: {
+      if (recursive) Out << 'N';
+
+      bool wasSubstituted = mangleSubstitution(QualType(type, 0));
+      assert(wasSubstituted && "no substitution for outer template argument?");
+      (void) wasSubstituted;
+      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);
       TemplateDecl *temp = tst->getTemplateName().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());
       mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs());
-    } else if (const DependentTemplateSpecializationType *tst
-                 = dyn_cast<DependentTemplateSpecializationType>(type)) {
+      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());
       mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs());
-    } else {
-      llvm_unreachable("unexpected type in nested name specifier!");
+      break;
+    }
     }
     break;
   }