summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-06-20 19:49:13 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-06-20 19:49:13 +0000
commit07ed9cfc3e8db2d6acf2412bc138d61e88ccc5f5 (patch)
tree4c38e7c51bc560d6994f559fb0a15cd08130f26d /clang/lib/Sema/SemaTemplate.cpp
parent97dc622ab3f77d877ee302908dec20d9dbddfe2b (diff)
downloadbcm5719-llvm-07ed9cfc3e8db2d6acf2412bc138d61e88ccc5f5.tar.gz
bcm5719-llvm-07ed9cfc3e8db2d6acf2412bc138d61e88ccc5f5.zip
Fix crash and rejects-valid when a later template parameter or default
template argument contains a backreference to a dependently-typed earlier parameter. In a case like: template<typename T, T A, decltype(A) = A> struct X {}; template<typename U> auto Y = X<U, 0>(); we previously treated both references to `A` in the third parameter as being of type `int` when checking the template-id in `Y`. That`s wrong; the type of `A` in these contexts is the dependent type `U`. When we encounter a non-type template argument that we can't convert to the parameter type because of type-dependence, we now insert a dependent conversion node so that the SubstNonTypeTemplateParmExpr for the template argument will have the parameter's type rather than whatever type the argument had. llvm-svn: 363972
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp45
1 files changed, 35 insertions, 10 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 74a891bcb70..7b0a3a3e094 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4888,10 +4888,22 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
Converted);
- NTTPType = SubstType(NTTPType,
- MultiLevelTemplateArgumentList(TemplateArgs),
- NTTP->getLocation(),
- NTTP->getDeclName());
+
+ // If the parameter is a pack expansion, expand this slice of the pack.
+ if (auto *PET = NTTPType->getAs<PackExpansionType>()) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this,
+ ArgumentPackIndex);
+ NTTPType = SubstType(PET->getPattern(),
+ MultiLevelTemplateArgumentList(TemplateArgs),
+ NTTP->getLocation(),
+ NTTP->getDeclName());
+ } else {
+ NTTPType = SubstType(NTTPType,
+ MultiLevelTemplateArgumentList(TemplateArgs),
+ NTTP->getLocation(),
+ NTTP->getDeclName());
+ }
+
// If that worked, check the non-type template parameter type
// for validity.
if (!NTTPType.isNull())
@@ -6310,9 +6322,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// When checking a deduced template argument, deduce from its type even if
// the type is dependent, in order to check the types of non-type template
// arguments line up properly in partial ordering.
- Optional<unsigned> Depth;
- if (CTAK != CTAK_Specified)
- Depth = Param->getDepth() + 1;
+ Optional<unsigned> Depth = Param->getDepth() + 1;
if (DeduceAutoType(
Context.getTrivialTypeSourceInfo(ParamType, Param->getLocation()),
Arg, ParamType, Depth) == DAR_Failed) {
@@ -6367,9 +6377,24 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// If either the parameter has a dependent type or the argument is
// type-dependent, there's nothing we can check now.
if (ParamType->isDependentType() || Arg->isTypeDependent()) {
- // FIXME: Produce a cloned, canonical expression?
- Converted = TemplateArgument(Arg);
- return Arg;
+ // Force the argument to the type of the parameter to maintain invariants.
+ auto *PE = dyn_cast<PackExpansionExpr>(Arg);
+ if (PE)
+ Arg = PE->getPattern();
+ ExprResult E = ImpCastExprToType(
+ Arg, ParamType.getNonLValueExprType(Context), CK_Dependent,
+ ParamType->isLValueReferenceType() ? VK_LValue :
+ ParamType->isRValueReferenceType() ? VK_XValue : VK_RValue);
+ if (E.isInvalid())
+ return ExprError();
+ if (PE) {
+ // Recreate a pack expansion if we unwrapped one.
+ E = new (Context)
+ PackExpansionExpr(E.get()->getType(), E.get(), PE->getEllipsisLoc(),
+ PE->getNumExpansions());
+ }
+ Converted = TemplateArgument(E.get());
+ return E;
}
// The initialization of the parameter from the argument is
OpenPOWER on IntegriCloud