[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