[cfe-commits] r78071 - in /cfe/trunk: include/clang/AST/TemplateName.h lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/TreeTransform.h

Douglas Gregor dgregor at apple.com
Tue Aug 4 09:50:46 PDT 2009


Author: dgregor
Date: Tue Aug  4 11:50:30 2009
New Revision: 78071

URL: http://llvm.org/viewvc/llvm-project?rev=78071&view=rev
Log:
Refactor template instantiation for types into a generic tree
transformation template (TreeTransform) that handles the
transformation and reconstruction of AST nodes. Template instantiation
for types is a (relatively small) customization of the generic tree
transformation.


Added:
    cfe/trunk/lib/Sema/TreeTransform.h   (with props)
Modified:
    cfe/trunk/include/clang/AST/TemplateName.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp

Modified: cfe/trunk/include/clang/AST/TemplateName.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TemplateName.h?rev=78071&r1=78070&r2=78071&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/TemplateName.h (original)
+++ cfe/trunk/include/clang/AST/TemplateName.h Tue Aug  4 11:50:30 2009
@@ -78,6 +78,9 @@
   explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { }
   explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { }
 
+  /// \brief Determine whether this template name is NULL.
+  bool isNull() const { return Storage.isNull(); }
+  
   /// \brief Retrieve the the underlying template declaration that
   /// this template name refers to, if known.
   ///

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Aug  4 11:50:30 2009
@@ -1,12 +1,10 @@
 //===------- SemaTemplate.cpp - Semantic Analysis for C++ Templates -------===/
-
 //
 //                     The LLVM Compiler Infrastructure
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //===----------------------------------------------------------------------===/
-
 //
 //  This file implements semantic analysis for C++ templates.
 //===----------------------------------------------------------------------===/

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Aug  4 11:50:30 2009
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===/
 
 #include "Sema.h"
+#include "TreeTransform.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Expr.h"
@@ -285,365 +286,95 @@
 // Template Instantiation for Types
 //===----------------------------------------------------------------------===/
 namespace {
-  class VISIBILITY_HIDDEN TemplateTypeInstantiator {
-    Sema &SemaRef;
+  class VISIBILITY_HIDDEN TemplateInstantiator 
+    : public TreeTransform<TemplateInstantiator> 
+  {
     const TemplateArgumentList &TemplateArgs;
     SourceLocation Loc;
     DeclarationName Entity;
 
   public:
-    TemplateTypeInstantiator(Sema &SemaRef, 
-                             const TemplateArgumentList &TemplateArgs,
-                             SourceLocation Loc,
-                             DeclarationName Entity) 
-      : SemaRef(SemaRef), TemplateArgs(TemplateArgs), 
-        Loc(Loc), Entity(Entity) { }
-
-    QualType operator()(QualType T) const { return Instantiate(T); }
+    TemplateInstantiator(Sema &SemaRef, 
+                         const TemplateArgumentList &TemplateArgs,
+                         SourceLocation Loc,
+                         DeclarationName Entity) 
+    : TreeTransform<TemplateInstantiator>(SemaRef), TemplateArgs(TemplateArgs), 
+      Loc(Loc), Entity(Entity) { }
+
+    /// \brief Determine whether the given type \p T has already been 
+    /// transformed.
+    ///
+    /// For the purposes of template instantiation, a type has already been
+    /// transformed if it is NULL or if it is not dependent.
+    bool AlreadyTransformed(QualType T) {
+      return T.isNull() || !T->isDependentType();
+    }
+        
+    /// \brief Returns the location of the entity being instantiated, if known.
+    SourceLocation getBaseLocation() { return Loc; }
     
-    QualType Instantiate(QualType T) const;
-
-    // Declare instantiate functions for each type.
-#define TYPE(Class, Base)                                       \
-    QualType Instantiate##Class##Type(const Class##Type *T) const;
-#define ABSTRACT_TYPE(Class, Base)
-#include "clang/AST/TypeNodes.def"
-  };
-}
-
-QualType 
-TemplateTypeInstantiator::InstantiateExtQualType(const ExtQualType *T) const {
-  // FIXME: Implement this
-  assert(false && "Cannot instantiate ExtQualType yet");
-  return QualType();
-}
-
-QualType 
-TemplateTypeInstantiator::InstantiateBuiltinType(const BuiltinType *T) const {
-  assert(false && "Builtin types are not dependent and cannot be instantiated");
-  return QualType(T, 0);
-}
-
-QualType 
-TemplateTypeInstantiator::
-InstantiateFixedWidthIntType(const FixedWidthIntType *T) const {
-  // FIXME: Implement this
-  assert(false && "Cannot instantiate FixedWidthIntType yet");
-  return QualType();
-}
-
-QualType 
-TemplateTypeInstantiator::InstantiateComplexType(const ComplexType *T) const {
-  // FIXME: Implement this
-  assert(false && "Cannot instantiate ComplexType yet");
-  return QualType();
-}
-
-QualType 
-TemplateTypeInstantiator::InstantiatePointerType(const PointerType *T) const {
-  QualType PointeeType = Instantiate(T->getPointeeType());
-  if (PointeeType.isNull())
-    return QualType();
-
-  return SemaRef.BuildPointerType(PointeeType, 0, Loc, Entity);
-}
-
-QualType 
-TemplateTypeInstantiator::InstantiateBlockPointerType(
-                                            const BlockPointerType *T) const {
-  QualType PointeeType = Instantiate(T->getPointeeType());
-  if (PointeeType.isNull())
-    return QualType();
-  
-  return SemaRef.BuildBlockPointerType(PointeeType, 0, Loc, Entity);
-}
-
-QualType
-TemplateTypeInstantiator::InstantiateLValueReferenceType(
-                                        const LValueReferenceType *T) const {
-  QualType ReferentType = Instantiate(T->getPointeeType());
-  if (ReferentType.isNull())
-    return QualType();
-
-  return SemaRef.BuildReferenceType(ReferentType, true, 0, Loc, Entity);
-}
-
-QualType
-TemplateTypeInstantiator::InstantiateRValueReferenceType(
-                                        const RValueReferenceType *T) const {
-  QualType ReferentType = Instantiate(T->getPointeeType());
-  if (ReferentType.isNull())
-    return QualType();
-
-  return SemaRef.BuildReferenceType(ReferentType, false, 0, Loc, Entity);
-}
-
-QualType 
-TemplateTypeInstantiator::
-InstantiateMemberPointerType(const MemberPointerType *T) const {
-  QualType PointeeType = Instantiate(T->getPointeeType());
-  if (PointeeType.isNull())
-    return QualType();
-
-  QualType ClassType = Instantiate(QualType(T->getClass(), 0));
-  if (ClassType.isNull())
-    return QualType();
-
-  return SemaRef.BuildMemberPointerType(PointeeType, ClassType, 0, Loc, 
-                                        Entity);
-}
-
-QualType 
-TemplateTypeInstantiator::
-InstantiateConstantArrayType(const ConstantArrayType *T) const {
-  QualType ElementType = Instantiate(T->getElementType());
-  if (ElementType.isNull())
-    return ElementType;
-  
-  // Build a temporary integer literal to specify the size for
-  // BuildArrayType. Since we have already checked the size as part of
-  // creating the dependent array type in the first place, we know
-  // there aren't any errors. However, we do need to determine what
-  // C++ type to give the size expression.
-  llvm::APInt Size = T->getSize();
-  QualType Types[] = { 
-    SemaRef.Context.UnsignedCharTy, SemaRef.Context.UnsignedShortTy, 
-    SemaRef.Context.UnsignedIntTy, SemaRef.Context.UnsignedLongTy, 
-    SemaRef.Context.UnsignedLongLongTy, SemaRef.Context.UnsignedInt128Ty 
+    /// \brief Returns the name of the entity being instantiated, if any.
+    DeclarationName getBaseEntity() { return Entity; }
+    
+    /// \brief Transforms an expression by instantiating it with the given
+    /// template arguments.
+    Sema::OwningExprResult TransformExpr(Expr *E);
+
+    /// \brief Transform the given declaration by instantiating a reference to
+    /// this declaration.
+    Decl *TransformDecl(Decl *D);
+    
+    /// \brief Transform the given nested-name-specifier by instantiating it.
+    NestedNameSpecifier *TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
+                                                      SourceRange Range);
+    
+    /// \brief Transform the given template name by instantiating it.
+    TemplateName TransformTemplateName(TemplateName Template);
+    
+    /// \brief Transform the given template argument by instantiating it.
+    TemplateArgument TransformTemplateArgument(const TemplateArgument &Arg);
+    
+    /// \brief Transforms a template type parameter type by performing 
+    /// substitution of the corresponding template type argument.
+    QualType TransformTemplateTypeParmType(const TemplateTypeParmType *T);
   };
-  const unsigned NumTypes = sizeof(Types) / sizeof(QualType);
-  QualType SizeType;
-  for (unsigned I = 0; I != NumTypes; ++I)
-    if (Size.getBitWidth() == SemaRef.Context.getIntWidth(Types[I])) {
-      SizeType = Types[I];
-      break;
-    }
-
-  if (SizeType.isNull())
-    SizeType = SemaRef.Context.getFixedWidthIntType(Size.getBitWidth(), false);
-
-  IntegerLiteral ArraySize(Size, SizeType, Loc);
-  return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(), 
-                                &ArraySize, T->getIndexTypeQualifier(), 
-                                SourceRange(), // FIXME: provide proper range?
-                                Entity);
-}
-
-QualType
-TemplateTypeInstantiator::InstantiateConstantArrayWithExprType
-(const ConstantArrayWithExprType *T) const {
-  return InstantiateConstantArrayType(T);
-}
-
-QualType
-TemplateTypeInstantiator::InstantiateConstantArrayWithoutExprType
-(const ConstantArrayWithoutExprType *T) const {
-  return InstantiateConstantArrayType(T);
 }
 
