[cfe-commits] r84716 - in /cfe/trunk/lib/Sema: SemaTemplate.cpp SemaTemplateInstantiate.cpp TreeTransform.h

John McCall rjmccall at apple.com
Tue Oct 20 17:40:47 PDT 2009


Author: rjmccall
Date: Tue Oct 20 19:40:46 2009
New Revision: 84716

URL: http://llvm.org/viewvc/llvm-project?rev=84716&view=rev
Log:
Rewrite TreeTransform to transform types as DeclaratorInfos rather than as bare
QualTypes.  Don't actually exploit this yet.


Modified:
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/TreeTransform.h

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=84716&r1=84715&r2=84716&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Oct 20 19:40:46 2009
@@ -4265,12 +4265,27 @@
     /// \brief Transforms a typename type by determining whether the type now
     /// refers to a member of the current instantiation, and then
     /// type-checking and building a QualifiedNameType (when possible).
-    QualType TransformTypenameType(const TypenameType *T);
+    QualType TransformTypenameType(TypeLocBuilder &TLB, TypenameTypeLoc TL);
+    QualType TransformTypenameType(TypenameType *T);
   };
 }
 
 QualType
-CurrentInstantiationRebuilder::TransformTypenameType(const TypenameType *T) {
+CurrentInstantiationRebuilder::TransformTypenameType(TypeLocBuilder &TLB,
+                                                     TypenameTypeLoc TL) {
+  QualType Result = TransformTypenameType(TL.getTypePtr());
+  if (Result.isNull())
+    return QualType();
+
+  TypenameTypeLoc NewTL = TLB.push<TypenameTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+QualType
+CurrentInstantiationRebuilder::TransformTypenameType(TypenameType *T) {
+
   NestedNameSpecifier *NNS
     = TransformNestedNameSpecifier(T->getQualifier(),
                               /*FIXME:*/SourceRange(getBaseLocation()));

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=84716&r1=84715&r2=84716&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Oct 20 19:40:46 2009
@@ -420,7 +420,8 @@
 
     /// \brief Transforms a template type parameter type by performing
     /// substitution of the corresponding template type argument.
-    QualType TransformTemplateTypeParmType(const TemplateTypeParmType *T);
+    QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
+                                           TemplateTypeParmTypeLoc TL);
   };
 }
 
@@ -625,8 +626,9 @@
 }
 
 QualType
-TemplateInstantiator::TransformTemplateTypeParmType(
-                                              const TemplateTypeParmType *T) {
+TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
+                                                TemplateTypeParmTypeLoc TL) {
+  TemplateTypeParmType *T = TL.getTypePtr();
   if (T->getDepth() < TemplateArgs.getNumLevels()) {
     // Replace the template type parameter with its corresponding
     // template argument.
@@ -635,8 +637,12 @@
     // because we are performing instantiation from explicitly-specified
     // template arguments in a function template class, but there were some
     // arguments left unspecified.
-    if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex()))
-      return QualType(T, 0);
+    if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex())) {
+      TemplateTypeParmTypeLoc NewTL
+        = TLB.push<TemplateTypeParmTypeLoc>(TL.getType());
+      NewTL.setNameLoc(TL.getNameLoc());
+      return TL.getType();
+    }
 
     assert(TemplateArgs(T->getDepth(), T->getIndex()).getKind()
              == TemplateArgument::Type &&
@@ -646,18 +652,27 @@
       = TemplateArgs(T->getDepth(), T->getIndex()).getAsType();
 
     // TODO: only do this uniquing once, at the start of instantiation.
-    return getSema().Context.getSubstTemplateTypeParmType(T, Replacement);
+    QualType Result
+      = getSema().Context.getSubstTemplateTypeParmType(T, Replacement);
+    SubstTemplateTypeParmTypeLoc NewTL
+      = TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
+    NewTL.setNameLoc(TL.getNameLoc());
+    return Result;
   }
 
   // The template type parameter comes from an inner template (e.g.,
   // the template parameter list of a member template inside the
   // template we are instantiating). Create a new template type
   // parameter with the template "level" reduced by one.
-  return getSema().Context.getTemplateTypeParmType(
-                                  T->getDepth() - TemplateArgs.getNumLevels(),
-                                                   T->getIndex(),
-                                                   T->isParameterPack(),
-                                                   T->getName());
+  QualType Result
+    = getSema().Context.getTemplateTypeParmType(T->getDepth()
+                                                 - TemplateArgs.getNumLevels(),
+                                                T->getIndex(),
+                                                T->isParameterPack(),
+                                                T->getName());
+  TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+  return Result;
 }
 
 /// \brief Perform substitution on the type T with a given set of template

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=84716&r1=84715&r2=84716&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Oct 20 19:40:46 2009
@@ -1,4 +1,4 @@
-//===------- TreeTransform.h - Semantic Tree Transformation ---------------===/
+//===------- TreeTransform.h - Semantic Tree Transformation -----*- C++ -*-===/
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -22,9 +22,11 @@
 #include "clang/AST/Stmt.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/StmtObjC.h"
