>> This patch would like to avoid the ICE when template lambdas call with >> default parameters in unevaluated context. The bug is the same as >> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119385. For example as blow: >> >> 1 | template <class T> >> 2 | void foo(T x) { >> 3 | sizeof []<int=0>(T=x) { return 0; }(); >> 4 | } >> 5 | >> 6 | void test { >> 7 | foo(0); >> 8 | } >> >> when compile with -fsyntax-only -std=c++20, it will have ICE similar as below >> >> test.cc: In instantiation of 'void foo(T) [with T = int]': >> test.cc:7:6: required from here >> 6 | foo(0); >> | ~~~^~~ >> test.cc:3:38: internal compiler error: in tsubst_expr, at cp/pt.cc:21919 >> 2 | sizeof []<int=0>(T=x) { return 0; }(); >> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~ >> >> And if without the template code `<int=0>`, the code will pass compile, it's >> wrong. >> >> When parsing lambda, the sizeof will affect the lambda internal unevaluated >> operand >> being handled. So consider save/restore cp_unevaluated_operand. >> >> gcc/cp/ChangeLog: >> >> * parser.cc (cp_parser_lambda_expression): Save/restore >> cp_unevaluated_operand when parser lambda. >> >> gcc/testsuite/ChangeLog: >> >> * g++.dg/cpp2a/lambda-uneval25.C: New test. >> --- >> gcc/cp/parser.cc | 4 ++++ >> gcc/testsuite/g++.dg/cpp2a/lambda-uneval25.C | 11 +++++++++++ >> 2 files changed, 15 insertions(+) >> create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-uneval25.C >> >> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc >> index 57a461042bf..9cc51f57fa7 100644 >> --- a/gcc/cp/parser.cc >> +++ b/gcc/cp/parser.cc >> @@ -11754,6 +11754,8 @@ cp_parser_lambda_expression (cp_parser* parser) >> /* Inside the class, surrounding template-parameter-lists do not >> apply. */ >> unsigned int saved_num_template_parameter_lists >> = parser->num_template_parameter_lists; >> + /* Inside the lambda, outside unevaluated context do not apply. */ >> + int saved_cp_unevaluated_operand = cp_unevaluated_operand;
> Instead of following the surrounding pattern, please use cp_evaluated. > That avoids the need for any change in the other two places. OK, I've replace it with cp_evaluated. >> unsigned char in_statement = parser->in_statement; >> bool in_switch_statement_p = parser->in_switch_statement_p; >> bool fully_implicit_function_template_p >> @@ -11765,6 +11767,7 @@ cp_parser_lambda_expression (cp_parser* parser) >> bool saved_omp_array_section_p = parser->omp_array_section_p; >> >> parser->num_template_parameter_lists = 0; >> + cp_unevaluated_operand = 0; >> parser->in_statement = 0; >> parser->in_switch_statement_p = false; >> parser->fully_implicit_function_template_p = false; >> @@ -11814,6 +11817,7 @@ cp_parser_lambda_expression (cp_parser* parser) >> in_discarded_stmt = discarded; >> >> parser->num_template_parameter_lists = >> saved_num_template_parameter_lists; >> + cp_unevaluated_operand = saved_cp_unevaluated_operand; >> parser->in_statement = in_statement; >> parser->in_switch_statement_p = in_switch_statement_p; >> parser->fully_implicit_function_template_p >> diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-uneval25.C >> b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval25.C >> new file mode 100644 >> index 00000000000..7fdd44d3ddd >> --- /dev/null >> +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval25.C >> @@ -0,0 +1,11 @@ >> +// { dg-do compile { target c++20 } } >> + >> +template <class T> >> +void foo(T x) { >> + sizeof []<int=0>(T=x) { return 0; }(); // { dg-error "may not appear" } >> + sizeof [](T=x) { return 0; }(); // { dg-error "may not appear" } >> +}; >> + >> +void test() { >> + foo(0); >> +} -- >8 -- This patch would like to avoid the ICE when template lambdas call with default parameters in unevaluated context. The bug is the same as https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119385. For example as blow: 1 | template <class T> 2 | void foo(T x) { 3 | sizeof []<int=0>(T=x) { return 0; }(); 4 | } 5 | 6 | void test { 7 | foo(0); 8 | } when compile with -fsyntax-only -std=c++20, it will have ICE similar as below test.cc: In instantiation of 'void foo(T) [with T = int]': test.cc:7:6: required from here 6 | foo(0); | ~~~^~~ test.cc:3:38: internal compiler error: in tsubst_expr, at cp/pt.cc:21919 2 | sizeof []<int=0>(T=x) { return 0; }(); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~ And if without the template code `<int=0>`, the code will pass compile, it's wrong. When parsing lambda, the sizeof will affect the lambda internal unevaluated operand being handled. So consider save/restore cp_unevaluated_operand. gcc/cp/ChangeLog: * parser.cc (cp_parser_lambda_expression): Use cp_evaluated. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/lambda-uneval25.C: New test. --- gcc/cp/parser.cc | 3 +++ gcc/testsuite/g++.dg/cpp2a/lambda-uneval25.C | 11 +++++++++++ 2 files changed, 14 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-uneval25.C diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 57a461042bf..0fd7e2de97b 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -11773,6 +11773,9 @@ cp_parser_lambda_expression (cp_parser* parser) parser->auto_is_implicit_function_template_parm_p = false; parser->omp_array_section_p = false; + /* Inside the lambda, outside unevaluated context do not apply. */ + cp_evaluated ev; + /* The body of a lambda in a discarded statement is not discarded. */ bool discarded = in_discarded_stmt; in_discarded_stmt = 0; diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-uneval25.C b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval25.C new file mode 100644 index 00000000000..7fdd44d3ddd --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval25.C @@ -0,0 +1,11 @@ +// { dg-do compile { target c++20 } } + +template <class T> +void foo(T x) { + sizeof []<int=0>(T=x) { return 0; }(); // { dg-error "may not appear" } + sizeof [](T=x) { return 0; }(); // { dg-error "may not appear" } +}; + +void test() { + foo(0); +} -- 2.43.0