-QualType 
-TemplateTypeInstantiator::
-InstantiateIncompleteArrayType(const IncompleteArrayType *T) const {
-  QualType ElementType = Instantiate(T->getElementType());
-  if (ElementType.isNull())
-    return ElementType;
-  
-  return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(), 
-                                0, T->getIndexTypeQualifier(),
-                                SourceRange(), // FIXME: provide proper range?
-                                Entity);
+Sema::OwningExprResult TemplateInstantiator::TransformExpr(Expr *E) {
+  return getSema().InstantiateExpr(E, TemplateArgs);
 }
 
-QualType
-TemplateTypeInstantiator::
-InstantiateVariableArrayType(const VariableArrayType *T) const {
-  // FIXME: Implement this
-  assert(false && "Cannot instantiate VariableArrayType yet");
-  return QualType();
+Decl *TemplateInstantiator::TransformDecl(Decl *D) {
+  return SemaRef.InstantiateCurrentDeclRef(cast_or_null<NamedDecl>(D));
 }
 
-QualType 
-TemplateTypeInstantiator::
-InstantiateDependentSizedArrayType(const DependentSizedArrayType *T) const {
-  Expr *ArraySize = T->getSizeExpr();
-  assert(ArraySize->isValueDependent() && 
-         "dependent sized array types must have value dependent size expr");
-  
-  // Instantiate the element type if needed
-  QualType ElementType = T->getElementType();
-  if (ElementType->isDependentType()) {
-    ElementType = Instantiate(ElementType);
-    if (ElementType.isNull())
-      return QualType();
-  }
-  
-  // Instantiate the size expression
-  EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
-  Sema::OwningExprResult InstantiatedArraySize = 
-    SemaRef.InstantiateExpr(ArraySize, TemplateArgs);
-  if (InstantiatedArraySize.isInvalid())
-    return QualType();
-  
-  return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(),
-                                InstantiatedArraySize.takeAs<Expr>(),
-                                T->getIndexTypeQualifier(),
-                                SourceRange(), // FIXME: provide proper range?
-                                Entity);
-}
-
-QualType 
-TemplateTypeInstantiator::
-InstantiateDependentSizedExtVectorType(
-                                const DependentSizedExtVectorType *T) const {
-
-  // Instantiate the element type if needed.
-  QualType ElementType = T->getElementType();
-  if (ElementType->isDependentType()) {
-    ElementType = Instantiate(ElementType);
-    if (ElementType.isNull())
-      return QualType();
-  }
-
-  // The expression in a dependent-sized extended vector type is not
-  // potentially evaluated.
-  EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
-
-  // Instantiate the size expression.
-  const Expr *SizeExpr = T->getSizeExpr();
-  Sema::OwningExprResult InstantiatedArraySize = 
-    SemaRef.InstantiateExpr(const_cast<Expr *>(SizeExpr), TemplateArgs);
-  if (InstantiatedArraySize.isInvalid())
-    return QualType();
-  
-  return SemaRef.BuildExtVectorType(ElementType,
-                                    SemaRef.Owned(
-                                      InstantiatedArraySize.takeAs<Expr>()),
-                                    T->getAttributeLoc());
-}
-
-QualType 
-TemplateTypeInstantiator::InstantiateVectorType(const VectorType *T) const {
-  // FIXME: Implement this
-  assert(false && "Cannot instantiate VectorType yet");
-  return QualType();
-}
-
-QualType 
-TemplateTypeInstantiator::InstantiateExtVectorType(
-                                              const ExtVectorType *T) const {
-  // FIXME: Implement this
-  assert(false && "Cannot instantiate ExtVectorType yet");
-  return QualType();
-}
-
-QualType 
-TemplateTypeInstantiator::
-InstantiateFunctionProtoType(const FunctionProtoType *T) const {
-  QualType ResultType = Instantiate(T->getResultType());
-  if (ResultType.isNull())
-    return ResultType;
-
-  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 = Instantiate(*Param);
-    if (P.isNull())
-      return P;
-
-    ParamTypes.push_back(P);
-  }
-
-  return SemaRef.BuildFunctionType(ResultType, ParamTypes.data(), 
-                                   ParamTypes.size(),
-                                   T->isVariadic(), T->getTypeQuals(),
-                                   Loc, Entity);
-}
-
-QualType 
-TemplateTypeInstantiator::
-InstantiateFunctionNoProtoType(const FunctionNoProtoType *T) const {
-  assert(false && "Functions without prototypes cannot be dependent.");
-  return QualType();
-}
-
-QualType 
-TemplateTypeInstantiator::InstantiateTypedefType(const TypedefType *T) const {
-  TypedefDecl *Typedef 
-    = cast_or_null<TypedefDecl>(
-                           SemaRef.InstantiateCurrentDeclRef(T->getDecl()));
-  if (!Typedef)
-    return QualType();
-  
-  return SemaRef.Context.getTypeDeclType(Typedef);
-}
-
-QualType 
-TemplateTypeInstantiator::InstantiateTypeOfExprType(
-                                              const TypeOfExprType *T) const {
-  // The expression in a typeof is not potentially evaluated.
-  EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
-  
-  Sema::OwningExprResult E 
-    = SemaRef.InstantiateExpr(T->getUnderlyingExpr(), TemplateArgs);
-  if (E.isInvalid())
-    return QualType();
-
-  return SemaRef.BuildTypeofExprType(E.takeAs<Expr>());
-}
-
-QualType 
-TemplateTypeInstantiator::InstantiateTypeOfType(const TypeOfType *T) const {
-  QualType Underlying = Instantiate(T->getUnderlyingType());
-  if (Underlying.isNull())
-    return QualType();
-
-  return SemaRef.Context.getTypeOfType(Underlying);
+NestedNameSpecifier *
+TemplateInstantiator::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
+                                                   SourceRange Range) {
+  return getSema().InstantiateNestedNameSpecifier(NNS, Range, TemplateArgs);
 }
 
