diff mbox series

c++: checking ICE w/ lambda targ inside constexpr if [PR117054]

Message ID 20241015044821.1488337-1-ppalka@redhat.com
State New
Headers show
Series c++: checking ICE w/ lambda targ inside constexpr if [PR117054] | expand

Commit Message

Patrick Palka Oct. 15, 2024, 4:48 a.m. UTC
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK
for trunk?

-- >8 --

Here we're tripping over the assert in extract_locals_r which enforces
that an extra-args tree appearing inside another extra-args tree doesn't
actually have extra args.  This invariant no longer always holds for
lambdas (which recently gained the extra-args mechanism), but it should
be safe to just disable the assert for them since cp_walk_subtrees doesn't
walk LAMBDA_EXPR_EXTRA_ARGS and so should be immune to the PR114303 issue
for now.

	PR c++/117054

gcc/cp/ChangeLog:

	* pt.cc (extract_locals_r): Disable tree_extra_args assert
	for LAMBDA_EXPR.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp2a/lambda-targ9.C: New test.
---
 gcc/cp/pt.cc                              |  7 ++++++-
 gcc/testsuite/g++.dg/cpp2a/lambda-targ9.C | 16 ++++++++++++++++
 2 files changed, 22 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-targ9.C

Comments

Jason Merrill Oct. 15, 2024, 1:20 p.m. UTC | #1
On 10/15/24 12:48 AM, Patrick Palka wrote:
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK
> for trunk?

OK.

> -- >8 --
> 
> Here we're tripping over the assert in extract_locals_r which enforces
> that an extra-args tree appearing inside another extra-args tree doesn't
> actually have extra args.  This invariant no longer always holds for
> lambdas (which recently gained the extra-args mechanism), but it should
> be safe to just disable the assert for them since cp_walk_subtrees doesn't
> walk LAMBDA_EXPR_EXTRA_ARGS and so should be immune to the PR114303 issue
> for now.
> 
> 	PR c++/117054
> 
> gcc/cp/ChangeLog:
> 
> 	* pt.cc (extract_locals_r): Disable tree_extra_args assert
> 	for LAMBDA_EXPR.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/cpp2a/lambda-targ9.C: New test.
> ---
>   gcc/cp/pt.cc                              |  7 ++++++-
>   gcc/testsuite/g++.dg/cpp2a/lambda-targ9.C | 16 ++++++++++++++++
>   2 files changed, 22 insertions(+), 1 deletion(-)
>   create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-targ9.C
> 
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index c7cbf6df26c..b90447ae6a2 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -13479,7 +13479,12 @@ extract_locals_r (tree *tp, int *walk_subtrees, void *data_)
>          outermost tree.  Nested *_EXTRA_ARGS should naturally be empty since
>          the outermost (extra-args) tree will intercept any substitution before
>          a nested tree can.  */
> -    gcc_checking_assert (tree_extra_args (*tp) == NULL_TREE);
> +    gcc_checking_assert (tree_extra_args (*tp) == NULL_TREE
> +			/* Except a lambda nested inside an extra-args tree
> +			   can have extra args if we deferred partial
> +			   substitution into it at template parse time.  But
> +			   we don't walk LAMBDA_EXPR_EXTRA_ARGS anyway.  */
> +			 || TREE_CODE (*tp) == LAMBDA_EXPR);
>   
>     if (TREE_CODE (*tp) == DECL_EXPR)
>       {
> diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ9.C b/gcc/testsuite/g++.dg/cpp2a/lambda-targ9.C
> new file mode 100644
> index 00000000000..00dd4b2406e
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ9.C
> @@ -0,0 +1,16 @@
> +// PR c++/117054
> +// { dg-do compile { target c++20 } }
> +
> +template<auto = [] {}>
> +constexpr bool a = true;
> +
> +template<typename>
> +void f() {
> +  [](auto) {
> +    if constexpr (a<>) {}
> +  };
> +}
> +
> +int main() {
> +  f<int>();
> +}
diff mbox series

Patch

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index c7cbf6df26c..b90447ae6a2 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -13479,7 +13479,12 @@  extract_locals_r (tree *tp, int *walk_subtrees, void *data_)
        outermost tree.  Nested *_EXTRA_ARGS should naturally be empty since
        the outermost (extra-args) tree will intercept any substitution before
        a nested tree can.  */
-    gcc_checking_assert (tree_extra_args (*tp) == NULL_TREE);
+    gcc_checking_assert (tree_extra_args (*tp) == NULL_TREE
+			/* Except a lambda nested inside an extra-args tree
+			   can have extra args if we deferred partial
+			   substitution into it at template parse time.  But
+			   we don't walk LAMBDA_EXPR_EXTRA_ARGS anyway.  */
+			 || TREE_CODE (*tp) == LAMBDA_EXPR);
 
   if (TREE_CODE (*tp) == DECL_EXPR)
     {
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ9.C b/gcc/testsuite/g++.dg/cpp2a/lambda-targ9.C
new file mode 100644
index 00000000000..00dd4b2406e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ9.C
@@ -0,0 +1,16 @@ 
+// PR c++/117054
+// { dg-do compile { target c++20 } }
+
+template<auto = [] {}>
+constexpr bool a = true;
+
+template<typename>
+void f() {
+  [](auto) {
+    if constexpr (a<>) {}
+  };
+}
+
+int main() {
+  f<int>();
+}