Clone the full Type hierarchy into the TypeLoc hierarchy.  Normalize
TypeLoc class names to be $(Type classname)Loc.  Rewrite the visitor.
Provide skeleton implementations for all the new TypeLocs.

Handle all cases in PCH.  Handle a few more cases when inserting
location information in SemaType.

It should be extremely straightforward to add new location information
to existing TypeLoc objects now.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84386 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 99b2a51..117f595 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/TypeLoc.h"
+#include "clang/AST/TypeLocVisitor.h"
 #include "clang/AST/Expr.h"
 #include "clang/Basic/PartialDiagnostic.h"
 #include "clang/Parse/DeclSpec.h"
@@ -1298,28 +1299,102 @@
   return T;
 }
 
-static void FillTypeSpecLoc(TypeLoc TSL, const DeclSpec &DS) {
-  if (TSL.isNull()) return;
+namespace {
+  class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {
+    const DeclSpec &DS;
 
-  if (TypedefLoc *TL = dyn_cast<TypedefLoc>(&TSL)) {
-    TL->setNameLoc(DS.getTypeSpecTypeLoc());
+  public:
+    TypeSpecLocFiller(const DeclSpec &DS) : DS(DS) {}
 
-  } else if (ObjCInterfaceLoc *TL = dyn_cast<ObjCInterfaceLoc>(&TSL)) {
-    TL->setNameLoc(DS.getTypeSpecTypeLoc());
+    void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+      Visit(TL.getUnqualifiedLoc());
+    }
+    void VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+      TL.setNameLoc(DS.getTypeSpecTypeLoc());
+    }
+    void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+      TL.setNameLoc(DS.getTypeSpecTypeLoc());
+    }
+    void VisitObjCProtocolListTypeLoc(ObjCProtocolListTypeLoc TL) {
+      assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
+      TL.setLAngleLoc(DS.getProtocolLAngleLoc());
+      TL.setRAngleLoc(DS.getSourceRange().getEnd());
+      for (unsigned i = 0; i != DS.getNumProtocolQualifiers(); ++i)
+        TL.setProtocolLoc(i, DS.getProtocolLocs()[i]);
 
-  } else if (ObjCProtocolListLoc *PLL = dyn_cast<ObjCProtocolListLoc>(&TSL)) {
-    assert(PLL->getNumProtocols() == DS.getNumProtocolQualifiers());
-    PLL->setLAngleLoc(DS.getProtocolLAngleLoc());
-    PLL->setRAngleLoc(DS.getSourceRange().getEnd());
-    for (unsigned i = 0; i != DS.getNumProtocolQualifiers(); ++i)
-      PLL->setProtocolLoc(i, DS.getProtocolLocs()[i]);
-    FillTypeSpecLoc(PLL->getBaseTypeLoc(), DS);
+      TypeLoc BaseLoc = TL.getBaseTypeLoc();
+      if (BaseLoc)
+        Visit(TL.getBaseTypeLoc());
+    }
+    void VisitTypeLoc(TypeLoc TL) {
+      // FIXME: add other typespec types and change this to an assert.
+      TL.initialize(DS.getTypeSpecTypeLoc());
+    }
+  };
 
-  } else {
-    //FIXME: Other typespecs.
-    DefaultTypeSpecLoc &DTL = cast<DefaultTypeSpecLoc>(TSL);
-    DTL.setStartLoc(DS.getSourceRange().getBegin());
-  }
+  class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> {
+    const DeclaratorChunk &Chunk;
+
+  public:
+    DeclaratorLocFiller(const DeclaratorChunk &Chunk) : Chunk(Chunk) {}
+
+    void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+      llvm::llvm_unreachable("qualified type locs not expected here!");
+    }
+
+    void VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::BlockPointer);
+      TL.setCaretLoc(Chunk.Loc);
+    }
+    void VisitPointerTypeLoc(PointerTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Pointer);
+      TL.setStarLoc(Chunk.Loc);
+    }
+    void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Pointer);
+      TL.setStarLoc(Chunk.Loc);
+    }
+    void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::MemberPointer);
+      TL.setStarLoc(Chunk.Loc);
+      // FIXME: nested name specifier
+    }
+    void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Reference);
+      assert(Chunk.Ref.LValueRef);
+      TL.setAmpLoc(Chunk.Loc);
+    }
+    void VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Reference);
+      assert(!Chunk.Ref.LValueRef);
+      TL.setAmpAmpLoc(Chunk.Loc);
+    }
+    void VisitArrayTypeLoc(ArrayTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Array);
+      TL.setLBracketLoc(Chunk.Loc);
+      TL.setRBracketLoc(Chunk.EndLoc);
+      TL.setSizeExpr(static_cast<Expr*>(Chunk.Arr.NumElts));
+    }
+    void VisitFunctionTypeLoc(FunctionTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Function);
+      TL.setLParenLoc(Chunk.Loc);
+      TL.setRParenLoc(Chunk.EndLoc);
+
+      const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun;
+      for (unsigned i = 0, e = FTI.NumArgs, tpi = 0; i != e; ++i) {
+        ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>();
+        if (Param) {
+          assert(tpi < TL.getNumArgs());
+          TL.setArg(tpi++, Param);
+        }
+      }
+      // FIXME: exception specs
+    }
+
+    void VisitTypeLoc(TypeLoc TL) {
+      llvm::llvm_unreachable("unsupported TypeLoc kind in declarator!");
+    }
+  };
 }
 
 /// \brief Create and instantiate a DeclaratorInfo with type source information.
