This patch would like to avoid the ICE when template lambdas call with
default parameters in unevaluated context. 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; }();
      |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~

For this example, the template lambda will build with an independent unevaluated
context. When convert default arguments, handling `int x` will be in a no 
unevaluated
operand context, the code `gcc_assert (cp_unevaluated_operand)` will make ICE.
So just remove this assert, and the code will get an effective error 
information:
"‘x’ is not captured".

gcc/cp/ChangeLog:

        * pt.cc (tsubst_expr): remove cp_unevaluated_operand assert
---
 gcc/cp/pt.cc                                 |  2 +-
 gcc/testsuite/g++.dg/cpp2a/lambda-uneval25.C | 10 ++++++++++
 2 files changed, 11 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-uneval25.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 538ff220d74..abbf2997a25 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -21916,7 +21916,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
              /* This can happen for a parameter name used later in a function
                 declaration (such as in a late-specified return type).  Just
                 make a dummy decl, since it's only used for its type.  */
-             gcc_assert (cp_unevaluated_operand);
+             // gcc_assert (cp_unevaluated_operand);
              r = tsubst_decl (t, args, complain);
              /* Give it the template pattern as its context; its true context
                 hasn't been instantiated yet and this is good enough for
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..a73a1c55a7e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval25.C
@@ -0,0 +1,10 @@
+// { dg-do compile { target c++20 } }
+
+template <class T>
+void foo(T x) {
+  sizeof []<int=0>(T=x) { return 0; }(); // { dg-error "'x' is not captured" }
+};
+
+void test() {
+  foo(0);
+}
-- 
2.43.0

Reply via email to