Move the template instantiation logic for template arguments into the
general tree transformation. Also, implement template instantiation
for parameter packs.
In addition, introduce logic to enter the appropriate context for
subexpressions that are not potentially evaluated.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78114 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 622f7b4..0aefda7 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -47,7 +47,7 @@
/// a new AST node.
///
/// Subclasses can customize the transformation at various levels. The
-/// most course-grained transformations involve replacing TransformType(),
+/// most coarse-grained transformations involve replacing TransformType(),
/// TransformExpr(), TransformDecl(), TransformNestedNameSpecifier(),
/// TransformTemplateName(), or TransformTemplateArgument() with entirely
/// new implementations.
@@ -172,7 +172,10 @@
/// \brief Transform the given template argument.
///
- /// FIXME: At the moment, subclasses must override this.
+ /// By default, this operation transforms the type, expression, or
+ /// declaration stored within the template argument and constructs a
+ /// new template argument from the transformed result. Subclasses may
+ /// override this function to provide alternate behavior.
TemplateArgument TransformTemplateArgument(const TemplateArgument &Arg);
#define ABSTRACT_TYPE(CLASS, PARENT)
@@ -397,6 +400,62 @@
}
};
+template<typename Derived>
+TemplateArgument
+TreeTransform<Derived>::TransformTemplateArgument(const TemplateArgument &Arg) {
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ return Arg;
+
+ case TemplateArgument::Type: {
+ QualType T = getDerived().TransformType(Arg.getAsType());
+ if (T.isNull())
+ return TemplateArgument();
+ return TemplateArgument(Arg.getLocation(), T);
+ }
+
+ case TemplateArgument::Declaration: {
+ Decl *D = getDerived().TransformDecl(Arg.getAsDecl());
+ if (!D)
+ return TemplateArgument();
+ return TemplateArgument(Arg.getLocation(), D);
+ }
+
+ case TemplateArgument::Expression: {
+ // Template argument expressions are not potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(getSema(),
+ Action::Unevaluated);
+
+ Sema::OwningExprResult E = getDerived().TransformExpr(Arg.getAsExpr());
+ if (E.isInvalid())
+ return TemplateArgument();
+ return TemplateArgument(E.takeAs<Expr>());
+ }
+
+ case TemplateArgument::Pack: {
+ llvm::SmallVector<TemplateArgument, 4> TransformedArgs;
+ TransformedArgs.reserve(Arg.pack_size());
+ for (TemplateArgument::pack_iterator A = Arg.pack_begin(),
+ AEnd = Arg.pack_end();
+ A != AEnd; ++A) {
+ TemplateArgument TA = getDerived().TransformTemplateArgument(*A);
+ if (TA.isNull())
+ return TA;
+
+ TransformedArgs.push_back(TA);
+ }
+ TemplateArgument Result;
+ Result.setArgumentPack(TransformedArgs.data(), TransformedArgs.size(),
+ true);
+ return Result;
+ }
+ }
+
+ // Work around bogus GCC warning
+ return TemplateArgument();
+}
+
//===----------------------------------------------------------------------===//
// Type transformation
//===----------------------------------------------------------------------===//
@@ -558,14 +617,22 @@
if (ElementType.isNull())
return QualType();
+ // Array bounds are not potentially evaluated contexts
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
+ Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
+ if (Size.isInvalid())
+ return QualType();
+
if (!getDerived().AlwaysRebuild() &&
- ElementType == T->getElementType())
+ ElementType == T->getElementType() &&
+ Size.get() == T->getSizeExpr())
return QualType(T, 0);
return getDerived().RebuildConstantArrayWithExprType(ElementType,
T->getSizeModifier(),
T->getSize(),
- /*FIXME: Transform?*/T->getSizeExpr(),
+ Size.takeAs<Expr>(),
T->getIndexTypeQualifier(),
T->getBracketsRange());
}
@@ -611,6 +678,9 @@
if (ElementType.isNull())
return QualType();
+ // Array bounds are not potentially evaluated contexts
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
if (Size.isInvalid())
return QualType();
@@ -636,6 +706,9 @@
if (ElementType.isNull())
return QualType();
+ // Array bounds are not potentially evaluated contexts
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
if (Size.isInvalid())
return QualType();
@@ -661,6 +734,9 @@
if (ElementType.isNull())
return QualType();
+ // Vector sizes are not potentially evaluated contexts
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
if (Size.isInvalid())
return QualType();
@@ -757,6 +833,9 @@
template<typename Derived>
QualType TreeTransform<Derived>::TransformTypeOfExprType(
const TypeOfExprType *T) {
+ // typeof expressions are not potentially evaluated contexts
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
Sema::OwningExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
if (E.isInvalid())
return QualType();
@@ -785,6 +864,9 @@
template<typename Derived>
QualType TreeTransform<Derived>::TransformDecltypeType(const DecltypeType *T) {
+ // decltype expressions are not potentially evaluated contexts
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
Sema::OwningExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
if (E.isInvalid())
return QualType();