From cc5e23ca8d11455acbd64fa0f88de15b55b9ff9f Mon Sep 17 00:00:00 2001
From: John McCall <rjmccall@apple.com>
Date: Sat, 5 Sep 2009 07:56:18 +0000
Subject: [PATCH] Overhaul the mangler to use a visitor pattern, at least for
 types.  We can safely ignore non-canonical type classes, but apparently we
 need to know how to mangle dependent names.

The missing cases are much more obvious now.

llvm-svn: 81070
---
 clang/lib/CodeGen/Mangle.cpp | 230 ++++++++++++++++++++---------------
 1 file changed, 134 insertions(+), 96 deletions(-)

diff --git a/clang/lib/CodeGen/Mangle.cpp b/clang/lib/CodeGen/Mangle.cpp
index 3d3efc62f95b..53a57d7de92c 100644
--- a/clang/lib/CodeGen/Mangle.cpp
+++ b/clang/lib/CodeGen/Mangle.cpp
@@ -23,6 +23,7 @@
 #include "clang/Basic/SourceManager.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/ErrorHandling.h"
 using namespace clang;
 
 namespace {
@@ -64,14 +65,16 @@ namespace {
     void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
     void mangleCVQualifiers(unsigned Quals);
     void mangleType(QualType T);
-    void mangleType(const BuiltinType *T);
-    void mangleType(const FunctionType *T);
-    void mangleBareFunctionType(const FunctionType *T, bool MangleReturnType);
-    void mangleType(const TagType *T);
-    void mangleType(const ArrayType *T);
-    void mangleType(const MemberPointerType *T);
-    void mangleType(const TemplateTypeParmType *T);
-    void mangleType(const ObjCInterfaceType *T);
+
+    // Declare manglers for every type class.
+#define ABSTRACT_TYPE(CLASS, PARENT)
+#define NON_CANONICAL_TYPE(CLASS, PARENT)
+#define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T);
+#include "clang/AST/TypeNodes.def"
+
+    void mangleType(const TagType*);
+    void mangleBareFunctionType(const FunctionType *T,
+                                bool MangleReturnType);
     void mangleExpression(Expr *E);
     void mangleCXXCtorType(CXXCtorType T);
     void mangleCXXDtorType(CXXDtorType T);
@@ -518,77 +521,24 @@ void CXXNameMangler::mangleType(QualType T) {
   // Only operate on the canonical type!
   T = Context.getCanonicalType(T);
 
-  // FIXME: Should we have a TypeNodes.def to make this easier? (YES!)
-
   //  <type> ::= <CV-qualifiers> <type>
   mangleCVQualifiers(T.getCVRQualifiers());
 
-  //         ::= <builtin-type>
-  if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr()))
-    mangleType(BT);
-  //         ::= <function-type>
-  else if (const FunctionType *FT = dyn_cast<FunctionType>(T.getTypePtr()))
-    mangleType(FT);
-  //         ::= <class-enum-type>
-  else if (const TagType *TT = dyn_cast<TagType>(T.getTypePtr()))
-    mangleType(TT);
-  //         ::= <array-type>
-  else if (const ArrayType *AT = dyn_cast<ArrayType>(T.getTypePtr()))
-    mangleType(AT);
-  //         ::= <pointer-to-member-type>
-  else if (const MemberPointerType *MPT 
-             = dyn_cast<MemberPointerType>(T.getTypePtr()))
-    mangleType(MPT);
-  //         ::= <template-param>
-  else if (const TemplateTypeParmType *TypeParm 
-             = dyn_cast<TemplateTypeParmType>(T.getTypePtr()))
-    mangleType(TypeParm);
-  //  FIXME: ::= <template-template-param> <template-args>
-  //  FIXME: ::= <substitution> # See Compression below
-  //         ::= P <type>   # pointer-to
-  else if (const PointerType *PT = dyn_cast<PointerType>(T.getTypePtr())) {
-    Out << 'P';
-    mangleType(PT->getPointeeType());
+  switch (T->getTypeClass()) {
+#define ABSTRACT_TYPE(CLASS, PARENT)
+#define NON_CANONICAL_TYPE(CLASS, PARENT) \
+  case Type::CLASS: \
+    llvm::llvm_unreachable("can't mangle non-canonical type " #CLASS "Type"); \
+    return;
+#define TYPE(CLASS, PARENT) \
+  case Type::CLASS: \
+    return mangleType(static_cast<CLASS##Type*>(T.getTypePtr()));
+#include "clang/AST/TypeNodes.def"
   }
-  else if (const ObjCObjectPointerType *PT = 
-           dyn_cast<ObjCObjectPointerType>(T.getTypePtr())) {
-    Out << 'P';
-    mangleType(PT->getPointeeType());
-  }
-  //         ::= R <type>   # reference-to
-  else if (const LValueReferenceType *RT =
-           dyn_cast<LValueReferenceType>(T.getTypePtr())) {
-    Out << 'R';
-    mangleType(RT->getPointeeType());
-  }
-  //         ::= O <type>   # rvalue reference-to (C++0x)
-  else if (const RValueReferenceType *RT =
-           dyn_cast<RValueReferenceType>(T.getTypePtr())) {
-    Out << 'O';
-    mangleType(RT->getPointeeType());
-  }
-  //         ::= C <type>   # complex pair (C 2000)
-  else if (const ComplexType *CT = dyn_cast<ComplexType>(T.getTypePtr())) {
-    Out << 'C';
-    mangleType(CT->getElementType());
-  } else if (const VectorType *VT = dyn_cast<VectorType>(T.getTypePtr())) {
-    // GNU extension: vector types
-    Out << "U8__vector";
-    mangleType(VT->getElementType());
-  } else if (const ObjCInterfaceType *IT = 
-             dyn_cast<ObjCInterfaceType>(T.getTypePtr())) {
-    mangleType(IT);
-  } else if (const ElaboratedType *ET =
-             dyn_cast<ElaboratedType>(T.getTypePtr())) {
-    mangleType(ET->getUnderlyingType());
-  }
-  // FIXME:  ::= G <type>   # imaginary (C 2000)
-  // FIXME:  ::= U <source-name> <type>     # vendor extended type qualifier
-  else
-    assert(false && "Cannot mangle unknown type");
 }
 
 void CXXNameMangler::mangleType(const BuiltinType *T) {
+  //  <type>         ::= <builtin-type>
   //  <builtin-type> ::= v  # void
   //                 ::= w  # wchar_t
   //                 ::= b  # bool
@@ -655,29 +605,32 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
   }
 }
 
-void CXXNameMangler::mangleType(const FunctionType *T) {
-  // <function-type> ::= F [Y] <bare-function-type> E
+// <type>          ::= <function-type>
+// <function-type> ::= F [Y] <bare-function-type> E
+void CXXNameMangler::mangleType(const FunctionProtoType *T) {
   Out << 'F';
   // FIXME: We don't have enough information in the AST to produce the 'Y'
   // encoding for extern "C" function types.
   mangleBareFunctionType(T, /*MangleReturnType=*/true);
   Out << 'E';
 }
-
+void CXXNameMangler::mangleType(const FunctionNoProtoType *T) {
+  llvm::llvm_unreachable("Can't mangle K&R function prototypes");
+}
 void CXXNameMangler::mangleBareFunctionType(const FunctionType *T,
                                             bool MangleReturnType) {
+  // We should never be mangling something without a prototype.
+  const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
+
   // <bare-function-type> ::= <signature type>+
   if (MangleReturnType)
-    mangleType(T->getResultType());
-
-  const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(T);
-  assert(Proto && "Can't mangle K&R function prototypes");
+    mangleType(Proto->getResultType());
 
   if (Proto->getNumArgs() == 0) {
     Out << 'v';
     return;
   }
-    
+  
   for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
                                          ArgEnd = Proto->arg_type_end(); 
        Arg != ArgEnd; ++Arg)
@@ -688,9 +641,15 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionType *T,
     Out << 'z';
 }
 
+// <type>            ::= <class-enum-type>
+// <class-enum-type> ::= <name>  
+void CXXNameMangler::mangleType(const EnumType *T) {
+  mangleType(static_cast<const TagType*>(T));
+}
+void CXXNameMangler::mangleType(const RecordType *T) {
+  mangleType(static_cast<const TagType*>(T));
+}
 void CXXNameMangler::mangleType(const TagType *T) {
-  //  <class-enum-type> ::= <name>
-  
   if (!T->getDecl()->getIdentifier())
     mangleName(T->getDecl()->getTypedefForAnonDecl());
   else
@@ -702,24 +661,33 @@ void CXXNameMangler::mangleType(const TagType *T) {
     mangleTemplateArgumentList(Spec->getTemplateArgs());
 }
 
-void CXXNameMangler::mangleType(const ArrayType *T) {
-  // <array-type> ::= A <positive dimension number> _ <element type>
-  //              ::= A [<dimension expression>] _ <element type>
+// <type>       ::= <array-type>
+// <array-type> ::= A <positive dimension number> _ <element type>
+//              ::= A [<dimension expression>] _ <element type>
+void CXXNameMangler::mangleType(const ConstantArrayType *T) {
+  Out << 'A' << T->getSize() << '_';
+  mangleType(T->getElementType());
+}
+void CXXNameMangler::mangleType(const VariableArrayType *T) {
   Out << 'A';
-  if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T))
-    Out << CAT->getSize();
-  else if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(T))
-    mangleExpression(VAT->getSizeExpr());
-  else if (const DependentSizedArrayType *DSAT 
-             = dyn_cast<DependentSizedArrayType>(T))
-    mangleExpression(DSAT->getSizeExpr());
-
+  mangleExpression(T->getSizeExpr());
   Out << '_';
   mangleType(T->getElementType());
 }
+void CXXNameMangler::mangleType(const DependentSizedArrayType *T) {
+  Out << 'A';
+  mangleExpression(T->getSizeExpr());
+  Out << '_';
+  mangleType(T->getElementType());
+}
+void CXXNameMangler::mangleType(const IncompleteArrayType *T) {
+  Out << 'A' << '_';
+  mangleType(T->getElementType());
+}
 
+// <type>                   ::= <pointer-to-member-type>
+// <pointer-to-member-type> ::= M <class type> <member type>
 void CXXNameMangler::mangleType(const MemberPointerType *T) {
-  //  <pointer-to-member-type> ::= M <class type> <member type>
   Out << 'M';
   mangleType(QualType(T->getClass(), 0));
   QualType PointeeType = T->getPointeeType();
@@ -730,23 +698,93 @@ void CXXNameMangler::mangleType(const MemberPointerType *T) {
     mangleType(PointeeType);
 }
 
+// <type>           ::= <template-param>
+// <template-param> ::= T_    # first template parameter
+//                  ::= T <parameter-2 non-negative number> _
 void CXXNameMangler::mangleType(const TemplateTypeParmType *T) {
-  // <template-param> ::= T_    # first template parameter
-  //                  ::= T <parameter-2 non-negative number> _
   if (T->getIndex() == 0)
     Out << "T_";
   else
     Out << 'T' << (T->getIndex() - 1) << '_';
 }
 
+// FIXME: <type> ::= <template-template-param> <template-args>
+// FIXME: <type> ::= <substitution> # See Compression below
+
+// <type> ::= P <type>   # pointer-to
+void CXXNameMangler::mangleType(const PointerType *T) {
+  Out << 'P';
+  mangleType(T->getPointeeType());
+}
+void CXXNameMangler::mangleType(const ObjCObjectPointerType *T) {
+  Out << 'P';
+  mangleType(T->getPointeeType());
+}
+
+// <type> ::= R <type>   # reference-to
+void CXXNameMangler::mangleType(const LValueReferenceType *T) {
+  Out << 'R';
+  mangleType(T->getPointeeType());
+}
+
+// <type> ::= O <type>   # rvalue reference-to (C++0x)
+void CXXNameMangler::mangleType(const RValueReferenceType *T) {
+  Out << 'O';
+  mangleType(T->getPointeeType());
+}
+
+// <type> ::= C <type>   # complex pair (C 2000)
+void CXXNameMangler::mangleType(const ComplexType *T) {
+  Out << 'C';
+  mangleType(T->getElementType());
+}
+
+// GNU extension: vector types
+void CXXNameMangler::mangleType(const VectorType *T) {
+  Out << "U8__vector";
+  mangleType(T->getElementType());
+}
+void CXXNameMangler::mangleType(const ExtVectorType *T) {
+  mangleType(static_cast<const VectorType*>(T));
+}
+void CXXNameMangler::mangleType(const DependentSizedExtVectorType *T) {
+  Out << "U8__vector";
+  mangleType(T->getElementType());
+}
+
 void CXXNameMangler::mangleType(const ObjCInterfaceType *T) {
   mangleSourceName(T->getDecl()->getIdentifier());
 }
 
+void CXXNameMangler::mangleType(const BlockPointerType *T) {
+  assert(false && "can't mangle block pointer types yet");
+}
+
+void CXXNameMangler::mangleType(const FixedWidthIntType *T) {
+  assert(false && "can't mangle arbitary-precision integer type yet");
+}
+
+void CXXNameMangler::mangleType(const TemplateSpecializationType *T) {
+  // TSTs are never canonical unless they're dependent.
+  assert(false && "can't mangle dependent template specializations yet");
+}
+
+void CXXNameMangler::mangleType(const TypenameType *T) {
+  assert(false && "can't mangle dependent typenames yet");
+}
+
+// FIXME: For now, just drop all extension qualifiers on the floor.
+void CXXNameMangler::mangleType(const ExtQualType *T) {
+  mangleType(QualType(T->getBaseType(), 0));
+}
+
 void CXXNameMangler::mangleExpression(Expr *E) {
   assert(false && "Cannot mangle expressions yet");
 }
 
+// FIXME: <type> ::= G <type>   # imaginary (C 2000)
+// FIXME: <type> ::= U <source-name> <type>     # vendor extended type qualifier
+
 void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) {
   // <ctor-dtor-name> ::= C1  # complete object constructor
   //                  ::= C2  # base object constructor