+#include "clang/AST/TypeLocBuilder.h"
 #include "clang/Parse/Ownership.h"
 #include "clang/Parse/Designator.h"
 #include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/ErrorHandling.h"
 #include <algorithm>
 
 namespace clang {
@@ -170,25 +172,30 @@
 
   /// \brief Transforms the given type into another type.
   ///
-  /// By default, this routine transforms a type by delegating to the
-  /// appropriate TransformXXXType to build a new type, then applying
-  /// the qualifiers on \p T to the resulting type with AddTypeQualifiers.
-  /// Subclasses may override this function (to take over all type
-  /// transformations), some set of the TransformXXXType functions, or
-  /// the AddTypeQualifiers function to alter the transformation.
+  /// By default, this routine transforms a type by creating a
+  /// DeclaratorInfo for it and delegating to the appropriate
+  /// function.  This is expensive, but we don't mind, because
+  /// this method is deprecated anyway;  all users should be
+  /// switched to storing DeclaratorInfos.
   ///
   /// \returns the transformed type.
   QualType TransformType(QualType T);
 
-  /// \brief Transform the given type by adding the given set of qualifiers
-  /// and returning the result.
+  /// \brief Transforms the given type-with-location into a new
+  /// type-with-location.
+  ///
+  /// By default, this routine transforms a type by delegating to the
+  /// appropriate TransformXXXType to build a new type.  Subclasses
+  /// may override this function (to take over all type
+  /// transformations) or some set of the TransformXXXType functions
+  /// to alter the transformation.
+  DeclaratorInfo *TransformType(DeclaratorInfo *DI);
+
+  /// \brief Transform the given type-with-location into a new
+  /// type, collecting location information in the given builder
+  /// as necessary.
   ///
-  /// FIXME: By default, this routine adds type qualifiers only to types that
-  /// can have qualifiers, and silently suppresses those qualifiers that are
-  /// not permitted (e.g., qualifiers on reference or function types). This
-  /// is the right thing for template instantiation, but probably not for
-  /// other clients.
-  QualType AddTypeQualifiers(QualType T, Qualifiers Qs);
+  QualType TransformType(TypeLocBuilder &TLB, TypeLoc TL);
 
   /// \brief Transform the given statement.
   ///
@@ -285,10 +292,10 @@
   /// override this function to provide alternate behavior.
   TemplateArgument TransformTemplateArgument(const TemplateArgument &Arg);
 
-#define ABSTRACT_TYPE(CLASS, PARENT)
-#define TYPE(CLASS, PARENT)                                   \
-  QualType Transform##CLASS##Type(const CLASS##Type *T);
-#include "clang/AST/TypeNodes.def"
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT)                                   \
+  QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T);
+#include "clang/AST/TypeLocNodes.def"
 
   QualType 
   TransformTemplateSpecializationType(const TemplateSpecializationType *T,
@@ -334,6 +341,9 @@
   /// type. Subclasses may override this routine to provide different behavior.
   QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType);
 
+  /// \brief Build a new Objective C object pointer type.
+  QualType RebuildObjCObjectPointerType(QualType PointeeType);
+
   /// \brief Build a new array type given the element type, size
   /// modifier, size of the array (if known), size expression, and index type
   /// qualifiers.
@@ -422,6 +432,9 @@
                                     unsigned NumParamTypes,
                                     bool Variadic, unsigned Quals);
 
+  /// \brief Build a new unprototyped function type.
+  QualType RebuildFunctionNoProtoType(QualType ResultType);
+
   /// \brief Build a new typedef type.
   QualType RebuildTypedefType(TypedefDecl *Typedef) {
     return SemaRef.Context.getTypeDeclType(Typedef);
@@ -501,6 +514,14 @@
                                   SourceRange(getDerived().getBaseLocation()));
   }
 
+  /// \brief Rebuild an objective C protocol list type.
+  QualType RebuildObjCProtocolListType(QualType BaseType,
+                                       ObjCProtocolDecl **Protocols,
+                                       unsigned NumProtocols) {
+    return SemaRef.Context.getObjCProtocolListType(BaseType, Protocols,
+                                                   NumProtocols);
+  }
+
   /// \brief Build a new nested-name-specifier given the prefix and an
   /// identifier that names the next step in the nested-name-specifier.
   ///
@@ -1939,222 +1960,369 @@
   if (getDerived().AlreadyTransformed(T))
     return T;
 
-  QualifierCollector Qs;
-  const Type *Ty = Qs.strip(T);
+  // Temporary workaround.  All of these transformations should
+  // eventually turn into transformations on TypeLocs.
+  DeclaratorInfo *DI = getSema().Context.CreateDeclaratorInfo(T);
+  DI->getTypeLoc().initialize(getBaseLocation());
+  
+  DeclaratorInfo *NewDI = getDerived().TransformType(DI);
 
-  QualType Result;
-  switch (Ty->getTypeClass()) {
-#define ABSTRACT_TYPE(CLASS, PARENT)
-#define TYPE(CLASS, PARENT)                                                  \
-    case Type::CLASS:                                                        \
-      Result = getDerived().Transform##CLASS##Type(                          \
-                                       static_cast<const CLASS##Type*>(Ty)); \
-      break;
-#include "clang/AST/TypeNodes.def"
-  }
+  if (!NewDI)
+    return QualType();
 
-  if (Result.isNull() || T == Result)
-    return Result;
+  return NewDI->getType();
+}
+
+template<typename Derived>
+DeclaratorInfo *TreeTransform<Derived>::TransformType(DeclaratorInfo *DI) {
+  if (getDerived().AlreadyTransformed(DI->getType()))
+    return DI;
+
+  TypeLocBuilder TLB;
+
+  TypeLoc TL = DI->getTypeLoc();
+  TLB.reserve(TL.getFullDataSize());
 
-  return getDerived().AddTypeQualifiers(Result, Qs);
+  QualType Result = getDerived().TransformType(TLB, TL);
+  if (Result.isNull())
+    return 0;
+
+  return TLB.getDeclaratorInfo(SemaRef.Context, Result);
 }
 
 template<typename Derived>
 QualType
-TreeTransform<Derived>::AddTypeQualifiers(QualType T, Qualifiers Quals) {
-  if (!Quals.empty() && !T->isFunctionType() && !T->isReferenceType())
-    return SemaRef.Context.getQualifiedType(T, Quals);
+TreeTransform<Derived>::TransformType(TypeLocBuilder &TLB, TypeLoc T) {
+  switch (T.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+  case TypeLoc::CLASS: \
+    return getDerived().Transform##CLASS##Type(TLB, cast<CLASS##TypeLoc>(T));
+#include "clang/AST/TypeLocNodes.def"
+  }
+
+  llvm::llvm_unreachable("unhandled type loc!");
+  return QualType();
+}
+
+/// FIXME: By default, this routine adds type qualifiers only to types
+/// that can have qualifiers, and silently suppresses those qualifiers
+/// that are not permitted (e.g., qualifiers on reference or function
+/// types). This is the right thing for template instantiation, but
+/// probably not for other clients.
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
+                                               QualifiedTypeLoc T) {
+  Qualifiers Quals = T.getType().getQualifiers();
 
-  return T;
+  QualType Result = getDerived().TransformType(TLB, T.getUnqualifiedLoc());
+  if (Result.isNull())
+    return QualType();
+
+  // Silently suppress qualifiers if the result type can't be qualified.
+  // FIXME: this is the right thing for template instantiation, but
+  // probably not for other clients.
+  if (Result->isFunctionType() || Result->isReferenceType())
+    return Result;
+
+  Result = SemaRef.Context.getQualifiedType(Result, Quals);
+
+  TLB.push<QualifiedTypeLoc>(Result);
+
+  // No location information to preserve.
+
+  return Result;
 }
 
