c++: pack in enumerator in lambda [PR100198]
The GCC 8 lambda overhaul fixed most uses of lambdas in pack expansions, but local enums and classes within such lambdas that depend on parameter packs are still broken. For now, give a sorry instead of an ICE or incorrect error. PR c++/100198 PR c++/100030 PR c++/100282 gcc/cp/ChangeLog: * parser.cc (cp_parser_enumerator_definition): Sorry on parameter pack in lambda. (cp_parser_class_head): And in class attributes. * pt.cc (check_for_bare_parameter_packs): Sorry instead of error in lambda. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/lambda/lambda-variadic13.C: Accept the sorry as well as the correct error. * g++.dg/cpp0x/lambda/lambda-variadic14.C: Likewise. * g++.dg/cpp0x/lambda/lambda-variadic14a.C: New test. * g++.dg/cpp0x/lambda/lambda-variadic15.C: New test. * g++.dg/cpp0x/lambda/lambda-variadic16.C: New test.
This commit is contained in:
parent
99f17e996f
commit
4d2efec9f2
|
@ -21146,7 +21146,16 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type)
|
|||
|
||||
/* If we are processing a template, make sure the initializer of the
|
||||
enumerator doesn't contain any bare template parameter pack. */
|
||||
if (check_for_bare_parameter_packs (value))
|
||||
if (current_lambda_expr ())
|
||||
{
|
||||
/* In a lambda it should work, but doesn't currently. */
|
||||
if (uses_parameter_packs (value))
|
||||
{
|
||||
sorry ("unexpanded parameter pack in enumerator in lambda");
|
||||
value = error_mark_node;
|
||||
}
|
||||
}
|
||||
else if (check_for_bare_parameter_packs (value))
|
||||
value = error_mark_node;
|
||||
|
||||
/* Create the enumerator. */
|
||||
|
@ -26624,6 +26633,14 @@ cp_parser_class_head (cp_parser* parser,
|
|||
|
||||
if (type)
|
||||
{
|
||||
if (current_lambda_expr ()
|
||||
&& uses_parameter_packs (attributes))
|
||||
{
|
||||
/* In a lambda this should work, but doesn't currently. */
|
||||
sorry ("unexpanded parameter pack in local class in lambda");
|
||||
attributes = NULL_TREE;
|
||||
}
|
||||
|
||||
/* Apply attributes now, before any use of the class as a template
|
||||
argument in its base list. */
|
||||
cplus_decl_attributes (&type, attributes, (int)ATTR_FLAG_TYPE_IN_PLACE);
|
||||
|
|
23
gcc/cp/pt.cc
23
gcc/cp/pt.cc
|
@ -4273,10 +4273,27 @@ check_for_bare_parameter_packs (tree t, location_t loc /* = UNKNOWN_LOCATION */)
|
|||
cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
|
||||
delete ppd.visited;
|
||||
|
||||
if (!parameter_packs)
|
||||
return false;
|
||||
|
||||
if (loc == UNKNOWN_LOCATION)
|
||||
loc = cp_expr_loc_or_input_loc (t);
|
||||
|
||||
/* It's OK for a lambda to have an unexpanded parameter pack from the
|
||||
containing context, but do complain about unexpanded capture packs. */
|
||||
if (current_class_type && LAMBDA_TYPE_P (current_class_type)
|
||||
&& CLASSTYPE_TEMPLATE_INFO (current_class_type))
|
||||
tree lam = current_lambda_expr ();
|
||||
if (lam)
|
||||
lam = TREE_TYPE (lam);
|
||||
|
||||
if (lam && lam != current_class_type)
|
||||
{
|
||||
/* We're in a lambda, but it isn't the innermost class.
|
||||
This should work, but currently doesn't. */
|
||||
sorry_at (loc, "unexpanded parameter pack in local class in lambda");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lam && CLASSTYPE_TEMPLATE_INFO (lam))
|
||||
for (; parameter_packs;
|
||||
parameter_packs = TREE_CHAIN (parameter_packs))
|
||||
{
|
||||
|
@ -4287,8 +4304,6 @@ check_for_bare_parameter_packs (tree t, location_t loc /* = UNKNOWN_LOCATION */)
|
|||
|
||||
if (parameter_packs)
|
||||
{
|
||||
if (loc == UNKNOWN_LOCATION)
|
||||
loc = cp_expr_loc_or_input_loc (t);
|
||||
error_at (loc, "parameter packs not expanded with %<...%>:");
|
||||
while (parameter_packs)
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
template <class... Ts>
|
||||
void f() {
|
||||
[] { struct S : Ts { }; }; // { dg-error "not expanded" }
|
||||
[] { struct S : Ts { }; }; // { dg-message "" }
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
|
|
@ -3,6 +3,6 @@
|
|||
|
||||
template <int... E>
|
||||
void f() {
|
||||
[] { enum e { e = E }; }; // { dg-error "not expanded" }
|
||||
[] { enum e { e = E }; }; // { dg-message "" }
|
||||
}
|
||||
template void f<>();
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
// PR c++/100198
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
template <int... E>
|
||||
void f() {
|
||||
([] { enum e { e = E }; }(), ...); // { dg-bogus "" "" { xfail *-*-* } }
|
||||
}
|
||||
|
||||
template void f<0>();
|
|
@ -0,0 +1,14 @@
|
|||
// PR c++/100030
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
template <class... Ts>
|
||||
void sink(Ts...);
|
||||
|
||||
template <class... Ts>
|
||||
void f(Ts...) {
|
||||
sink([] { struct alignas(Ts) S {}; }...); // { dg-bogus "" "" { xfail *-*-* } }
|
||||
}
|
||||
|
||||
int main() {
|
||||
f(0);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// PR c++/100282
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
template <typename... Ts>
|
||||
void
|
||||
local_class ()
|
||||
{
|
||||
int { []{ struct ZZ : Ts {}; }... }; // { dg-bogus "" "" { xfail *-*-* } }
|
||||
}
|
||||
|
||||
template // <>
|
||||
void
|
||||
local_class<int> ();
|
Loading…
Reference in New Issue