diff options
author | yxj-github-437 <2457369732@qq.com> | 2025-03-25 23:43:10 +0800 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2025-03-25 13:09:43 -0400 |
commit | 525d4a10302113b3cce9b4e5420767f0a2f5624e (patch) | |
tree | 7e4547eb22886258588c4d8015cb06f33123b868 | |
parent | ca0a8421f7aa2191b2b867ff24888223d6cde433 (diff) | |
download | gcc-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.cc | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/lambda-uneval25.C | 11 |
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); +} |