-template<typename Derived>
-QualType TreeTransform<Derived>::TransformBuiltinType(const BuiltinType *T) {
-  // Nothing to do
-  return QualType(T, 0);
+template <class TyLoc> static inline
+QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) {
+  TyLoc NewT = TLB.push<TyLoc>(T.getType());
+  NewT.setNameLoc(T.getNameLoc());
+  return T.getType();
+}
+
+// Ugly metaprogramming macros because I couldn't be bothered to make
+// the equivalent template version work.
+#define TransformPointerLikeType(TypeClass) do { \
+  QualType PointeeType                                       \
+    = getDerived().TransformType(TLB, TL.getPointeeLoc());   \
+  if (PointeeType.isNull())                                  \
+    return QualType();                                       \
+                                                             \
+  QualType Result = TL.getType();                            \
+  if (getDerived().AlwaysRebuild() ||                        \
+      PointeeType != TL.getPointeeLoc().getType()) {         \
+    Result = getDerived().Rebuild##TypeClass(PointeeType);   \
+    if (Result.isNull())                                     \
+      return QualType();                                     \
+  }                                                          \
+                                                             \
+  TypeClass##Loc NewT = TLB.push<TypeClass##Loc>(Result);    \
+  NewT.setSigilLoc(TL.getSigilLoc());                        \
+                                                             \
+  return Result;                                             \
+} while(0)
+
+// Reference collapsing forces us to transform reference types
+// differently from the other pointer-like types.
+#define TransformReferenceType(TypeClass) do { \
+  QualType PointeeType                                       \
+    = getDerived().TransformType(TLB, TL.getPointeeLoc());   \
+  if (PointeeType.isNull())                                  \
+    return QualType();                                       \
+                                                             \
+  QualType Result = TL.getType();                            \
+  if (getDerived().AlwaysRebuild() ||                        \
+      PointeeType != TL.getPointeeLoc().getType()) {         \
+    Result = getDerived().Rebuild##TypeClass(PointeeType);   \
+    if (Result.isNull())                                     \
+      return QualType();                                     \
+  }                                                          \
+                                                             \
+  /* Workaround: rebuild doesn't always change the type */   \
+  /* FIXME: avoid losing this location information. */       \
+  if (Result == PointeeType)                                 \
+    return Result;                                           \
+  ReferenceTypeLoc NewTL;                                    \
+  if (isa<LValueReferenceType>(Result))                      \
+    NewTL = TLB.push<LValueReferenceTypeLoc>(Result);        \
+  else                                                       \
+    NewTL = TLB.push<RValueReferenceTypeLoc>(Result);        \
+  NewTL.setSigilLoc(TL.getSigilLoc());                       \
+  return Result;                                             \
+} while (0)
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformBuiltinType(TypeLocBuilder &TLB,
+                                                      BuiltinTypeLoc T) {
+  return TransformTypeSpecType(TLB, T);
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::TransformFixedWidthIntType(
-                                                  const FixedWidthIntType *T) {
-  // FIXME: Implement
-  return QualType(T, 0);
+QualType
+TreeTransform<Derived>::TransformFixedWidthIntType(TypeLocBuilder &TLB,
+                                                   FixedWidthIntTypeLoc T) {
+  return TransformTypeSpecType(TLB, T);
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::TransformComplexType(const ComplexType *T) {
-  // FIXME: Implement
-  return QualType(T, 0);
+QualType TreeTransform<Derived>::TransformComplexType(TypeLocBuilder &TLB,
+                                                      ComplexTypeLoc T) {
+  // FIXME: recurse?
+  return TransformTypeSpecType(TLB, T);
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::TransformPointerType(const PointerType *T) {
-  QualType PointeeType = getDerived().TransformType(T->getPointeeType());
-  if (PointeeType.isNull())
-    return QualType();
-
-  if (!getDerived().AlwaysRebuild() &&
-      PointeeType == T->getPointeeType())
-    return QualType(T, 0);
-
-  return getDerived().RebuildPointerType(PointeeType);
+QualType TreeTransform<Derived>::TransformPointerType(TypeLocBuilder &TLB,
+                                                      PointerTypeLoc TL) {
+  TransformPointerLikeType(PointerType);
 }
 
 template<typename Derived>
 QualType
-TreeTransform<Derived>::TransformBlockPointerType(const BlockPointerType *T) {
-  QualType PointeeType = getDerived().TransformType(T->getPointeeType());
-  if (PointeeType.isNull())
-    return QualType();
-
-  if (!getDerived().AlwaysRebuild() &&
-      PointeeType == T->getPointeeType())
-    return QualType(T, 0);
-
-  return getDerived().RebuildBlockPointerType(PointeeType);
+TreeTransform<Derived>::TransformBlockPointerType(TypeLocBuilder &TLB,
+                                                  BlockPointerTypeLoc TL) {
+  TransformPointerLikeType(BlockPointerType);
 }
 
 template<typename Derived>
 QualType
-TreeTransform<Derived>::TransformLValueReferenceType(
-                                               const LValueReferenceType *T) {
-  QualType PointeeType = getDerived().TransformType(T->getPointeeType());
-  if (PointeeType.isNull())
-    return QualType();
-
-  if (!getDerived().AlwaysRebuild() &&
-      PointeeType == T->getPointeeType())
-    return QualType(T, 0);
-
-  return getDerived().RebuildLValueReferenceType(PointeeType);
+TreeTransform<Derived>::TransformLValueReferenceType(TypeLocBuilder &TLB,
+                                                 LValueReferenceTypeLoc TL) {
+  TransformReferenceType(LValueReferenceType);
 }
 
 template<typename Derived>
 QualType
-TreeTransform<Derived>::TransformRValueReferenceType(
-                                              const RValueReferenceType *T) {
-  QualType PointeeType = getDerived().TransformType(T->getPointeeType());
-  if (PointeeType.isNull())
-    return QualType();
-
-  if (!getDerived().AlwaysRebuild() &&
-      PointeeType == T->getPointeeType())
-    return QualType(T, 0);
-
-  return getDerived().RebuildRValueReferenceType(PointeeType);
+TreeTransform<Derived>::TransformRValueReferenceType(TypeLocBuilder &TLB,
+                                                 RValueReferenceTypeLoc TL) {
+  TransformReferenceType(RValueReferenceType);
 }
 
 template<typename Derived>
 QualType
-TreeTransform<Derived>::TransformMemberPointerType(const MemberPointerType *T) {
-  QualType PointeeType = getDerived().TransformType(T->getPointeeType());
+TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
+                                                   MemberPointerTypeLoc TL) {
+  MemberPointerType *T = TL.getTypePtr();
+
+  QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc());
   if (PointeeType.isNull())
     return QualType();
 
-  QualType ClassType = getDerived().TransformType(QualType(T->getClass(), 0));
+  // TODO: preserve source information for this.
+  QualType ClassType
+    = getDerived().TransformType(QualType(T->getClass(), 0));
   if (ClassType.isNull())
     return QualType();
 
-  if (!getDerived().AlwaysRebuild() &&
-      PointeeType == T->getPointeeType() &&
-      ClassType == QualType(T->getClass(), 0))
-    return QualType(T, 0);
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      PointeeType != T->getPointeeType() ||
+      ClassType != QualType(T->getClass(), 0)) {
+    Result = getDerived().RebuildMemberPointerType(PointeeType, ClassType);
+    if (Result.isNull())
+      return QualType();
+  }
+
+  MemberPointerTypeLoc NewTL = TLB.push<MemberPointerTypeLoc>(Result);
+  NewTL.setSigilLoc(TL.getSigilLoc());
 
-  return getDerived().RebuildMemberPointerType(PointeeType, ClassType);
+  return Result;
 }
 
 template<typename Derived>
 QualType
-TreeTransform<Derived>::TransformConstantArrayType(const ConstantArrayType *T) {
-  QualType ElementType = getDerived().TransformType(T->getElementType());
+TreeTransform<Derived>::TransformConstantArrayType(TypeLocBuilder &TLB,
+                                                   ConstantArrayTypeLoc TL) {
+  ConstantArrayType *T = TL.getTypePtr();
+  QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
   if (ElementType.isNull())
     return QualType();
 
-  if (!getDerived().AlwaysRebuild() &&
-      ElementType == T->getElementType())
-    return QualType(T, 0);
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType()) {
+    Result = getDerived().RebuildConstantArrayType(ElementType,
+                                                   T->getSizeModifier(),
+                                                   T->getSize(),
+                                             T->getIndexTypeCVRQualifiers());
+    if (Result.isNull())
+      return QualType();
+  }
+  
+  ConstantArrayTypeLoc NewTL = TLB.push<ConstantArrayTypeLoc>(Result);
+  NewTL.setLBracketLoc(TL.getLBracketLoc());
+  NewTL.setRBracketLoc(TL.getRBracketLoc());
 
-  return getDerived().RebuildConstantArrayType(ElementType,
-                                               T->getSizeModifier(),
-                                               T->getSize(),
-                                               T->getIndexTypeCVRQualifiers());
+  Expr *Size = TL.getSizeExpr();
+  if (Size) {
+    EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+    Size = getDerived().TransformExpr(Size).template takeAs<Expr>();
+  }
+  NewTL.setSizeExpr(Size);
+
+  return Result;
 }
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformIncompleteArrayType(
-                                              const IncompleteArrayType *T) {
-  QualType ElementType = getDerived().TransformType(T->getElementType());
+                                              TypeLocBuilder &TLB,
+                                              IncompleteArrayTypeLoc TL) {
+  IncompleteArrayType *T = TL.getTypePtr();
+  QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
   if (ElementType.isNull())
     return QualType();
 
-  if (!getDerived().AlwaysRebuild() &&
-      ElementType == T->getElementType())
-    return QualType(T, 0);
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType()) {
+    Result = getDerived().RebuildIncompleteArrayType(ElementType,
+                                                     T->getSizeModifier(),
+                                             T->getIndexTypeCVRQualifiers());
+    if (Result.isNull())
+      return QualType();
+  }
+  
+  IncompleteArrayTypeLoc NewTL = TLB.push<IncompleteArrayTypeLoc>(Result);
+  NewTL.setLBracketLoc(TL.getLBracketLoc());
+  NewTL.setRBracketLoc(TL.getRBracketLoc());
+  NewTL.setSizeExpr(0);
 
-  return getDerived().RebuildIncompleteArrayType(ElementType,
-                                                 T->getSizeModifier(),
-                                               T->getIndexTypeCVRQualifiers());
+  return Result;
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::TransformVariableArrayType(
-                                                  const VariableArrayType *T) {
-  QualType ElementType = getDerived().TransformType(T->getElementType());
+QualType
+TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB,
+                                                   VariableArrayTypeLoc TL) {
+  VariableArrayType *T = TL.getTypePtr();
+  QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
   if (ElementType.isNull())
     return QualType();
 
   // Array bounds are not potentially evaluated contexts
   EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
 
-  Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
-  if (Size.isInvalid())
+  Sema::OwningExprResult SizeResult
+    = getDerived().TransformExpr(T->getSizeExpr());
+  if (SizeResult.isInvalid())
     return QualType();
 
-  if (!getDerived().AlwaysRebuild() &&
-      ElementType == T->getElementType() &&
-      Size.get() == T->getSizeExpr()) {
-    Size.take();
-    return QualType(T, 0);
+  Expr *Size = static_cast<Expr*>(SizeResult.get());
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType() ||
+      Size != T->getSizeExpr()) {
+    Result = getDerived().RebuildVariableArrayType(ElementType,
+                                                   T->getSizeModifier(),
+                                                   move(SizeResult),
+                                             T->getIndexTypeCVRQualifiers(),
+                                                   T->getBracketsRange());
+    if (Result.isNull())
+      return QualType();
   }
+  else SizeResult.take();
+  
+  VariableArrayTypeLoc NewTL = TLB.push<VariableArrayTypeLoc>(Result);
+  NewTL.setLBracketLoc(TL.getLBracketLoc());
+  NewTL.setRBracketLoc(TL.getRBracketLoc());
+  NewTL.setSizeExpr(Size);
 
-  return getDerived().RebuildVariableArrayType(ElementType,
-                                               T->getSizeModifier(),
-                                               move(Size),
-                                               T->getIndexTypeCVRQualifiers(),
-                                               T->getBracketsRange());
+  return Result;
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::TransformDependentSizedArrayType(
-                                          const DependentSizedArrayType *T) {
-  QualType ElementType = getDerived().TransformType(T->getElementType());
+QualType
+TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB,
+                                             DependentSizedArrayTypeLoc TL) {
+  DependentSizedArrayType *T = TL.getTypePtr();
+  QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
   if (ElementType.isNull())
     return QualType();
 
   // Array bounds are not potentially evaluated contexts
   EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
 
-  Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
-  if (Size.isInvalid())
+  Sema::OwningExprResult SizeResult
+    = getDerived().TransformExpr(T->getSizeExpr());
+  if (SizeResult.isInvalid())
     return QualType();
 
-  if (!getDerived().AlwaysRebuild() &&
-      ElementType == T->getElementType() &&
-      Size.get() == T->getSizeExpr()) {
-    Size.take();
-    return QualType(T, 0);
+  Expr *Size = static_cast<Expr*>(SizeResult.get());
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType() ||
+      Size != T->getSizeExpr()) {
+    Result = getDerived().RebuildDependentSizedArrayType(ElementType,
+                                                         T->getSizeModifier(),
+                                                         move(SizeResult),
+                                                T->getIndexTypeCVRQualifiers(),
+                                                        T->getBracketsRange());
+    if (Result.isNull())
+      return QualType();
   }
+  else SizeResult.take();
 
-  return getDerived().RebuildDependentSizedArrayType(ElementType,
-                                                     T->getSizeModifier(),
-                                                     move(Size),
-                                            T->getIndexTypeCVRQualifiers(),
-                                                     T->getBracketsRange());
+  // We might have any sort of array type now, but fortunately they
+  // all have the same location layout.
+  ArrayTypeLoc NewTL = TLB.push<ArrayTypeLoc>(Result);
+  NewTL.setLBracketLoc(TL.getLBracketLoc());
+  NewTL.setRBracketLoc(TL.getRBracketLoc());
+  NewTL.setSizeExpr(Size);
+
+  return Result;
 }
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
-                                      const DependentSizedExtVectorType *T) {
+                                      TypeLocBuilder &TLB,
+                                      DependentSizedExtVectorTypeLoc TL) {
+  DependentSizedExtVectorType *T = TL.getTypePtr();
+
+  // FIXME: ext vector locs should be nested
   QualType ElementType = getDerived().TransformType(T->getElementType());
   if (ElementType.isNull())
     return QualType();
@@ -2166,98 +2334,202 @@
   if (Size.isInvalid())
     return QualType();
 
-  if (!getDerived().AlwaysRebuild() &&
-      ElementType == T->getElementType() &&
-      Size.get() == T->getSizeExpr()) {
-    Size.take();
-    return QualType(T, 0);
-  }
-
-  return getDerived().RebuildDependentSizedExtVectorType(ElementType,
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType() &&
+      Size.get() != T->getSizeExpr()) {
+    Result = getDerived().RebuildDependentSizedExtVectorType(ElementType,
                                                          move(Size),
                                                          T->getAttributeLoc());
+    if (Result.isNull())
+      return QualType();
+  }
+  else Size.take();
+
+  // Result might be dependent or not.
+  if (isa<DependentSizedExtVectorType>(Result)) {
+    DependentSizedExtVectorTypeLoc NewTL
+      = TLB.push<DependentSizedExtVectorTypeLoc>(Result);
+    NewTL.setNameLoc(TL.getNameLoc());
+  } else {
+    ExtVectorTypeLoc NewTL = TLB.push<ExtVectorTypeLoc>(Result);
+    NewTL.setNameLoc(TL.getNameLoc());
+  }
+
+  return Result;
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::TransformVectorType(const VectorType *T) {
+QualType TreeTransform<Derived>::TransformVectorType(TypeLocBuilder &TLB,
+                                                     VectorTypeLoc TL) {
+  VectorType *T = TL.getTypePtr();
   QualType ElementType = getDerived().TransformType(T->getElementType());
   if (ElementType.isNull())
     return QualType();
 
-  if (!getDerived().AlwaysRebuild() &&
-      ElementType == T->getElementType())
-    return QualType(T, 0);
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType()) {
+    Result = getDerived().RebuildVectorType(ElementType, T->getNumElements());
+    if (Result.isNull())
+      return QualType();
+  }
+  
+  VectorTypeLoc NewTL = TLB.push<VectorTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
 
-  return getDerived().RebuildVectorType(ElementType, T->getNumElements());
+  return Result;
 }
 
 template<typename Derived>
-QualType
-TreeTransform<Derived>::TransformExtVectorType(const ExtVectorType *T) {
+QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB,
+                                                        ExtVectorTypeLoc TL) {
+  VectorType *T = TL.getTypePtr();
   QualType ElementType = getDerived().TransformType(T->getElementType());
   if (ElementType.isNull())
     return QualType();
 
-  if (!getDerived().AlwaysRebuild() &&
-      ElementType == T->getElementType())
-    return QualType(T, 0);
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType()) {
+    Result = getDerived().RebuildExtVectorType(ElementType,
+                                               T->getNumElements(),
+                                               /*FIXME*/ SourceLocation());
+    if (Result.isNull())
+      return QualType();
+  }
+  
+  ExtVectorTypeLoc NewTL = TLB.push<ExtVectorTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
 
-  return getDerived().RebuildExtVectorType(ElementType, T->getNumElements(),
-                                           /*FIXME*/SourceLocation());
+  return Result;
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::TransformFunctionProtoType(
-                                                  const FunctionProtoType *T) {
-  QualType ResultType = getDerived().TransformType(T->getResultType());
+QualType
+TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
+                                                   FunctionProtoTypeLoc TL) {
+  FunctionProtoType *T = TL.getTypePtr();
+  QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
   if (ResultType.isNull())
     return QualType();
 
+  // Transform the parameters.
   llvm::SmallVector<QualType, 4> ParamTypes;
-  for (FunctionProtoType::arg_type_iterator Param = T->arg_type_begin(),
-                                         ParamEnd = T->arg_type_end();
-       Param != ParamEnd; ++Param) {
-    QualType P = getDerived().TransformType(*Param);
-    if (P.isNull())
-      return QualType();
+  llvm::SmallVector<ParmVarDecl*, 4> ParamDecls;
+  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
+    ParmVarDecl *OldParm = TL.getArg(i);
+
+    QualType NewType;
+    ParmVarDecl *NewParm;
+
+    if (OldParm) {
+      DeclaratorInfo *OldDI = OldParm->getDeclaratorInfo();
+      assert(OldDI->getType() == T->getArgType(i));
+
+      DeclaratorInfo *NewDI = getDerived().TransformType(OldDI);
+      if (!NewDI)
+        return QualType();
+
+      if (NewDI == OldDI)
+        NewParm = OldParm;
+      else
+        NewParm = ParmVarDecl::Create(SemaRef.Context,
+                                      OldParm->getDeclContext(),
+                                      OldParm->getLocation(),
+                                      OldParm->getIdentifier(),
+                                      NewDI->getType(),
+                                      NewDI,
+                                      OldParm->getStorageClass(),
+                                      /* DefArg */ NULL);
+      NewType = NewParm->getType();
+
+    // Deal with the possibility that we don't have a parameter
+    // declaration for this parameter.
+    } else {
+      NewParm = 0;
+
+      QualType OldType = T->getArgType(i);
+      NewType = getDerived().TransformType(OldType);
+      if (NewType.isNull())
+        return QualType();
+    }
 
-    ParamTypes.push_back(P);
+    ParamTypes.push_back(NewType);
+    ParamDecls.push_back(NewParm);
   }
 
-  if (!getDerived().AlwaysRebuild() &&
-      ResultType == T->getResultType() &&
-      std::equal(T->arg_type_begin(), T->arg_type_end(), ParamTypes.begin()))
-    return QualType(T, 0);
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ResultType != T->getResultType() ||
+      !std::equal(T->arg_type_begin(), T->arg_type_end(), ParamTypes.begin())) {
+    Result = getDerived().RebuildFunctionProtoType(ResultType,
+                                                   ParamTypes.data(),
+                                                   ParamTypes.size(),
+                                                   T->isVariadic(),
+                                                   T->getTypeQuals());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  FunctionProtoTypeLoc NewTL = TLB.push<FunctionProtoTypeLoc>(Result);
+  NewTL.setLParenLoc(TL.getLParenLoc());
+  NewTL.setRParenLoc(TL.getRParenLoc());
+  for (unsigned i = 0, e = NewTL.getNumArgs(); i != e; ++i)
+    NewTL.setArg(i, ParamDecls[i]);
 
-  return getDerived().RebuildFunctionProtoType(ResultType, ParamTypes.data(),
-                                               ParamTypes.size(), T->isVariadic(),
-                                               T->getTypeQuals());
+  return Result;
 }
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformFunctionNoProtoType(
-                                                const FunctionNoProtoType *T) {
-  // FIXME: Implement
-  return QualType(T, 0);
+                                                 TypeLocBuilder &TLB,
+                                                 FunctionNoProtoTypeLoc TL) {
+  FunctionNoProtoType *T = TL.getTypePtr();
+  QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+  if (ResultType.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ResultType != T->getResultType())
+    Result = getDerived().RebuildFunctionNoProtoType(ResultType);
+
+  FunctionNoProtoTypeLoc NewTL = TLB.push<FunctionNoProtoTypeLoc>(Result);
+  NewTL.setLParenLoc(TL.getLParenLoc());
+  NewTL.setRParenLoc(TL.getRParenLoc());
+
+  return Result;
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::TransformTypedefType(const TypedefType *T) {
+QualType TreeTransform<Derived>::TransformTypedefType(TypeLocBuilder &TLB,
+                                                      TypedefTypeLoc TL) {
+  TypedefType *T = TL.getTypePtr();
   TypedefDecl *Typedef
     = cast_or_null<TypedefDecl>(getDerived().TransformDecl(T->getDecl()));
   if (!Typedef)
     return QualType();
 
-  if (!getDerived().AlwaysRebuild() &&
-      Typedef == T->getDecl())
-    return QualType(T, 0);
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      Typedef != T->getDecl()) {
+    Result = getDerived().RebuildTypedefType(Typedef);
+    if (Result.isNull())
+      return QualType();
+  }
+
+  TypedefTypeLoc NewTL = TLB.push<TypedefTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
 
-  return getDerived().RebuildTypedefType(Typedef);
+  return Result;
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::TransformTypeOfExprType(
-                                                    const TypeOfExprType *T) {
+QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB,
+                                                      TypeOfExprTypeLoc TL) {
+  TypeOfExprType *T = TL.getTypePtr();
+
   // typeof expressions are not potentially evaluated contexts
   EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
 
@@ -2265,30 +2537,50 @@
   if (E.isInvalid())
     return QualType();
 
-  if (!getDerived().AlwaysRebuild() &&
-      E.get() == T->getUnderlyingExpr()) {
-    E.take();
-    return QualType(T, 0);
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      E.get() != T->getUnderlyingExpr()) {
+    Result = getDerived().RebuildTypeOfExprType(move(E));
+    if (Result.isNull())
+      return QualType();
   }
+  else E.take();
+
+  TypeOfExprTypeLoc NewTL = TLB.push<TypeOfExprTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
 
-  return getDerived().RebuildTypeOfExprType(move(E));
+  return Result;
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::TransformTypeOfType(const TypeOfType *T) {
+QualType TreeTransform<Derived>::TransformTypeOfType(TypeLocBuilder &TLB,
+                                                     TypeOfTypeLoc TL) {
+  TypeOfType *T = TL.getTypePtr();
+
+  // FIXME: should be an inner type, or at least have a DeclaratorInfo.
   QualType Underlying = getDerived().TransformType(T->getUnderlyingType());
   if (Underlying.isNull())
     return QualType();
 
-  if (!getDerived().AlwaysRebuild() &&
-      Underlying == T->getUnderlyingType())
-    return QualType(T, 0);
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      Underlying != T->getUnderlyingType()) {
+    Result = getDerived().RebuildTypeOfType(Underlying);
+    if (Result.isNull())
+      return QualType();
+  }
 
-  return getDerived().RebuildTypeOfType(Underlying);
+  TypeOfTypeLoc NewTL = TLB.push<TypeOfTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::TransformDecltypeType(const DecltypeType *T) {
+QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB,
+                                                       DecltypeTypeLoc TL) {
+  DecltypeType *T = TL.getTypePtr();
+
   // decltype expressions are not potentially evaluated contexts
   EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
 
@@ -2296,77 +2588,122 @@
   if (E.isInvalid())
     return QualType();
 
-  if (!getDerived().AlwaysRebuild() &&
-      E.get() == T->getUnderlyingExpr()) {
-    E.take();
-    return QualType(T, 0);
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      E.get() != T->getUnderlyingExpr()) {
+    Result = getDerived().RebuildDecltypeType(move(E));
+    if (Result.isNull())
+      return QualType();
   }
+  else E.take();
+
+  DecltypeTypeLoc NewTL = TLB.push<DecltypeTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
 
-  return getDerived().RebuildDecltypeType(move(E));
+  return Result;
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::TransformRecordType(const RecordType *T) {
+QualType TreeTransform<Derived>::TransformRecordType(TypeLocBuilder &TLB,
+                                                     RecordTypeLoc TL) {
+  RecordType *T = TL.getTypePtr();
   RecordDecl *Record
-  = cast_or_null<RecordDecl>(getDerived().TransformDecl(T->getDecl()));
+    = cast_or_null<RecordDecl>(getDerived().TransformDecl(T->getDecl()));
   if (!Record)
     return QualType();
 
-  if (!getDerived().AlwaysRebuild() &&
-      Record == T->getDecl())
-    return QualType(T, 0);
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      Record != T->getDecl()) {
+    Result = getDerived().RebuildRecordType(Record);
+    if (Result.isNull())
+      return QualType();
+  }
 
-  return getDerived().RebuildRecordType(Record);
+  RecordTypeLoc NewTL = TLB.push<RecordTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::TransformEnumType(const EnumType *T) {
+QualType TreeTransform<Derived>::TransformEnumType(TypeLocBuilder &TLB,
+                                                   EnumTypeLoc TL) {
+  EnumType *T = TL.getTypePtr();
   EnumDecl *Enum
-  = cast_or_null<EnumDecl>(getDerived().TransformDecl(T->getDecl()));
+    = cast_or_null<EnumDecl>(getDerived().TransformDecl(T->getDecl()));
   if (!Enum)
     return QualType();
 
-  if (!getDerived().AlwaysRebuild() &&
-      Enum == T->getDecl())
-    return QualType(T, 0);
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      Enum != T->getDecl()) {
+    Result = getDerived().RebuildEnumType(Enum);
+    if (Result.isNull())
+      return QualType();
+  }
+
+  EnumTypeLoc NewTL = TLB.push<EnumTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
 
-  return getDerived().RebuildEnumType(Enum);
+  return Result;
 }
 
 template <typename Derived>
-QualType TreeTransform<Derived>::TransformElaboratedType(
-                                                    const ElaboratedType *T) {
+QualType TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,
+                                                      ElaboratedTypeLoc TL) {
+  ElaboratedType *T = TL.getTypePtr();
+
+  // FIXME: this should be a nested type.
   QualType Underlying = getDerived().TransformType(T->getUnderlyingType());
   if (Underlying.isNull())
     return QualType();
 
-  if (!getDerived().AlwaysRebuild() &&
-      Underlying == T->getUnderlyingType())
-    return QualType(T, 0);
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      Underlying != T->getUnderlyingType()) {
+    Result = getDerived().RebuildElaboratedType(Underlying, T->getTagKind());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
 
-  return getDerived().RebuildElaboratedType(Underlying, T->getTagKind());
+  return Result;
 }
 
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformTemplateTypeParmType(
-                                              const TemplateTypeParmType *T) {
-  // Nothing to do
-  return QualType(T, 0);
+                                                TypeLocBuilder &TLB,
+                                                TemplateTypeParmTypeLoc TL) {
+  return TransformTypeSpecType(TLB, TL);
 }
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
-                                         const SubstTemplateTypeParmType *T) {
-  // Nothing to do
-  return QualType(T, 0);
+                                         TypeLocBuilder &TLB,
+                                         SubstTemplateTypeParmTypeLoc TL) {
+  return TransformTypeSpecType(TLB, TL);
 }
 
 template<typename Derived>
 inline QualType 
 TreeTransform<Derived>::TransformTemplateSpecializationType(
-                                          const TemplateSpecializationType *T) {
-  return TransformTemplateSpecializationType(T, QualType());
+                                          TypeLocBuilder &TLB,
+                                          TemplateSpecializationTypeLoc TL) {
+  // TODO: figure out how make this work with an ObjectType.
+  QualType Result
+    = TransformTemplateSpecializationType(TL.getTypePtr(), QualType());
+  if (Result.isNull())
+    return QualType();
+
+  TemplateSpecializationTypeLoc NewTL
+    = TLB.push<TemplateSpecializationTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
 }
   
 template<typename Derived>
@@ -2399,8 +2736,10 @@
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::TransformQualifiedNameType(
-                                                  const QualifiedNameType *T) {
+QualType
+TreeTransform<Derived>::TransformQualifiedNameType(TypeLocBuilder &TLB,
+                                                   QualifiedNameTypeLoc TL) {
+  QualifiedNameType *T = TL.getTypePtr();
   NestedNameSpecifier *NNS
     = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
                                                 SourceRange());
@@ -2411,22 +2750,33 @@
   if (Named.isNull())
     return QualType();
 
-  if (!getDerived().AlwaysRebuild() &&
-      NNS == T->getQualifier() &&
-      Named == T->getNamedType())
-    return QualType(T, 0);
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      NNS != T->getQualifier() ||
+      Named != T->getNamedType()) {
+    Result = getDerived().RebuildQualifiedNameType(NNS, Named);
+    if (Result.isNull())
+      return QualType();
+  }
 
-  return getDerived().RebuildQualifiedNameType(NNS, Named);
+  QualifiedNameTypeLoc NewTL = TLB.push<QualifiedNameTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::TransformTypenameType(const TypenameType *T) {
+QualType TreeTransform<Derived>::TransformTypenameType(TypeLocBuilder &TLB,
+                                                       TypenameTypeLoc TL) {
+  TypenameType *T = TL.getTypePtr();
   NestedNameSpecifier *NNS
     = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
                         SourceRange(/*FIXME:*/getDerived().getBaseLocation()));
   if (!NNS)
     return QualType();
 
+  QualType Result;
+
   if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) {
     QualType NewTemplateId
       = getDerived().TransformType(QualType(TemplateId, 0));
@@ -2438,31 +2788,67 @@
         NewTemplateId == QualType(TemplateId, 0))
       return QualType(T, 0);
 
-    return getDerived().RebuildTypenameType(NNS, NewTemplateId);
+    Result = getDerived().RebuildTypenameType(NNS, NewTemplateId);
+  } else {
+    Result = getDerived().RebuildTypenameType(NNS, T->getIdentifier());
   }
+  if (Result.isNull())
+    return QualType();
 
-  return getDerived().RebuildTypenameType(NNS, T->getIdentifier());
+  TypenameTypeLoc NewTL = TLB.push<TypenameTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::TransformObjCInterfaceType(
-                                                  const ObjCInterfaceType *T) {
-  // FIXME: Implement
-  return QualType(T, 0);
+QualType
+TreeTransform<Derived>::TransformObjCInterfaceType(TypeLocBuilder &TLB,
+                                                   ObjCInterfaceTypeLoc TL) {
+  return TransformTypeSpecType(TLB, TL);
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::TransformObjCObjectPointerType(
-                                             const ObjCObjectPointerType *T) {
-  // FIXME: Implement
-  return QualType(T, 0);
+QualType
+TreeTransform<Derived>::TransformObjCObjectPointerType(TypeLocBuilder &TLB,
+                                               ObjCObjectPointerTypeLoc TL) {
+  TransformPointerLikeType(ObjCObjectPointerType);
 }
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformObjCProtocolListType(
-                                                const ObjCProtocolListType *T) {
-  assert(false && "Should not see ObjCProtocolList types");
-  return QualType(T, 0);
+                                                TypeLocBuilder &TLB,
+                                                ObjCProtocolListTypeLoc TL) {
+  ObjCProtocolListType *T = TL.getTypePtr();
+  QualType BaseType = T->getBaseType();
+  if (!BaseType.isNull()) {
+    BaseType = getDerived().TransformType(TLB, TL.getBaseTypeLoc());
+    if (BaseType.isNull())
+      return QualType();
+  } 
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      BaseType != T->getBaseType()) {
+    // TODO: transform these?
+    llvm::SmallVector<ObjCProtocolDecl*,4> Protocols(T->getNumProtocols());
+    std::copy(T->qual_begin(), T->qual_end(), Protocols.begin());
+    Result = getDerived().RebuildObjCProtocolListType(BaseType,
+                                                      &Protocols[0],
+                                                      T->getNumProtocols());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  ObjCProtocolListTypeLoc NewTL = TLB.push<ObjCProtocolListTypeLoc>(Result);
+  NewTL.setLAngleLoc(TL.getLAngleLoc());
+  NewTL.setRAngleLoc(TL.getRAngleLoc());
+
+  assert(NewTL.getNumProtocols() == TL.getNumProtocols());
+  for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
+    NewTL.setProtocolLoc(i, TL.getProtocolLoc(i));
+
+  return Result;
 }
 
 //===----------------------------------------------------------------------===//
@@ -4479,6 +4865,14 @@
 
 template<typename Derived>
 QualType
+TreeTransform<Derived>::RebuildObjCObjectPointerType(QualType PointeeType) {
+  return SemaRef.BuildPointerType(PointeeType, Qualifiers(),
+                                  getDerived().getBaseLocation(),
+                                  getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType
 TreeTransform<Derived>::RebuildArrayType(QualType ElementType,
                                          ArrayType::ArraySizeModifier SizeMod,
                                          const llvm::APInt *Size,
@@ -4596,6 +4990,11 @@
 }
 
 template<typename Derived>
+QualType TreeTransform<Derived>::RebuildFunctionNoProtoType(QualType T) {
+  return SemaRef.Context.getFunctionNoProtoType(T);
+}
+
+template<typename Derived>
 QualType TreeTransform<Derived>::RebuildTypeOfExprType(ExprArg E) {
   return SemaRef.BuildTypeofExprType(E.takeAs<Expr>());
 }





More information about the cfe-commits mailing list