-QualType
-TemplateTypeInstantiator::InstantiateDecltypeType(const DecltypeType *T) const {
-  // C++0x [dcl.type.simple]p4:
-  //   The operand of the decltype specifier is an unevaluated operand.
-  EnterExpressionEvaluationContext Unevaluated(SemaRef,
-                                               Action::Unevaluated);
-  
-  Sema::OwningExprResult E 
-    = SemaRef.InstantiateExpr(T->getUnderlyingExpr(), TemplateArgs);
-
-  if (E.isInvalid())
-    return QualType();
-  
-  return SemaRef.BuildDecltypeType(E.takeAs<Expr>());
+TemplateName 
+TemplateInstantiator::TransformTemplateName(TemplateName Template) {
+  return getSema().InstantiateTemplateName(Template, /*FIXME*/Loc, 
+                                           TemplateArgs);
 }
 
-QualType 
-TemplateTypeInstantiator::InstantiateRecordType(const RecordType *T) const {
-  RecordDecl *Record 
-    = cast_or_null<RecordDecl>(SemaRef.InstantiateCurrentDeclRef(T->getDecl()));
-  if (!Record)
-    return QualType();
-  
-  return SemaRef.Context.getTypeDeclType(Record);
+TemplateArgument 
+TemplateInstantiator::TransformTemplateArgument(const TemplateArgument &Arg) {
+  return getSema().Instantiate(Arg, TemplateArgs);
 }
 
 QualType 
-TemplateTypeInstantiator::InstantiateEnumType(const EnumType *T) const {
-  EnumDecl *Enum 
-    = cast_or_null<EnumDecl>(SemaRef.InstantiateCurrentDeclRef(T->getDecl()));
-  if (!Enum)
-    return QualType();
-  
-  return SemaRef.Context.getTypeDeclType(Enum);
-}
-
-QualType 
-TemplateTypeInstantiator::
-InstantiateTemplateTypeParmType(const TemplateTypeParmType *T) const {
+TemplateInstantiator::TransformTemplateTypeParmType(
+                                              const TemplateTypeParmType *T) {
   if (T->getDepth() == 0) {
     // Replace the template type parameter with its corresponding
     // template argument.
     
+    // FIXME: When dealing with member templates, we might end up with multiple
+    /// levels of template arguments that we're substituting into concurrently.
+    
     // If the corresponding template argument is NULL or doesn't exist, it's 
     // because we are performing instantiation from explicitly-specified 
     // template arguments in a function template class, but there were some 
@@ -661,112 +392,10 @@
   // 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 SemaRef.Context.getTemplateTypeParmType(T->getDepth() - 1,
-                                                 T->getIndex(),
-                                                 T->isParameterPack(),
-                                                 T->getName());
-}
-
-QualType 
-TemplateTypeInstantiator::
-InstantiateTemplateSpecializationType(
-                                  const TemplateSpecializationType *T) const {
-  llvm::SmallVector<TemplateArgument, 4> InstantiatedTemplateArgs;
-  InstantiatedTemplateArgs.reserve(T->getNumArgs());
-  for (TemplateSpecializationType::iterator Arg = T->begin(), ArgEnd = T->end();
-       Arg != ArgEnd; ++Arg) {
-    TemplateArgument InstArg = SemaRef.Instantiate(*Arg, TemplateArgs);
-    if (InstArg.isNull())
-      return QualType();
-
-    InstantiatedTemplateArgs.push_back(InstArg);
-  }
-
-  // FIXME: We're missing the locations of the template name, '<', and '>'.
-
-  TemplateName Name = SemaRef.InstantiateTemplateName(T->getTemplateName(),
-                                                      Loc, 
-                                                      TemplateArgs);
-
-  return SemaRef.CheckTemplateIdType(Name, Loc, SourceLocation(),
-                                     InstantiatedTemplateArgs.data(),
-                                     InstantiatedTemplateArgs.size(),
-                                     SourceLocation());
-}
-
-QualType 
-TemplateTypeInstantiator::
-InstantiateQualifiedNameType(const QualifiedNameType *T) const {
-  // When we instantiated a qualified name type, there's no point in
-  // keeping the qualification around in the instantiated result. So,
-  // just instantiate the named type.
-  return (*this)(T->getNamedType());
-}
-
-QualType 
-TemplateTypeInstantiator::
-InstantiateTypenameType(const TypenameType *T) const {
-  if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) {
-    // When the typename type refers to a template-id, the template-id
-    // is dependent and has enough information to instantiate the
-    // result of the typename type. Since we don't care about keeping
-    // the spelling of the typename type in template instantiations,
-    // we just instantiate the template-id.
-    return InstantiateTemplateSpecializationType(TemplateId);
-  }
-
-  NestedNameSpecifier *NNS 
-    = SemaRef.InstantiateNestedNameSpecifier(T->getQualifier(), 
-                                             SourceRange(Loc),
-                                             TemplateArgs);
-  if (!NNS)
-    return QualType();
-
-  return SemaRef.CheckTypenameType(NNS, *T->getIdentifier(), SourceRange(Loc));
-}
-
-QualType 
-TemplateTypeInstantiator::
-InstantiateObjCObjectPointerType(const ObjCObjectPointerType *T) const {
-  assert(false && "Objective-C types cannot be dependent");
-  return QualType();
-}
-
-QualType
-TemplateTypeInstantiator::
-InstantiateObjCInterfaceType(const ObjCInterfaceType *T) const {
-  assert(false && "Objective-C types cannot be dependent");
-  return QualType();
-}
-
-/// \brief The actual implementation of Sema::InstantiateType().
-QualType TemplateTypeInstantiator::Instantiate(QualType T) const {
-  // If T is not a dependent type, there is nothing to do.
-  if (!T->isDependentType())
-    return T;
-
-  QualType Result;
-  switch (T->getTypeClass()) {
-#define TYPE(Class, Base)                                               \
-  case Type::Class:                                                     \
-    Result = Instantiate##Class##Type(cast<Class##Type>(T.getTypePtr()));  \
-    break;
-#define ABSTRACT_TYPE(Class, Base)
-#include "clang/AST/TypeNodes.def"
-  }
-
-  // C++ [dcl.ref]p1:
-  //   [...] Cv-qualified references are ill-formed except when
-  //   the cv-qualifiers are introduced through the use of a
-  //   typedef (7.1.3) or of a template type argument (14.3), in
-  //   which case the cv-qualifiers are ignored.
-  // 
-  // The same rule applies to function types.
-  // FIXME: what about address-space and Objective-C GC qualifiers?
-  if (!Result.isNull() && T.getCVRQualifiers() &&
-      !Result->isFunctionType() && !Result->isReferenceType())
-    Result = Result.getWithAdditionalQualifiers(T.getCVRQualifiers());
-  return Result;
+  return getSema().Context.getTemplateTypeParmType(T->getDepth() - 1,
+                                                   T->getIndex(),
+                                                   T->isParameterPack(),
+                                                   T->getName());
 }
 
 /// \brief Instantiate the type T with a given set of template arguments.
@@ -806,8 +435,8 @@
   if (!T->isDependentType())
     return T;
 
-  TemplateTypeInstantiator Instantiator(*this, TemplateArgs, Loc, Entity);
-  return Instantiator(T);
+  TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, Entity);
+  return Instantiator.TransformType(T);
 }
 
 /// \brief Instantiate the base class specifiers of the given class