@@ -1328,70 +1403,14 @@
 DeclaratorInfo *
 Sema::GetDeclaratorInfoForDeclarator(Declarator &D, QualType T, unsigned Skip) {
   DeclaratorInfo *DInfo = Context.CreateDeclaratorInfo(T);
-  TypeLoc CurrTL = DInfo->getTypeLoc();
+  UnqualTypeLoc CurrTL = DInfo->getTypeLoc().getUnqualifiedLoc();
 
   for (unsigned i = Skip, e = D.getNumTypeObjects(); i != e; ++i) {
-    assert(!CurrTL.isNull());
-    
-    // Don't bother recording source locations for qualifiers.
-    CurrTL = CurrTL.getUnqualifiedLoc();
-
-    DeclaratorChunk &DeclType = D.getTypeObject(i);
-    switch (DeclType.Kind) {
-    default: assert(0 && "Unknown decltype!");
-    case DeclaratorChunk::BlockPointer: {
-      BlockPointerLoc &BPL = cast<BlockPointerLoc>(CurrTL);
-      BPL.setCaretLoc(DeclType.Loc);
-      break;
-    }
-    case DeclaratorChunk::Pointer: {
-      //FIXME: ObjCObject pointers.
-      PointerLoc &PL = cast<PointerLoc>(CurrTL);
-      PL.setStarLoc(DeclType.Loc);
-      break;
-    }
-    case DeclaratorChunk::Reference: {
-      ReferenceLoc &RL = cast<ReferenceLoc>(CurrTL);
-      RL.setAmpLoc(DeclType.Loc);
-      break;
-    }
-    case DeclaratorChunk::Array: {
-      DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr;
-      ArrayLoc &AL = cast<ArrayLoc>(CurrTL);
-      AL.setLBracketLoc(DeclType.Loc);
-      AL.setRBracketLoc(DeclType.EndLoc);
-      AL.setSizeExpr(static_cast<Expr*>(ATI.NumElts));
-      //FIXME: Star location for [*].
-      break;
-    }
-    case DeclaratorChunk::Function: {
-      const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
-      FunctionLoc &FL = cast<FunctionLoc>(CurrTL);
-      FL.setLParenLoc(DeclType.Loc);
-      FL.setRParenLoc(DeclType.EndLoc);
-      for (unsigned i = 0, e = FTI.NumArgs, tpi = 0; i != e; ++i) {
-        ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>();
-        if (Param) {
-          assert(tpi < FL.getNumArgs());
-          FL.setArg(tpi++, Param);
-        }
-      }
-      break;
-      //FIXME: Exception specs.
-    }
-    case DeclaratorChunk::MemberPointer: {
-      MemberPointerLoc &MPL = cast<MemberPointerLoc>(CurrTL);
-      MPL.setStarLoc(DeclType.Loc);
-      //FIXME: Class location.
-      break;
-    }
-
-    }
-
-    CurrTL = CurrTL.getNextTypeLoc();
+    DeclaratorLocFiller(D.getTypeObject(i)).Visit(CurrTL);
+    CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
   }
   
-  FillTypeSpecLoc(CurrTL, D.getDeclSpec());
+  TypeSpecLocFiller(D.getDeclSpec()).Visit(CurrTL);
 
   return DInfo;
 }