diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index a995181d0198..c281b96a9ea6 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -331,9 +331,6 @@ namespace { /// \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); @@ -360,11 +357,6 @@ TemplateInstantiator::TransformTemplateName(TemplateName Template) { TemplateArgs); } -TemplateArgument -TemplateInstantiator::TransformTemplateArgument(const TemplateArgument &Arg) { - return getSema().Instantiate(Arg, TemplateArgs); -} - QualType TemplateInstantiator::TransformTemplateTypeParmType( const TemplateTypeParmType *T) { @@ -852,42 +844,7 @@ Sema::InstantiateTemplateName(TemplateName Name, SourceLocation Loc, TemplateArgument Sema::Instantiate(TemplateArgument Arg, const TemplateArgumentList &TemplateArgs) { - switch (Arg.getKind()) { - case TemplateArgument::Null: - assert(false && "Should never have a NULL template argument"); - break; - - case TemplateArgument::Type: { - QualType T = InstantiateType(Arg.getAsType(), TemplateArgs, - Arg.getLocation(), DeclarationName()); - if (T.isNull()) - return TemplateArgument(); - - return TemplateArgument(Arg.getLocation(), T); - } - - case TemplateArgument::Declaration: - // FIXME: Template instantiation for template template parameters. - return Arg; - - case TemplateArgument::Integral: - return Arg; - - case TemplateArgument::Expression: { - // Template argument expressions are not potentially evaluated. - EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated); - - Sema::OwningExprResult E = InstantiateExpr(Arg.getAsExpr(), TemplateArgs); - if (E.isInvalid()) - return TemplateArgument(); - return TemplateArgument(E.takeAs()); - } - - case TemplateArgument::Pack: - assert(0 && "FIXME: Implement!"); - break; - } - - assert(false && "Unhandled template argument kind"); - return TemplateArgument(); + TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(), + DeclarationName()); + return Instantiator.TransformTemplateArgument(Arg); } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 622f7b44cd92..0aefda7f1187 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -47,7 +47,7 @@ namespace clang { /// 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 @@ public: /// \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 @@ public: } }; +template +TemplateArgument +TreeTransform::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()); + } + + case TemplateArgument::Pack: { + llvm::SmallVector 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 @@ TreeTransform::TransformConstantArrayWithExprType( 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(), T->getIndexTypeQualifier(), T->getBracketsRange()); } @@ -611,6 +678,9 @@ QualType TreeTransform::TransformVariableArrayType( 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 @@ QualType TreeTransform::TransformDependentSizedArrayType( 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 @@ QualType TreeTransform::TransformDependentSizedExtVectorType( 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 @@ QualType TreeTransform::TransformTypedefType(const TypedefType *T) { template QualType TreeTransform::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 @@ QualType TreeTransform::TransformTypeOfType(const TypeOfType *T) { template QualType TreeTransform::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();