Added: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=78071&view=auto

==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (added)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Aug  4 11:50:30 2009
@@ -0,0 +1,1135 @@
+//===------- TreeTransform.h - Semantic Tree Transformation ---------------===/
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+//  This file implements a semantic tree transformation that takes a given
+//  AST and rebuilds it, possibly transforming some nodes in the process.
+//
+//===----------------------------------------------------------------------===/
+#ifndef LLVM_CLANG_SEMA_TREETRANSFORM_H
+#define LLVM_CLANG_SEMA_TREETRANSFORM_H
+
+#include "Sema.h"
+#include <algorithm>
+
+namespace clang {
+  
+/// \brief A semantic tree transformation that allows one to transform one
+/// abstract syntax tree into another.
+///
+/// A new tree transformation is defined by creating a new subclass \c X of 
+/// \c TreeTransform<X> and then overriding certain operations to provide 
+/// behavior specific to that transformation. For example, template 
+/// instantiation is implemented as a tree transformation where the
+/// transformation of TemplateTypeParmType nodes involves substituting the
+/// template arguments for their corresponding template parameters; a similar
+/// transformation is performed for non-type template parameters and
+/// template template parameters.
+///
+/// This tree-transformation template uses static polymorphism to allow
+/// subclasses to customize any of its operations. Thus, a subclass can 
+/// override any of the transformation or rebuild operators by providing an
+/// operation with the same signature as the default implementation. The
+/// overridding function should not be virtual.
+///
+/// Semantic tree transformations are split into two stages, either of which
+/// can be replaced by a subclass. The "transform" step transforms an AST node
+/// or the parts of an AST node using the various transformation functions,
+/// then passes the pieces on to the "rebuild" step, which constructs a new AST
+/// node of the appropriate kind from the pieces. The default transformation
+/// routines recursively transform the operands to composite AST nodes (e.g.,
+/// the pointee type of a PointerType node) and, if any of those operand nodes
+/// were changed by the transformation, invokes the rebuild operation to create
+/// a new AST node.
+///
+/// Subclasses can customize the transformation at various levels. The 
+/// most course-grained transformations involve replacing TransformType(),
+/// TransformExpr(), TransformDecl(), TransformNestedNameSpecifier(),
+/// TransformTemplateName(), or TransformTemplateArgument() with entirely
+/// new implementations.
+///
+/// For more fine-grained transformations, subclasses can replace any of the
+/// \c TransformXXX functions (where XXX is the name of an AST node, e.g.,
+/// PointerType) to alter the transformation. As mentioned previously,
+/// replacing TransformTemplateTypeParmType() allows template instantiation
+/// to substitute template arguments for their corresponding template 
+/// parameters. Additionally, subclasses can override the \c RebuildXXX
+/// functions to control how AST nodes are rebuilt when their operands change.
+/// By default, \c TreeTransform will invoke semantic analysis to rebuild
+/// AST nodes. However, certain other tree transformations (e.g, cloning) may
+/// be able to use more efficient rebuild steps.
+///
+/// There are a handful of other functions that can be overridden, allowing one
+/// to avoid traversing nodes that don't need any transformation 
+/// (\c AlreadyTransformed()), force rebuilding AST nodes even when their
+/// operands have not changed (\c AlwaysRebuild()), and customize the
+/// default locations and entity names used for type-checking
+/// (\c getBaseLocation(), \c getBaseEntity()).
+///
+/// FIXME: In the future, TreeTransform will support transformation of
+/// statements and expressions as well as types.
+template<typename Derived>
+class TreeTransform {
+protected:
+  Sema &SemaRef;
+  
+public:  
+  /// \brief Initializes a new tree transformer.
+  TreeTransform(Sema &SemaRef) : SemaRef(SemaRef) { }
+          
+  /// \brief Retrieves a reference to the derived class.
+  Derived &getDerived() { return static_cast<Derived&>(*this); }
+
+  /// \brief Retrieves a reference to the derived class.
+  const Derived &getDerived() const { 
+    return static_cast<const Derived&>(*this); 
+  }
+
+  /// \brief Retrieves a reference to the semantic analysis object used for
+  /// this tree transform.
+  Sema &getSema() const { return SemaRef; }
+  
+  /// \brief Whether the transformation should always rebuild AST nodes, even
+  /// if none of the children have changed.
+  ///
+  /// Subclasses may override this function to specify when the transformation
+  /// should rebuild all AST nodes.
+  bool AlwaysRebuild() { return false; }
+  
+  /// \brief Returns the location of the entity being transformed, if that
+  /// information was not available elsewhere in the AST.
+  ///
+  /// By default, returns no source-location information. Subclasses can 
+  /// provide an alternative implementation that provides better location
+  /// information.
+  SourceLocation getBaseLocation() { return SourceLocation(); }
+  
+  /// \brief Returns the name of the entity being transformed, if that
+  /// information was not available elsewhere in the AST.
+  ///
+  /// By default, returns an empty name. Subclasses can provide an alternative
+  /// implementation with a more precise name.
+  DeclarationName getBaseEntity() { return DeclarationName(); }
+
+  /// \brief Determine whether the given type \p T has already been 
+  /// transformed.
+  ///
+  /// Subclasses can provide an alternative implementation of this routine
+  /// to short-circuit evaluation when it is known that a given type will 
+  /// not change. For example, template instantiation need not traverse
+  /// non-dependent types.
+  bool AlreadyTransformed(QualType T) {
+    return T.isNull();
+  }
+
+  /// \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.
+  ///
+  /// \returns the transformed type.
+  QualType TransformType(QualType T);
+  
+  /// \brief Transform the given type by adding the given set of qualifiers
+  /// and returning the result.
+  ///
+  /// 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, unsigned CVRQualifiers);
+       
+  /// \brief Transform the given expression.
+  ///
+  /// FIXME: At the moment, subclasses must override this.
+  Sema::OwningExprResult TransformExpr(Expr *E);
+  
+  /// \brief Transform the given declaration, which is referenced from a type
+  /// or expression.
+  ///
+  /// Subclasses must override this.
+  Decl *TransformDecl(Decl *D);
+  
+  /// \brief Transform the given nested-name-specifier.
+  ///
+  /// Subclasses must override this.
+  NestedNameSpecifier *TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
+                                                    SourceRange Range);
+  
+  /// \brief Transform the given template name.
+  /// 
+  /// FIXME: At the moment, subclasses must override this.
+  TemplateName TransformTemplateName(TemplateName Template);
+  
+  /// \brief Transform the given template argument.
+  ///
+  /// FIXME: At the moment, subclasses must override this.
+  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"      
+
+  /// \brief Build a new pointer type given its pointee type.
+  ///
+  /// By default, performs semantic analysis when building the pointer type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildPointerType(QualType PointeeType);
+
+  /// \brief Build a new block pointer type given its pointee type.
+  ///
+  /// By default, performs semantic analysis when building the block pointer 
+  /// type. Subclasses may override this routine to provide different behavior.
+  QualType RebuildBlockPointerType(QualType PointeeType);
+
+  /// \brief Build a new lvalue reference type given the type it references.
+  ///
+  /// By default, performs semantic analysis when building the lvalue reference
+  /// type. Subclasses may override this routine to provide different behavior.
+  QualType RebuildLValueReferenceType(QualType ReferentType);
+
+  /// \brief Build a new rvalue reference type given the type it references.
+  ///
+  /// By default, performs semantic analysis when building the rvalue reference
+  /// type. Subclasses may override this routine to provide different behavior.
+  QualType RebuildRValueReferenceType(QualType ReferentType);
+  
+  /// \brief Build a new member pointer type given the pointee type and the
+  /// class type it refers into.
+  ///
+  /// By default, performs semantic analysis when building the member pointer
+  /// type. Subclasses may override this routine to provide different behavior.
+  QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType);
+  
+  /// \brief Build a new array type given the element type, size
+  /// modifier, size of the array (if known), size expression, and index type
+  /// qualifiers.
+  ///
+  /// By default, performs semantic analysis when building the array type.
+  /// Subclasses may override this routine to provide different behavior.
+  /// Also by default, all of the other Rebuild*Array 
+  QualType RebuildArrayType(QualType ElementType,
+                            ArrayType::ArraySizeModifier SizeMod,
+                            const llvm::APInt *Size,
+                            Expr *SizeExpr,
+                            unsigned IndexTypeQuals,
+                            SourceRange BracketsRange);
+  
+  /// \brief Build a new constant array type given the element type, size
+  /// modifier, (known) size of the array, and index type qualifiers.
+  ///
+  /// By default, performs semantic analysis when building the array type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildConstantArrayType(QualType ElementType, 
+                                    ArrayType::ArraySizeModifier SizeMod,
+                                    const llvm::APInt &Size,
+                                    unsigned IndexTypeQuals);
+
+  /// \brief Build a new constant array type given the element type, size
+  /// modifier, (known) size of the array, size expression, and index type 
+  /// qualifiers.
+  ///
+  /// By default, performs semantic analysis when building the array type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildConstantArrayWithExprType(QualType ElementType, 
+                                            ArrayType::ArraySizeModifier SizeMod,
+                                            const llvm::APInt &Size,
+                                            Expr *SizeExpr,
+                                            unsigned IndexTypeQuals,
+                                            SourceRange BracketsRange);
+
+  /// \brief Build a new constant array type given the element type, size
+  /// modifier, (known) size of the array, and index type qualifiers.
+  ///
+  /// By default, performs semantic analysis when building the array type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildConstantArrayWithoutExprType(QualType ElementType, 
+                                               ArrayType::ArraySizeModifier SizeMod,
+                                               const llvm::APInt &Size,
+                                               unsigned IndexTypeQuals);
+
+  /// \brief Build a new incomplete array type given the element type, size
+  /// modifier, and index type qualifiers.
+  ///
+  /// By default, performs semantic analysis when building the array type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildIncompleteArrayType(QualType ElementType, 
+                                      ArrayType::ArraySizeModifier SizeMod,
+                                      unsigned IndexTypeQuals);
+
+  /// \brief Build a new variable-length array type given the element type, 
+  /// size modifier, size expression, and index type qualifiers.
+  ///
+  /// By default, performs semantic analysis when building the array type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildVariableArrayType(QualType ElementType, 
+                                    ArrayType::ArraySizeModifier SizeMod,
+                                    Sema::ExprArg SizeExpr,
+                                    unsigned IndexTypeQuals,
+                                    SourceRange BracketsRange);
+
+  /// \brief Build a new dependent-sized array type given the element type, 
+  /// size modifier, size expression, and index type qualifiers.
+  ///
+  /// By default, performs semantic analysis when building the array type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildDependentSizedArrayType(QualType ElementType, 
+                                          ArrayType::ArraySizeModifier SizeMod,
+                                          Sema::ExprArg SizeExpr,
+                                          unsigned IndexTypeQuals,
+                                          SourceRange BracketsRange);
+
+  /// \brief Build a new vector type given the element type and
+  /// number of elements.
+  ///
+  /// By default, performs semantic analysis when building the vector type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildVectorType(QualType ElementType, unsigned NumElements);
+  
+  /// \brief Build a new extended vector type given the element type and
+  /// number of elements.
+  ///
+  /// By default, performs semantic analysis when building the vector type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildExtVectorType(QualType ElementType, unsigned NumElements,
+                                SourceLocation AttributeLoc);
+  
+  /// \brief Build a new potentially dependently-sized extended vector type 
+  /// given the element type and number of elements.
+  ///
+  /// By default, performs semantic analysis when building the vector type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildDependentSizedExtVectorType(QualType ElementType, 
+                                              Sema::ExprArg SizeExpr,
+                                              SourceLocation AttributeLoc);
+    
+  /// \brief Build a new function type.
+  ///
+  /// By default, performs semantic analysis when building the function type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildFunctionProtoType(QualType T,
+                                    QualType *ParamTypes, 
+                                    unsigned NumParamTypes,
+                                    bool Variadic, unsigned Quals);
+    
+  /// \brief Build a new typedef type.
+  QualType RebuildTypedefType(TypedefDecl *Typedef) {
+    return SemaRef.Context.getTypeDeclType(Typedef);
+  }
+
+  /// \brief Build a new class/struct/union type.
+  QualType RebuildRecordType(RecordDecl *Record) {
+    return SemaRef.Context.getTypeDeclType(Record);
+  }
+
+  /// \brief Build a new Enum type.
+  QualType RebuildEnumType(EnumDecl *Enum) {
+    return SemaRef.Context.getTypeDeclType(Enum);
+  }
+  
+  /// \brief Build a new typeof(expr) type. 
+  ///
+  /// By default, performs semantic analysis when building the typeof type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildTypeOfExprType(Sema::ExprArg Underlying);
+
+  /// \brief Build a new typeof(type) type. 
+  ///
+  /// By default, builds a new TypeOfType with the given underlying type.
+  QualType RebuildTypeOfType(QualType Underlying);
+
+  /// \brief Build a new C++0x decltype type. 
+  ///
+  /// By default, performs semantic analysis when building the decltype type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildDecltypeType(Sema::ExprArg Underlying);
+  
+  /// \brief Build a new template specialization type.
+  ///
+  /// By default, performs semantic analysis when building the template
+  /// specialization type. Subclasses may override this routine to provide
+  /// different behavior.
+  QualType RebuildTemplateSpecializationType(TemplateName Template,
+                                             const TemplateArgument *Args,
+                                             unsigned NumArgs);
+  
+  /// \brief Build a new qualified name type.
+  ///
+  /// By default, builds a new QualifiedNameType type from the 
+  /// nested-name-specifier and the named type. Subclasses may override 
+  /// this routine to provide different behavior.
+  QualType RebuildQualifiedNameType(NestedNameSpecifier *NNS, QualType Named) {
+    return SemaRef.Context.getQualifiedNameType(NNS, Named);
+  }  
+
+  /// \brief Build a new typename type that refers to a template-id.
+  ///
+  /// By default, builds a new TypenameType type from the nested-name-specifier
+  /// and the given type. Subclasses may override this routine to provide 
+  /// different behavior.
+  QualType RebuildTypenameType(NestedNameSpecifier *NNS, QualType T) {
+    if (NNS->isDependent())
+      return SemaRef.Context.getTypenameType(NNS, 
+                                          cast<TemplateSpecializationType>(T));
+    
+    return SemaRef.Context.getQualifiedNameType(NNS, T);
+  }  
+
+  /// \brief Build a new typename type that refers to an identifier.
+  ///
+  /// By default, performs semantic analysis when building the typename type
+  /// (or qualified name type). Subclasses may override this routine to provide 
+  /// different behavior.
+  QualType RebuildTypenameType(NestedNameSpecifier *NNS, 
+                               const IdentifierInfo *Id) {
+    return SemaRef.CheckTypenameType(NNS, *Id,
+                                  SourceRange(getDerived().getBaseLocation()));
+  }    
+};
+  
+//===----------------------------------------------------------------------===//
+// Type transformation
+//===----------------------------------------------------------------------===//
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformType(QualType T) {
+  if (getDerived().AlreadyTransformed(T))
+    return T;
+  
+  QualType Result;
+  switch (T->getTypeClass()) {
+#define ABSTRACT_TYPE(CLASS, PARENT) 
+#define TYPE(CLASS, PARENT)                                                  \
+    case Type::CLASS:                                                        \
+      Result = getDerived().Transform##CLASS##Type(                          \
+                                  static_cast<CLASS##Type*>(T.getTypePtr())); \
+      break;
+#include "clang/AST/TypeNodes.def"      
+  }
+  
+  if (Result.isNull() || T == Result)
+    return Result;
+  
+  return getDerived().AddTypeQualifiers(Result, T.getCVRQualifiers());
+}
+  
+template<typename Derived>
+QualType 
+TreeTransform<Derived>::AddTypeQualifiers(QualType T, unsigned CVRQualifiers) {
+  if (CVRQualifiers && !T->isFunctionType() && !T->isReferenceType())
+    return T.getWithAdditionalQualifiers(CVRQualifiers);
+  
+  return T;
+}
+  
+template<typename Derived> 
+QualType TreeTransform<Derived>::TransformExtQualType(const ExtQualType *T) { 
+  // FIXME: Implement
+  return QualType(T, 0); 
+}
+  
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformBuiltinType(const BuiltinType *T) { 
+  // Nothing to do
+  return QualType(T, 0); 
+}
+  
+template<typename Derived> 
+QualType TreeTransform<Derived>::TransformFixedWidthIntType(
+                                                  const FixedWidthIntType *T) { 
+  // FIXME: Implement
+  return QualType(T, 0); 
+}
+  
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformComplexType(const ComplexType *T) { 
+  // FIXME: Implement
+  return QualType(T, 0); 
+}
+  
+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);
+}
+  
+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);
+}
+
+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);
+}
+
+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);
+}
+  
+template<typename Derived>
+QualType 
+TreeTransform<Derived>::TransformMemberPointerType(const MemberPointerType *T) { 
+  QualType PointeeType = getDerived().TransformType(T->getPointeeType());
+  if (PointeeType.isNull())
+    return QualType();
+  
+  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);
+
+  return getDerived().RebuildMemberPointerType(PointeeType, ClassType);
+}
+
+template<typename Derived> 
+QualType 
+TreeTransform<Derived>::TransformConstantArrayType(const ConstantArrayType *T) { 
+  QualType ElementType = getDerived().TransformType(T->getElementType());
+  if (ElementType.isNull())
+    return QualType();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      ElementType == T->getElementType())
+    return QualType(T, 0);
+  
+  return getDerived().RebuildConstantArrayType(ElementType, 
+                                               T->getSizeModifier(),
+                                               T->getSize(),
+                                               T->getIndexTypeQualifier());
+}
+  
+template<typename Derived>
+QualType 
+TreeTransform<Derived>::TransformConstantArrayWithExprType(
+                                      const ConstantArrayWithExprType *T) { 
+  QualType ElementType = getDerived().TransformType(T->getElementType());
+  if (ElementType.isNull())
+    return QualType();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      ElementType == T->getElementType())
+    return QualType(T, 0);
+  
+  return getDerived().RebuildConstantArrayWithExprType(ElementType, 
+                                                       T->getSizeModifier(),
+                                                       T->getSize(),
+                                        /*FIXME: Transform?*/T->getSizeExpr(),
+                                                   T->getIndexTypeQualifier(),
+                                                       T->getBracketsRange());
+}
+  
+template<typename Derived> 
+QualType 
+TreeTransform<Derived>::TransformConstantArrayWithoutExprType(
+                                      const ConstantArrayWithoutExprType *T) { 
+  QualType ElementType = getDerived().TransformType(T->getElementType());
+  if (ElementType.isNull())
+    return QualType();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      ElementType == T->getElementType())
+    return QualType(T, 0);
+  
+  return getDerived().RebuildConstantArrayWithoutExprType(ElementType, 
+                                                       T->getSizeModifier(),
+                                                       T->getSize(),
+                                                    T->getIndexTypeQualifier());
+}
+
+template<typename Derived> 
+QualType TreeTransform<Derived>::TransformIncompleteArrayType(
+                                              const IncompleteArrayType *T) { 
+  QualType ElementType = getDerived().TransformType(T->getElementType());
+  if (ElementType.isNull())
+    return QualType();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      ElementType == T->getElementType())
+    return QualType(T, 0);
+
+  return getDerived().RebuildIncompleteArrayType(ElementType,
+                                                 T->getSizeModifier(),
+                                                 T->getIndexTypeQualifier());
+}
+  
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformVariableArrayType(
+                                                  const VariableArrayType *T) { 
+  QualType ElementType = getDerived().TransformType(T->getElementType());
+  if (ElementType.isNull())
+    return QualType();
+  
+  Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
+  if (Size.isInvalid())
+    return QualType();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      ElementType == T->getElementType() &&
+      Size.get() == T->getSizeExpr()) {
+    Size.take();
+    return QualType(T, 0);
+  }
+  
+  return getDerived().RebuildVariableArrayType(ElementType, 
+                                               T->getSizeModifier(),
+                                               move(Size),
+                                               T->getIndexTypeQualifier(),
+                                               T->getBracketsRange());
+}
+  
+template<typename Derived> 
+QualType TreeTransform<Derived>::TransformDependentSizedArrayType(
+                                          const DependentSizedArrayType *T) { 
+  QualType ElementType = getDerived().TransformType(T->getElementType());
+  if (ElementType.isNull())
+    return QualType();
+  
+  Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
+  if (Size.isInvalid())
+    return QualType();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      ElementType == T->getElementType() &&
+      Size.get() == T->getSizeExpr()) {
+    Size.take();
+    return QualType(T, 0);
+  }
+  
+  return getDerived().RebuildDependentSizedArrayType(ElementType, 
+                                                     T->getSizeModifier(),
+                                                     move(Size),
+                                                     T->getIndexTypeQualifier(),
+                                                     T->getBracketsRange());
+}
+  
+template<typename Derived> 
+QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
+                                      const DependentSizedExtVectorType *T) { 
+  QualType ElementType = getDerived().TransformType(T->getElementType());
+  if (ElementType.isNull())
+    return QualType();
+  
+  Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
+  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, 
+                                                         move(Size),
+                                                         T->getAttributeLoc());
+}
+  
+template<typename Derived> 
+QualType TreeTransform<Derived>::TransformVectorType(const VectorType *T) { 
+  QualType ElementType = getDerived().TransformType(T->getElementType());
+  if (ElementType.isNull())
+    return QualType();
+
+  if (!getDerived().AlwaysRebuild() &&
+      ElementType == T->getElementType())
+    return QualType(T, 0);
+  
+  return getDerived().RebuildVectorType(ElementType, T->getNumElements());
+}
+  
+template<typename Derived> 
+QualType 
+TreeTransform<Derived>::TransformExtVectorType(const ExtVectorType *T) { 
+  QualType ElementType = getDerived().TransformType(T->getElementType());
+  if (ElementType.isNull())
+    return QualType();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      ElementType == T->getElementType())
+    return QualType(T, 0);
+  
+  return getDerived().RebuildExtVectorType(ElementType, T->getNumElements(),
+                                           /*FIXME*/SourceLocation());
+}
+
+template<typename Derived> 
+QualType TreeTransform<Derived>::TransformFunctionProtoType(
+                                                  const FunctionProtoType *T) { 
+  QualType ResultType = getDerived().TransformType(T->getResultType());
+  if (ResultType.isNull())
+    return QualType();
+  
+  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();
+    
+    ParamTypes.push_back(P);
+  }
+  
+  if (!getDerived().AlwaysRebuild() &&
+      ResultType == T->getResultType() &&
+      std::equal(T->arg_type_begin(), T->arg_type_end(), ParamTypes.begin()))
+    return QualType(T, 0);
+  
+  return getDerived().RebuildFunctionProtoType(ResultType, ParamTypes.data(), 
+                                               ParamTypes.size(), T->isVariadic(),
+                                               T->getTypeQuals());
+}
+  
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformFunctionNoProtoType(
+                                                const FunctionNoProtoType *T) { 
+  // FIXME: Implement
+  return QualType(T, 0); 
+}
+  
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTypedefType(const TypedefType *T) { 
+  TypedefDecl *Typedef
+    = cast_or_null<TypedefDecl>(getDerived().TransformDecl(T->getDecl()));
+  if (!Typedef)
+    return QualType();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      Typedef == T->getDecl())
+    return QualType(T, 0);
+  
+  return getDerived().RebuildTypedefType(Typedef);
+}
+  
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTypeOfExprType(
+                                                    const TypeOfExprType *T) { 
+  Sema::OwningExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
+  if (E.isInvalid())
+    return QualType();
+
+  if (!getDerived().AlwaysRebuild() &&
+      E.get() == T->getUnderlyingExpr()) {
+    E.take();
+    return QualType(T, 0);
+  }
+  
+  return getDerived().RebuildTypeOfExprType(move(E));
+}
+  
+template<typename Derived> 
+QualType TreeTransform<Derived>::TransformTypeOfType(const TypeOfType *T) { 
+  QualType Underlying = getDerived().TransformType(T->getUnderlyingType());
+  if (Underlying.isNull())
+    return QualType();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      Underlying == T->getUnderlyingType())
+    return QualType(T, 0);
+  
+  return getDerived().RebuildTypeOfType(Underlying);
+}
+  
+template<typename Derived> 
+QualType TreeTransform<Derived>::TransformDecltypeType(const DecltypeType *T) { 
+  Sema::OwningExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
+  if (E.isInvalid())
+    return QualType();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      E.get() == T->getUnderlyingExpr()) {
+    E.take();
+    return QualType(T, 0);
+  }
+  
+  return getDerived().RebuildDecltypeType(move(E));
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformRecordType(const RecordType *T) { 
+  RecordDecl *Record
+  = cast_or_null<RecordDecl>(getDerived().TransformDecl(T->getDecl()));
+  if (!Record)
+    return QualType();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      Record == T->getDecl())
+    return QualType(T, 0);
+  
+  return getDerived().RebuildRecordType(Record);
+}
+  
+template<typename Derived> 
+QualType TreeTransform<Derived>::TransformEnumType(const EnumType *T) { 
+  EnumDecl *Enum
+  = cast_or_null<EnumDecl>(getDerived().TransformDecl(T->getDecl()));
+  if (!Enum)
+    return QualType();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      Enum == T->getDecl())
+    return QualType(T, 0);
+  
+  return getDerived().RebuildEnumType(Enum);
+}
+  
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTemplateTypeParmType(
+                                              const TemplateTypeParmType *T) { 
+  // Nothing to do
+  return QualType(T, 0); 
+}
+
+template<typename Derived> 
+QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
+                                        const TemplateSpecializationType *T) { 
+  TemplateName Template 
+    = getDerived().TransformTemplateName(T->getTemplateName());
+  if (Template.isNull())
+    return QualType();
+  
+  llvm::SmallVector<TemplateArgument, 4> NewTemplateArgs;
+  NewTemplateArgs.reserve(T->getNumArgs());
+  for (TemplateSpecializationType::iterator Arg = T->begin(), ArgEnd = T->end();
+       Arg != ArgEnd; ++Arg) {
+    TemplateArgument NewArg = getDerived().TransformTemplateArgument(*Arg);
+    if (NewArg.isNull())
+      return QualType();
+    
+    NewTemplateArgs.push_back(NewArg);
+  }
+  
+  // FIXME: early abort if all of the template arguments and such are the
+  // same.
+  
+  // FIXME: We're missing the locations of the template name, '<', and '>'.
+  return getDerived().RebuildTemplateSpecializationType(Template,
+                                                        NewTemplateArgs.data(),
+                                                        NewTemplateArgs.size());
+}
+  
+template<typename Derived> 
+QualType TreeTransform<Derived>::TransformQualifiedNameType(
+                                                  const QualifiedNameType *T) {
+  NestedNameSpecifier *NNS
+    = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
+                                                SourceRange());
+  if (!NNS)
+    return QualType();
+  
+  QualType Named = getDerived().TransformType(T->getNamedType());
+  if (Named.isNull())
+    return QualType();
+                      
+  if (!getDerived().AlwaysRebuild() &&
+      NNS == T->getQualifier() &&
+      Named == T->getNamedType())
+    return QualType(T, 0);
+
+  return getDerived().RebuildQualifiedNameType(NNS, Named);
+}
+  
+template<typename Derived> 
+QualType TreeTransform<Derived>::TransformTypenameType(const TypenameType *T) {
+  NestedNameSpecifier *NNS
+    = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
+                                SourceRange(getDerived().getBaseLocation()));
+  if (!NNS)
+    return QualType();
+  
+  if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) {
+    QualType NewTemplateId 
+      = getDerived().TransformType(QualType(TemplateId, 0));
+    if (NewTemplateId.isNull())
+      return QualType();
+    
+    if (!getDerived().AlwaysRebuild() &&
+        NNS == T->getQualifier() &&
+        NewTemplateId == QualType(TemplateId, 0))
+      return QualType(T, 0);
+    
+    return getDerived().RebuildTypenameType(NNS, NewTemplateId);
+  }
+
+  return getDerived().RebuildTypenameType(NNS, T->getIdentifier());
+}
+  
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformObjCInterfaceType(
+                                                  const ObjCInterfaceType *T) { 
+  // FIXME: Implement
+  return QualType(T, 0); 
+}
+  
+template<typename Derived> 
+QualType TreeTransform<Derived>::TransformObjCObjectPointerType(
+                                             const ObjCObjectPointerType *T) { 
+  // FIXME: Implement
+  return QualType(T, 0); 
+}
+
+//===----------------------------------------------------------------------===//
+// Type reconstruction
+//===----------------------------------------------------------------------===//
+
+template<typename Derived> 
+QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType) {
+  return SemaRef.BuildPointerType(PointeeType, 0, 
+                                  getDerived().getBaseLocation(),
+                                  getDerived().getBaseEntity());
+}
+
+template<typename Derived> 
+QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType) {
+  return SemaRef.BuildBlockPointerType(PointeeType, 0, 
+                                       getDerived().getBaseLocation(),
+                                       getDerived().getBaseEntity());
+}
+
+template<typename Derived> 
+QualType 
+TreeTransform<Derived>::RebuildLValueReferenceType(QualType ReferentType) {
+  return SemaRef.BuildReferenceType(ReferentType, true, 0, 
+                                    getDerived().getBaseLocation(),
+                                    getDerived().getBaseEntity());
+}
+
+template<typename Derived> 
+QualType 
+TreeTransform<Derived>::RebuildRValueReferenceType(QualType ReferentType) {
+  return SemaRef.BuildReferenceType(ReferentType, false, 0, 
+                                    getDerived().getBaseLocation(),
+                                    getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType, 
+                                                          QualType ClassType) {
+  return SemaRef.BuildMemberPointerType(PointeeType, ClassType, 0, 
+                                        getDerived().getBaseLocation(),
+                                        getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType 
+TreeTransform<Derived>::RebuildArrayType(QualType ElementType,
+                                         ArrayType::ArraySizeModifier SizeMod,
+                                         const llvm::APInt *Size,
+                                         Expr *SizeExpr,
+                                         unsigned IndexTypeQuals,
+                                         SourceRange BracketsRange) {
+  if (SizeExpr || !Size)
+    return SemaRef.BuildArrayType(ElementType, SizeMod, SizeExpr,
+                                  IndexTypeQuals, BracketsRange,
+                                  getDerived().getBaseEntity());
+  
+  QualType Types[] = { 
+    SemaRef.Context.UnsignedCharTy, SemaRef.Context.UnsignedShortTy, 
+    SemaRef.Context.UnsignedIntTy, SemaRef.Context.UnsignedLongTy, 
+    SemaRef.Context.UnsignedLongLongTy, SemaRef.Context.UnsignedInt128Ty 
+  };
+  const unsigned NumTypes = sizeof(Types) / sizeof(QualType);
+  QualType SizeType;
+  for (unsigned I = 0; I != NumTypes; ++I)
+    if (Size->getBitWidth() == SemaRef.Context.getIntWidth(Types[I])) {
+      SizeType = Types[I];
+      break;
+    }
+  
+  if (SizeType.isNull())
+    SizeType = SemaRef.Context.getFixedWidthIntType(Size->getBitWidth(), false);
+  
+  IntegerLiteral ArraySize(*Size, SizeType, /*FIXME*/BracketsRange.getBegin());
+  return SemaRef.BuildArrayType(ElementType, SizeMod, &ArraySize, 
+                                IndexTypeQuals, BracketsRange,
+                                getDerived().getBaseEntity());    
+}
+  
+template<typename Derived>
+QualType 
+TreeTransform<Derived>::RebuildConstantArrayType(QualType ElementType, 
+                                                 ArrayType::ArraySizeModifier SizeMod,
+                                                 const llvm::APInt &Size,
+                                                 unsigned IndexTypeQuals) {
+  return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, 0, 
+                                        IndexTypeQuals, SourceRange());
+}
+
+template<typename Derived>
+QualType 
+TreeTransform<Derived>::RebuildConstantArrayWithExprType(QualType ElementType, 
+                                          ArrayType::ArraySizeModifier SizeMod,
+                                                      const llvm::APInt &Size,
+                                                         Expr *SizeExpr,
+                                                      unsigned IndexTypeQuals,
+                                                    SourceRange BracketsRange) {
+  return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, SizeExpr, 
+                                       IndexTypeQuals, BracketsRange);
+}
+
+template<typename Derived>
+QualType 
+TreeTransform<Derived>::RebuildConstantArrayWithoutExprType(
+                                                        QualType ElementType, 
+                                          ArrayType::ArraySizeModifier SizeMod,
+                                                       const llvm::APInt &Size,
+                                                     unsigned IndexTypeQuals) {
+  return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, 0, 
+                                       IndexTypeQuals, SourceRange());
+}
+
+template<typename Derived>
+QualType 
+TreeTransform<Derived>::RebuildIncompleteArrayType(QualType ElementType, 
+                                          ArrayType::ArraySizeModifier SizeMod,
+                                                 unsigned IndexTypeQuals) {
+  return getDerived().RebuildArrayType(ElementType, SizeMod, 0, 0, 
+                                       IndexTypeQuals, SourceRange());
+}
+  
+template<typename Derived>
+QualType 
+TreeTransform<Derived>::RebuildVariableArrayType(QualType ElementType, 
+                                          ArrayType::ArraySizeModifier SizeMod,
+                                                 Sema::ExprArg SizeExpr,
+                                                 unsigned IndexTypeQuals,
+                                                 SourceRange BracketsRange) {
+  return getDerived().RebuildArrayType(ElementType, SizeMod, 0, 
+                                       SizeExpr.takeAs<Expr>(),
+                                       IndexTypeQuals, BracketsRange);
+}
+
+template<typename Derived>
+QualType 
+TreeTransform<Derived>::RebuildDependentSizedArrayType(QualType ElementType, 
+                                          ArrayType::ArraySizeModifier SizeMod,
+                                                       Sema::ExprArg SizeExpr,
+                                                       unsigned IndexTypeQuals,
+                                                   SourceRange BracketsRange) {
+  return getDerived().RebuildArrayType(ElementType, SizeMod, 0, 
+                                       SizeExpr.takeAs<Expr>(),
+                                       IndexTypeQuals, BracketsRange);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildVectorType(QualType ElementType,
+                                                   unsigned NumElements) {
+  // FIXME: semantic checking!
+  return SemaRef.Context.getVectorType(ElementType, NumElements);
+}
+  
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildExtVectorType(QualType ElementType,
+                                                      unsigned NumElements,
+                                                 SourceLocation AttributeLoc) {
+  llvm::APInt numElements(SemaRef.Context.getIntWidth(SemaRef.Context.IntTy),
+                          NumElements, true);
+  IntegerLiteral *VectorSize
+    = new (SemaRef.Context) IntegerLiteral(numElements, SemaRef.Context.IntTy, 
+                                           AttributeLoc);
+  return SemaRef.BuildExtVectorType(ElementType, SemaRef.Owned(VectorSize),
+                                    AttributeLoc);
+}
+  
+template<typename Derived>
+QualType 
+TreeTransform<Derived>::RebuildDependentSizedExtVectorType(QualType ElementType, 
+                                                         Sema::ExprArg SizeExpr,
+                                                  SourceLocation AttributeLoc) {
+  return SemaRef.BuildExtVectorType(ElementType, move(SizeExpr), AttributeLoc);
+}
+ 
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildFunctionProtoType(QualType T,
+                                                          QualType *ParamTypes, 
+                                                        unsigned NumParamTypes,
+                                                          bool Variadic, 
+                                                          unsigned Quals) {
+  return SemaRef.BuildFunctionType(T, ParamTypes, NumParamTypes, Variadic, 
+                                   Quals,
+                                   getDerived().getBaseLocation(),
+                                   getDerived().getBaseEntity());
+}
+  
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildTypeOfExprType(Sema::ExprArg E) {
+  return SemaRef.BuildTypeofExprType(E.takeAs<Expr>());
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildTypeOfType(QualType Underlying) {
+  return SemaRef.Context.getTypeOfType(Underlying);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildDecltypeType(Sema::ExprArg E) {
+  return SemaRef.BuildDecltypeType(E.takeAs<Expr>());
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildTemplateSpecializationType(
+                                                        TemplateName Template,
+                                                 const TemplateArgument *Args,
+                                                           unsigned NumArgs) {
+  // FIXME: Missing source locations for the template name, <, >.
+  return SemaRef.CheckTemplateIdType(Template, getDerived().getBaseLocation(),
+                                     SourceLocation(), Args, NumArgs, 
+                                     SourceLocation());  
+}
+  
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_TREETRANSFORM_H

Propchange: cfe/trunk/lib/Sema/TreeTransform.h

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/lib/Sema/TreeTransform.h

------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/lib/Sema/TreeTransform.h

------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list