forked from OSchip/llvm-project
PR18401: Fix assert by implementing the current proposed direction of core
issue 1430. Don't allow a pack expansion to be used as an argument to an alias template unless the corresponding parameter is a parameter pack. llvm-svn: 198833
This commit is contained in:
parent
73f7b0273e
commit
83b11aae18
|
@ -3414,6 +3414,8 @@ def note_template_declared_here : Note<
|
|||
"%select{function template|class template|variable template"
|
||||
"|type alias template|template template parameter}0 "
|
||||
"%1 declared here">;
|
||||
def err_alias_template_expansion_into_fixed_list : Error<
|
||||
"pack expansion used as argument for non-pack parameter of alias template">;
|
||||
def note_parameter_type : Note<
|
||||
"parameter of type %0 is declared here">;
|
||||
|
||||
|
|
|
@ -5298,18 +5298,12 @@ public:
|
|||
/// \param Converted Will receive the converted, canonicalized template
|
||||
/// arguments.
|
||||
///
|
||||
///
|
||||
/// \param ExpansionIntoFixedList If non-NULL, will be set true to indicate
|
||||
/// when the template arguments contain a pack expansion that is being
|
||||
/// expanded into a fixed parameter list.
|
||||
///
|
||||
/// \returns True if an error occurred, false otherwise.
|
||||
/// \returns true if an error occurred, false otherwise.
|
||||
bool CheckTemplateArgumentList(TemplateDecl *Template,
|
||||
SourceLocation TemplateLoc,
|
||||
TemplateArgumentListInfo &TemplateArgs,
|
||||
bool PartialTemplateArgs,
|
||||
SmallVectorImpl<TemplateArgument> &Converted,
|
||||
bool *ExpansionIntoFixedList = 0);
|
||||
SmallVectorImpl<TemplateArgument> &Converted);
|
||||
|
||||
bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
|
||||
const TemplateArgumentLoc &Arg,
|
||||
|
|
|
@ -1975,17 +1975,15 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
|
|||
// Check that the template argument list is well-formed for this
|
||||
// template.
|
||||
SmallVector<TemplateArgument, 4> Converted;
|
||||
bool ExpansionIntoFixedList = false;
|
||||
if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs,
|
||||
false, Converted, &ExpansionIntoFixedList))
|
||||
false, Converted))
|
||||
return QualType();
|
||||
|
||||
QualType CanonType;
|
||||
|
||||
bool InstantiationDependent = false;
|
||||
TypeAliasTemplateDecl *AliasTemplate = 0;
|
||||
if (!ExpansionIntoFixedList &&
|
||||
(AliasTemplate = dyn_cast<TypeAliasTemplateDecl>(Template))) {
|
||||
if (TypeAliasTemplateDecl *AliasTemplate =
|
||||
dyn_cast<TypeAliasTemplateDecl>(Template)) {
|
||||
// Find the canonical type for this type alias template specialization.
|
||||
TypeAliasDecl *Pattern = AliasTemplate->getTemplatedDecl();
|
||||
if (Pattern->isInvalidDecl())
|
||||
|
@ -2590,11 +2588,10 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
|
|||
|
||||
// Check that the template argument list is well-formed for this template.
|
||||
SmallVector<TemplateArgument, 4> Converted;
|
||||
bool ExpansionIntoFixedList = false;
|
||||
if (CheckTemplateArgumentList(
|
||||
Template, TemplateNameLoc,
|
||||
const_cast<TemplateArgumentListInfo &>(TemplateArgs), false,
|
||||
Converted, &ExpansionIntoFixedList))
|
||||
Converted))
|
||||
return true;
|
||||
|
||||
// Find the variable template specialization declaration that
|
||||
|
@ -3549,11 +3546,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
|
|||
SourceLocation TemplateLoc,
|
||||
TemplateArgumentListInfo &TemplateArgs,
|
||||
bool PartialTemplateArgs,
|
||||
SmallVectorImpl<TemplateArgument> &Converted,
|
||||
bool *ExpansionIntoFixedList) {
|
||||
if (ExpansionIntoFixedList)
|
||||
*ExpansionIntoFixedList = false;
|
||||
|
||||
SmallVectorImpl<TemplateArgument> &Converted) {
|
||||
TemplateParameterList *Params = Template->getTemplateParameters();
|
||||
|
||||
SourceLocation RAngleLoc = TemplateArgs.getRAngleLoc();
|
||||
|
@ -3606,6 +3599,20 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
|
|||
ArgumentPack.size(), Converted))
|
||||
return true;
|
||||
|
||||
if (TemplateArgs[ArgIdx].getArgument().isPackExpansion() &&
|
||||
isa<TypeAliasTemplateDecl>(Template) &&
|
||||
!(Param + 1 == ParamEnd && (*Param)->isTemplateParameterPack() &&
|
||||
!getExpandedPackSize(*Param))) {
|
||||
// Core issue 1430: we have a pack expansion as an argument to an
|
||||
// alias template, and it's not part of a final parameter pack. This
|
||||
// can't be canonicalized, so reject it now.
|
||||
Diag(TemplateArgs[ArgIdx].getLocation(),
|
||||
diag::err_alias_template_expansion_into_fixed_list)
|
||||
<< TemplateArgs[ArgIdx].getSourceRange();
|
||||
Diag((*Param)->getLocation(), diag::note_template_param_here);
|
||||
return true;
|
||||
}
|
||||
|
||||
// We're now done with this argument.
|
||||
++ArgIdx;
|
||||
|
||||
|
@ -3652,9 +3659,6 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
|
|||
ArgumentPack.data(),
|
||||
ArgumentPack.size()));
|
||||
ArgumentPack.clear();
|
||||
} else if (ExpansionIntoFixedList) {
|
||||
// We have expanded a pack into a fixed list.
|
||||
*ExpansionIntoFixedList = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -2480,11 +2480,10 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
|
|||
|
||||
// Check that the template argument list is well-formed for this template.
|
||||
SmallVector<TemplateArgument, 4> Converted;
|
||||
bool ExpansionIntoFixedList = false;
|
||||
if (SemaRef.CheckTemplateArgumentList(
|
||||
VarTemplate, VarTemplate->getLocStart(),
|
||||
const_cast<TemplateArgumentListInfo &>(VarTemplateArgsInfo), false,
|
||||
Converted, &ExpansionIntoFixedList))
|
||||
Converted))
|
||||
return 0;
|
||||
|
||||
// Find the variable template specialization declaration that
|
||||
|
|
|
@ -121,7 +121,16 @@ namespace PartialSpecialization {
|
|||
|
||||
namespace FixedAliasTemplate {
|
||||
template<typename,typename,typename> struct S {};
|
||||
template<typename T, typename U> using U = S<T, int, U>;
|
||||
template<typename...Ts> U<Ts...> &f(U<Ts...>, Ts...);
|
||||
S<int, int, double> &s1 = f({}, 0, 0.0);
|
||||
template<typename T, typename U> using U = S<T, int, U>; // expected-note 2{{template parameter is declared here}}
|
||||
template<typename...Ts> U<Ts...> &f(U<Ts...>, Ts...); // expected-error 2{{pack expansion used as argument for non-pack parameter of alias template}}
|
||||
S<int, int, double> &s1 = f({}, 0, 0.0); // expected-error {{no matching function}}
|
||||
}
|
||||
|
||||
namespace PR18401 {
|
||||
template<typename... Args> struct foo { };
|
||||
template<typename T, typename... Args> using bar = foo<T, Args...>; // expected-note 2{{template parameter is declared here}} expected-note {{'bar' declared here}}
|
||||
template<typename T, typename... Args> using baz = bar<Args..., T>; // expected-error {{pack expansion used as argument for non-pack parameter of alias template}}
|
||||
// FIXME: We should still record the alias template, but mark it as invalid.
|
||||
template<typename...T> void f(baz<T...>); // expected-error {{no template named 'baz'; did you mean 'bar'}} expected-error {{pack expansion used as argument for non-pack}}
|
||||
void g() { f(foo<int, char, double>()); } // expected-error {{no matching function}}
|
||||
}
|
||||
|
|
|
@ -11,10 +11,6 @@ template<typename T> void g(T);
|
|||
|
||||
template<template<typename> class F> void h(F<int>);
|
||||
|
||||
template<typename,typename,typename> struct S {};
|
||||
template<typename T, typename U> using U = S<T, int, U>;
|
||||
template<typename...Ts> void h(U<Ts...>, Ts...);
|
||||
|
||||
// CHECK-LABEL: define void @_Z1zv(
|
||||
void z() {
|
||||
vector<int> VI;
|
||||
|
@ -42,7 +38,4 @@ void z() {
|
|||
Vec<Vec<int>> VVI;
|
||||
g(VVI);
|
||||
// CHECK: call void @_Z1gI6vectorIS0_Ii5allocIiEES1_IS3_EEEvT_(
|
||||
|
||||
// CHECK: call void @_Z1hIJidEEv1UIDpT_ES2_
|
||||
h({}, 0, 0.0);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS
|
||||
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING
|
||||
|
||||
template<class F, class ...Rest> struct first_impl { typedef F type; };
|
||||
template<class ...Args> using first = typename first_impl<Args...>::type;
|
||||
|
||||
namespace simple_explicit_capture {
|
||||
void test() {
|
||||
int i;
|
||||
|
@ -497,8 +500,6 @@ int run = fooT('a') + fooT(3.14);
|
|||
|
||||
template<class ... Ts> void print(Ts ... ts) { }
|
||||
|
||||
template<class F, class ... Rest> using first = F;
|
||||
|
||||
template<class ... Ts> auto fooV(Ts ... ts) {
|
||||
auto L = [](auto ... a) {
|
||||
auto M = [](decltype(a) ... b) {
|
||||
|
@ -568,7 +569,6 @@ int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expe
|
|||
namespace variadic_tests_1 {
|
||||
template<class ... Ts> void print(Ts ... ts) { }
|
||||
|
||||
template<class F, class ... Rest> using FirstType = F;
|
||||
template<class F, class ... Rest> F& FirstArg(F& f, Rest...) { return f; }
|
||||
|
||||
template<class ... Ts> int fooV(Ts ... ts) {
|
||||
|
@ -582,7 +582,7 @@ template<class ... Ts> int fooV(Ts ... ts) {
|
|||
};
|
||||
N('a');
|
||||
N(N);
|
||||
N(FirstType<Ts...>{});
|
||||
N(first<Ts...>{});
|
||||
};
|
||||
M(a...);
|
||||
print("a = ", a..., "\n");
|
||||
|
@ -607,7 +607,7 @@ template<class ... Ts> int fooV(Ts ... ts) {
|
|||
};
|
||||
N('a');
|
||||
N(N);
|
||||
N(FirstType<Ts...>{});
|
||||
N(first<Ts...>{});
|
||||
};
|
||||
M(a...);
|
||||
return M;
|
||||
|
@ -627,7 +627,7 @@ template<class ... Ts> int fooV(Ts ... ts) {
|
|||
};
|
||||
N('a');
|
||||
N(N);
|
||||
N(FirstType<Ts...>{});
|
||||
N(first<Ts...>{});
|
||||
return N;
|
||||
};
|
||||
M(a...);
|
||||
|
@ -771,7 +771,6 @@ int run = test();
|
|||
|
||||
|
||||
namespace fptr_with_decltype_return_type {
|
||||
template<class F, class ... Ts> using FirstType = F;
|
||||
template<class F, class ... Rest> F& FirstArg(F& f, Rest& ... r) { return f; };
|
||||
template<class ... Ts> auto vfun(Ts&& ... ts) {
|
||||
print(ts...);
|
||||
|
@ -782,7 +781,7 @@ int test()
|
|||
{
|
||||
auto L = [](auto ... As) {
|
||||
return [](auto b) ->decltype(b) {
|
||||
vfun([](decltype(As) a) -> decltype(a) { return a; } ...)(FirstType<decltype(As)...>{});
|
||||
vfun([](decltype(As) a) -> decltype(a) { return a; } ...)(first<decltype(As)...>{});
|
||||
return decltype(b){};
|
||||
};
|
||||
};
|
||||
|
@ -913,4 +912,4 @@ int run2 = x2.fooG3();
|
|||
|
||||
|
||||
|
||||
} //end ns inclass_lambdas_within_nested_classes
|
||||
} //end ns inclass_lambdas_within_nested_classes
|
||||
|
|
Loading…
Reference in New Issue