aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryxj-github-437 <2457369732@qq.com>2025-03-25 23:43:10 +0800
committerJason Merrill <jason@redhat.com>2025-03-25 13:09:43 -0400
commit525d4a10302113b3cce9b4e5420767f0a2f5624e (patch)
tree7e4547eb22886258588c4d8015cb06f33123b868
parentca0a8421f7aa2191b2b867ff24888223d6cde433 (diff)
downloadgcc-525d4a10302113b3cce9b4e5420767f0a2f5624e.zip
gcc-525d4a10302113b3cce9b4e5420767f0a2f5624e.tar.gz
gcc-525d4a10302113b3cce9b4e5420767f0a2f5624e.tar.bz2
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 <jason@redhat.com>
-rw-r--r--gcc/cp/parser.cc3
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/lambda-uneval25.C11
2 files changed, 14 insertions, 0 deletions
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 57a4610..88e722d 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 0000000..7fdd44d
--- /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);
+}