Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1454,6 +1454,11 @@ changed below to be TRUE for certain kinds of expressions and/or contexts.
#endif /* MICROSOFT_EXTENSIONS_ALLOWED */
if (suppress_warning) {
/* The caller has requested that warnings be suppressed. */
} else if (in_generic_lambda_in_real_instantiation()) {
/* A hybrid expansion can collapse to an expression with no effect in
this prototype instantiation. Wait for the real instantiation rather
than diagnosing that transient form. */
suppress_warning = TRUE;
} else if (expr_stack->is_type_operator_arg_expression) {
/* decltype expressions are sometimes written to check SFINAE
conditions, so do not warn inside them. */
Expand Down
14 changes: 14 additions & 0 deletions src/pending_changes/gh-500.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[GH #500]
Empty enclosing packs in generic lambdas

A pack expansion in a generic lambda nested in a template instantiation could
produce an error node in the IL when it referenced a lambda parameter pack
before an empty enclosing parameter pack. Empty enclosing packs are now
handled correctly regardless of the order of the pack references. Spurious
warnings from prototype instantiations in such cases are also suppressed. For
example, with --c++20 -tused:

template<int... Is> void f() {
[]<int... Js>() { ((Js * Is) * ... * 1); };
}
template void f<>(); // Previously produced an error node in the IL.
7 changes: 6 additions & 1 deletion src/scope_stk.c
Original file line number Diff line number Diff line change
Expand Up @@ -12548,7 +12548,7 @@ have a pack expansion so that it can be expanded in a rescan context.
} /* add_pack_expansion_descr_to_prototype_arg */


static a_boolean in_generic_lambda_in_real_instantiation(void)
a_boolean in_generic_lambda_in_real_instantiation(void)
/*
Return TRUE if we are in the definition of a generic lambda that is nested
inside a real instantiation. In such contexts, a kind of "hybrid expansion"
Expand Down Expand Up @@ -12836,6 +12836,11 @@ lengths) *err is set to TRUE, FALSE otherwise.
/* Got an expansion from an enclosing real instantiation and an
unexpanded pack from a nested generic lambda. */
has_hybrid_pack_expansion = TRUE;
if (elements_for_pack == 0) {
/* An empty enclosing pack makes the expansion empty even if an
unexpanded pack from the lambda was encountered first. */
elements = 0;
} /* if */
} else if (!is_rescan) {
pos_st2_error(ec_pack_length_mismatch, &prp->position,
prp->symbol->header->identifier,
Expand Down
2 changes: 2 additions & 0 deletions src/scope_stk.h
Original file line number Diff line number Diff line change
Expand Up @@ -2632,6 +2632,8 @@ extern void end_prescan_context(
a_boolean saved_in_disambiguation,
a_boolean saved_source_sequence_entries_disallowed);

extern a_boolean in_generic_lambda_in_real_instantiation(void);

extern a_boolean in_generic_lambda_in_prototype_instantiation(void);

extern a_routine_ptr enclosing_nonlambda_routine_for_lambda_class(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,4 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
baz<TTPs>;
^

"Test_name.c", line 130: error: template template parameter "<error>" is not compatible with template template parameter "<unnamed>"
baz<TTPs>;
^
detected during instantiation of "void GH112352::S::foldExpr2<TTPs...>() [with TTPs=<>]" at line 139

"Test_name.c", line 131: error: too many arguments for template template parameter "TTPs"
TTPs<int> D;
^
detected during instantiation of "void GH112352::S::foldExpr2<TTPs...>() [with TTPs=<>]" at line 139

5 errors detected in the compilation of "Test_name.c".
3 errors detected in the compilation of "Test_name.c".
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,4 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
instantiation of function "lambda []()->void [with Ts=<int, int>]" at line 55
instantiation of "void GH63677::f<<unnamed>>() [with <unnamed>=int]" at line 58

"Test_name.c", line 130: error: template template parameter "<error>" is not compatible with template template parameter "<unnamed>"
baz<TTPs>;
^
detected during instantiation of "void GH112352::S::foldExpr2<TTPs...>() [with TTPs=<>]" at line 139

"Test_name.c", line 131: error: too many arguments for template template parameter "TTPs"
TTPs<int> D;
^
detected during instantiation of "void GH112352::S::foldExpr2<TTPs...>() [with TTPs=<>]" at line 139

9 errors detected in the compilation of "Test_name.c".
7 errors detected in the compilation of "Test_name.c".
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,4 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
instantiation of function "lambda []()->void [with Ts=<int, int>]" at line 55
instantiation of "void GH63677::f<<unnamed>>() [with <unnamed>=int]" at line 58

"Test_name.c", line 130: error: template template parameter "<error>" is not compatible with template template parameter "<unnamed>"
baz<TTPs>;
^
detected during instantiation of "void GH112352::S::foldExpr2<TTPs...>() [with TTPs=<>]" at line 139

"Test_name.c", line 131: error: too many arguments for template template parameter "TTPs"
TTPs<int> D;
^
detected during instantiation of "void GH112352::S::foldExpr2<TTPs...>() [with TTPs=<>]" at line 139

9 errors detected in the compilation of "Test_name.c".
7 errors detected in the compilation of "Test_name.c".
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ fe_only -DTEST_NUMBER=1 --gnu_version=999999 -tused -e 200 --no_wrap --no_wrap_d
"Test_name.c", line 10: warning: expression has no effect
(..., ts);
^
detected during instantiation of "void f(Ts...) [with Ts=<int, char>]" at line 16
detected during:
instantiation of function "lambda [](auto)->auto [with <auto-1>=int]" at line 12
instantiation of "void f(Ts...) [with Ts=<int, char>]" at line 16

"Test_name.c", line 10: warning: expression has no effect
(..., ts);
^
detected during instantiation of "void f(Ts...) [with Ts=<int, char>]" at line 16
detected during:
instantiation of function "lambda [](auto)->auto [with <auto-1>=int]" at line 12
instantiation of "void f(Ts...) [with Ts=<int, char>]" at line 16

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ fe_only -DTEST_NUMBER=1 --gnu_version=999999 -tused -e 200 --no_wrap --no_wrap_d
ys;
^
detected during:
instantiation of function "lambda [](auto &...)->auto [with <auto-1>=<int>]" at line 26
instantiation of function "lambda [](auto)->auto [with <auto-1>=int]" at line 11
instantiation of "void X::f(F) [with F=lambda [](auto)->auto]" at line 26
instantiation of "void bug(Xs...) [with Xs=<X>]" at line 31

8 changes: 8 additions & 0 deletions tests/tests/regressions/.gh-500-warnings.rto/default.1.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fe_only -DTEST_NUMBER=1 -tused --c++20 Test_name.c
"Test_name.c", line 17: warning: expression has no effect
auto l = []<int... S>() { ((S * V) * ... * 1); };
^
detected during:
instantiation of function "lambda []()->auto [with S=<3>]" at line 18
instantiation of "void real_instantiation::f<V...>() [with V=<2>]" at line 21

8 changes: 8 additions & 0 deletions tests/tests/regressions/.gh-500-warnings.rto/default.2.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fe_only -DTEST_NUMBER=2 -tused --c++20 --gnu_version 150200 Test_name.c
"Test_name.c", line 17: warning: expression has no effect
auto l = []<int... S>() { ((S * V) * ... * 1); };
^
detected during:
instantiation of function "lambda []()->auto [with S=<3>]" at line 18
instantiation of "void real_instantiation::f<V...>() [with V=<2>]" at line 21

8 changes: 8 additions & 0 deletions tests/tests/regressions/.gh-500-warnings.rto/default.3.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fe_only -DTEST_NUMBER=3 -tused --c++20 --clang_version 220100 Test_name.c
"Test_name.c", line 17: warning: expression has no effect
auto l = []<int... S>() { ((S * V) * ... * 1); };
^
detected during:
instantiation of function "lambda []()->auto [with S=<3>]" at line 18
instantiation of "void real_instantiation::f<V...>() [with V=<2>]" at line 21

8 changes: 8 additions & 0 deletions tests/tests/regressions/.gh-500-warnings.rto/default.4.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fe_only -DTEST_NUMBER=4 -tused --ms_c++20 --microsoft_version 1950 Test_name.c
"Test_name.c", line 17: warning: expression has no effect
auto l = []<int... S>() { ((S * V) * ... * 1); };
^
detected during:
instantiation of function "lambda []()->auto [with S=<3>]" at line 18
instantiation of "void real_instantiation::f<V...>() [with V=<2>]" at line 21

1 change: 1 addition & 0 deletions tests/tests/regressions/.gh-500.rto/default.1.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fe_only -DTEST_NUMBER=1 --il_display -tused --c++20 Test_name.c
1 change: 1 addition & 0 deletions tests/tests/regressions/.gh-500.rto/default.2.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fe_only -DTEST_NUMBER=2 --il_display -tused --c++20 --gn 150200 Test_name.c
1 change: 1 addition & 0 deletions tests/tests/regressions/.gh-500.rto/default.3.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fe_only -DTEST_NUMBER=3 --il_display -tused --c++20 --clang_version 220100 Test_name.c
1 change: 1 addition & 0 deletions tests/tests/regressions/.gh-500.rto/default.4.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fe_only -DTEST_NUMBER=4 --il_display -tused --ms_c++20 --microsoft_version 1950 Test_name.c
22 changes: 22 additions & 0 deletions tests/tests/regressions/gh-500-warnings.sft.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//type:fp
//options:--c++20:--c++20 --gnu_version 150200:--c++20 --clang_version 220100:--ms_c++20 --microsoft_version 1950
//options_all:-tused

namespace suppressed_in_prototype
{
template<int... V> void f() {
[]<int... S>() { ((S * V) * ... * 1); };
}

template void f<>();
}

namespace real_instantiation
{
template<int... V> void f() {
auto l = []<int... S>() { ((S * V) * ... * 1); };
l.template operator()<3>();
}

template void f<2>();
}
43 changes: 43 additions & 0 deletions tests/tests/regressions/gh-500.sft.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//type:fp
//options:--c++20:--c++20 --gn 150200:--c++20 --clang_version 220100:--ms_c++20 --microsoft_version 1950
//options_all:--il_display -tused
//filter:grep -E '(tk_error|enk_error)'

namespace minimal
{
template<int... Is> void f() {
[]<int... Js>() { ((Js * Is) * ... * 1); };
}
template void f<>();
}

namespace inner_pack_first
{
template<int... V> constexpr auto f() {
return []<int... S>() { return ((S * V) * ... * 1); };
}

static_assert(f<>().template operator()<>() == 1);
static_assert(f<2>().template operator()<3>() == 6);
static_assert(f<2, 3>().template operator()<4, 5>() == 120);
}

namespace outer_pack_first
{
template<int... V> constexpr auto f() {
return []<int... S>() { return ((V * S) * ... * 1); };
}

static_assert(f<>().template operator()<>() == 1);
static_assert(f<2>().template operator()<3>() == 6);
static_assert(f<2, 3>().template operator()<4, 5>() == 120);
}

namespace uninstantiated_lambda
{
template<int... V> void f() {
[]<int... S>() { (void)((S * V) * ... * 1); };
}

void g() { f<>(); }
}
Loading