diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-11-11 21:54:23 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-11-11 21:54:23 +0000 |
commit | f35f828f9883123772a9731af190a608f3236ef4 (patch) | |
tree | 01f5a4ff2168279d314ec964b4531d78185a8f8b /lib/Sema/SemaTemplate.cpp | |
parent | 961c76ea8d5089293e448e5d538570653e28080c (diff) |
Improve diagnostics when a default template argument does not match
with its corresponding template parameter. This can happen when we
performed some substitution into the default template argument and
what we had doesn't match any more, e.g.,
template<int> struct A;
template<typename T, template<T> class X = A> class B;
B<long> b;
Previously, we'd emit a pretty but disembodied diagnostic showing how
the default argument didn't match the template parameter. The
diagnostic was good, but nothing tied it to the *use* of the default
argument in "B<long>". This commit fixes that.
Also, tweak the counting of active template instantiations to avoid
counting non-instantiation records, such as those we create for
(surprise!) checking default arguments, instantiating default
arguments, and performing substitutions as part of template argument
deduction.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86884 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 132 |
1 files changed, 73 insertions, 59 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index aace983441..ee928bccaf 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1856,73 +1856,87 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, continue; } - // Decode the template argument + if (ArgIdx < NumArgs) { + // Check the template argument we were given. + if (CheckTemplateArgument(*Param, TemplateArgs[ArgIdx], Template, + TemplateLoc, RAngleLoc, Converted)) + return true; + + continue; + } + + // We have a default template argument that we will use. TemplateArgumentLoc Arg; + + // Retrieve the default template argument from the template + // parameter. For each kind of template parameter, we substitute the + // template arguments provided thus far and any "outer" template arguments + // (when the template parameter was part of a nested template) into + // the default argument. + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) { + if (!TTP->hasDefaultArgument()) { + assert((Invalid || PartialTemplateArgs) && "Missing default argument"); + break; + } - if (ArgIdx >= NumArgs) { - // Retrieve the default template argument from the template - // parameter. - if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) { - if (TTP->isParameterPack()) { - // We have an empty argument pack. - Converted.BeginPack(); - Converted.EndPack(); - break; - } - - if (!TTP->hasDefaultArgument()) - break; - - DeclaratorInfo *ArgType = SubstDefaultTemplateArgument(*this, - Template, - TemplateLoc, - RAngleLoc, - TTP, - Converted); - if (!ArgType) - return true; - - Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()), - ArgType); - } else if (NonTypeTemplateParmDecl *NTTP - = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { - if (!NTTP->hasDefaultArgument()) - break; - - Sema::OwningExprResult E = SubstDefaultTemplateArgument(*this, Template, - TemplateLoc, - RAngleLoc, - NTTP, - Converted); - if (E.isInvalid()) - return true; + DeclaratorInfo *ArgType = SubstDefaultTemplateArgument(*this, + Template, + TemplateLoc, + RAngleLoc, + TTP, + Converted); + if (!ArgType) + return true; + + Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()), + ArgType); + } else if (NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { + if (!NTTP->hasDefaultArgument()) { + assert((Invalid || PartialTemplateArgs) && "Missing default argument"); + break; + } - Expr *Ex = E.takeAs<Expr>(); - Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex); - } else { - TemplateTemplateParmDecl *TempParm - = cast<TemplateTemplateParmDecl>(*Param); + Sema::OwningExprResult E = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + NTTP, + Converted); + if (E.isInvalid()) + return true; - if (!TempParm->hasDefaultArgument()) - break; + Expr *Ex = E.takeAs<Expr>(); + Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex); + } else { + TemplateTemplateParmDecl *TempParm + = cast<TemplateTemplateParmDecl>(*Param); - TemplateName Name = SubstDefaultTemplateArgument(*this, Template, - TemplateLoc, - RAngleLoc, - TempParm, - Converted); - if (Name.isNull()) - return true; - - Arg = TemplateArgumentLoc(TemplateArgument(Name), - TempParm->getDefaultArgument().getTemplateQualifierRange(), - TempParm->getDefaultArgument().getTemplateNameLoc()); + if (!TempParm->hasDefaultArgument()) { + assert((Invalid || PartialTemplateArgs) && "Missing default argument"); + break; } - } else { - // Retrieve the template argument produced by the user. - Arg = TemplateArgs[ArgIdx]; + + TemplateName Name = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + TempParm, + Converted); + if (Name.isNull()) + return true; + + Arg = TemplateArgumentLoc(TemplateArgument(Name), + TempParm->getDefaultArgument().getTemplateQualifierRange(), + TempParm->getDefaultArgument().getTemplateNameLoc()); } + // Introduce an instantiation record that describes where we are using + // the default template argument. + InstantiatingTemplate Instantiating(*this, RAngleLoc, Template, *Param, + Converted.getFlatArguments(), + Converted.flatSize(), + SourceRange(TemplateLoc, RAngleLoc)); + + // Check the default template argument. if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc, RAngleLoc, Converted)) return true; |