diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-11-09 19:17:50 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-11-09 19:17:50 +0000 |
commit | 0f8716b7bb25d61a82f699b3975167451f7b5a68 (patch) | |
tree | 14553c111b4a3ce70343f638e95df7fd7378d073 /lib/Sema/SemaTemplate.cpp | |
parent | 62cf322cf16dfbe58c56daecabb9cbcbb2bf38f7 (diff) |
Improve instantiation of default template arguments for nested
templates. The instantiation of these default arguments must be (and
now, is) delayed until the template argument is actually used, at
which point we substitute all levels of template arguments
concurrently.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86578 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 141 |
1 files changed, 110 insertions, 31 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 5ef370104d..0f7106135b 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1449,6 +1449,102 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, return false; } +/// \brief Substitute template arguments into the default template argument for +/// the given template type parameter. +/// +/// \param SemaRef the semantic analysis object for which we are performing +/// the substitution. +/// +/// \param Template the template that we are synthesizing template arguments +/// for. +/// +/// \param TemplateLoc the location of the template name that started the +/// template-id we are checking. +/// +/// \param RAngleLoc the location of the right angle bracket ('>') that +/// terminates the template-id. +/// +/// \param Param the template template parameter whose default we are +/// substituting into. +/// +/// \param Converted the list of template arguments provided for template +/// parameters that precede \p Param in the template parameter list. +/// +/// \returns the substituted template argument, or NULL if an error occurred. +static DeclaratorInfo * +SubstDefaultTemplateArgument(Sema &SemaRef, + TemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + TemplateTypeParmDecl *Param, + TemplateArgumentListBuilder &Converted) { + DeclaratorInfo *ArgType = Param->getDefaultArgumentInfo(); + + // If the argument type is dependent, instantiate it now based + // on the previously-computed template arguments. + if (ArgType->getType()->isDependentType()) { + TemplateArgumentList TemplateArgs(SemaRef.Context, Converted, + /*TakeArgs=*/false); + + MultiLevelTemplateArgumentList AllTemplateArgs + = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs); + + Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, + Template, Converted.getFlatArguments(), + Converted.flatSize(), + SourceRange(TemplateLoc, RAngleLoc)); + + ArgType = SemaRef.SubstType(ArgType, AllTemplateArgs, + Param->getDefaultArgumentLoc(), + Param->getDeclName()); + } + + return ArgType; +} + +/// \brief Substitute template arguments into the default template argument for +/// the given non-type template parameter. +/// +/// \param SemaRef the semantic analysis object for which we are performing +/// the substitution. +/// +/// \param Template the template that we are synthesizing template arguments +/// for. +/// +/// \param TemplateLoc the location of the template name that started the +/// template-id we are checking. +/// +/// \param RAngleLoc the location of the right angle bracket ('>') that +/// terminates the template-id. +/// +/// \param Param the template template parameter whose default we are +/// substituting into. +/// +/// \param Converted the list of template arguments provided for template +/// parameters that precede \p Param in the template parameter list. +/// +/// \returns the substituted template argument, or NULL if an error occurred. +static Sema::OwningExprResult +SubstDefaultTemplateArgument(Sema &SemaRef, + TemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + NonTypeTemplateParmDecl *Param, + TemplateArgumentListBuilder &Converted) { + TemplateArgumentList TemplateArgs(SemaRef.Context, Converted, + /*TakeArgs=*/false); + + MultiLevelTemplateArgumentList AllTemplateArgs + = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs); + + Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, + Template, Converted.getFlatArguments(), + Converted.flatSize(), + SourceRange(TemplateLoc, RAngleLoc)); + + return SemaRef.SubstExpr(Param->getDefaultArgument(), AllTemplateArgs); +} + /// \brief Check that the given template argument list is well-formed /// for specializing the given template. bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, @@ -1516,44 +1612,27 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, if (!TTP->hasDefaultArgument()) break; - DeclaratorInfo *ArgType = TTP->getDefaultArgumentInfo(); - - // If the argument type is dependent, instantiate it now based - // on the previously-computed template arguments. - if (ArgType->getType()->isDependentType()) { - InstantiatingTemplate Inst(*this, TemplateLoc, - Template, Converted.getFlatArguments(), - Converted.flatSize(), - SourceRange(TemplateLoc, RAngleLoc)); - - TemplateArgumentList TemplateArgs(Context, Converted, - /*TakeArgs=*/false); - ArgType = SubstType(ArgType, - MultiLevelTemplateArgumentList(TemplateArgs), - TTP->getDefaultArgumentLoc(), - TTP->getDeclName()); - } - + DeclaratorInfo *ArgType = SubstDefaultTemplateArgument(*this, + Template, + TemplateLoc, + RAngleLoc, + TTP, + Converted); if (!ArgType) return true; - - Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()), ArgType); + + Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()), + ArgType); } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { if (!NTTP->hasDefaultArgument()) break; - InstantiatingTemplate Inst(*this, TemplateLoc, - Template, Converted.getFlatArguments(), - Converted.flatSize(), - SourceRange(TemplateLoc, RAngleLoc)); - - TemplateArgumentList TemplateArgs(Context, Converted, - /*TakeArgs=*/false); - - Sema::OwningExprResult E - = SubstExpr(NTTP->getDefaultArgument(), - MultiLevelTemplateArgumentList(TemplateArgs)); + Sema::OwningExprResult E = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + NTTP, + Converted); if (E.isInvalid()) return true; |