https://gcc.gnu.org/g:525d4a10302113b3cce9b4e5420767f0a2f5624e

commit r15-8900-g525d4a10302113b3cce9b4e5420767f0a2f5624e
Author: yxj-github-437 <2457369...@qq.com>
Date:   Tue Mar 25 23:43:10 2025 +0800

    c++: lambda, default argument, unevaluated context
    
    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:
    
        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 to
    
    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.
    
    Reviewed-by: Jason Merrill <ja...@redhat.com>

Diff:
---
 gcc/cp/parser.cc                             |  3 +++
 gcc/testsuite/g++.dg/cpp2a/lambda-uneval25.C | 11 +++++++++++
 2 files changed, 14 insertions(+)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 57a461042bf1..88e722d8406d 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 000000000000..7fdd44d3ddd3
--- /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);
+}

Reply via email to