>> 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

Reply via email to