c++: ICE with MODIFY_EXPR in constexpr [PR118169]

Message ID 20250107155835.27484-1-polacek@redhat.com
State New
Headers
Series c++: ICE with MODIFY_EXPR in constexpr [PR118169] |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed

Commit Message

Marek Polacek Jan. 7, 2025, 3:58 p.m. UTC
  Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
Here, cxx_eval_outermost_expression gets a sequence of initialization
statements:

  D.2912.t = TARGET_EXPR <...>;
  TARGET_EXPR <D.2922, 1>;
  D.2922 = 0;

the last of which wasn't converted to void and so we, since r15-6369,
do not take the "if (VOID_TYPE_P (type))" path, and try to set
D.2912 to false.

The last statement comes from build_disable_temp_cleanup.
convert_to_void is typically called from finish_expr_stmt, but we are
adding the cleanup statement via add_stmt which doesn't convert to void.
So I think we can use finish_expr_stmt instead.

	PR c++/118169

gcc/cp/ChangeLog:

	* typeck2.cc (split_nonconstant_init): Call finish_expr_stmt instead
	of add_stmt.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp1y/constexpr-prvalue2.C: New test.
---
 gcc/cp/typeck2.cc                               |  2 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-prvalue2.C | 13 +++++++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-prvalue2.C


base-commit: d3ccd89fa0d34d44226af47fe82c27ba7833fe65
  

Comments

Jason Merrill Jan. 8, 2025, 12:29 a.m. UTC | #1
On 1/7/25 10:58 AM, Marek Polacek wrote:
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

OK.

> -- >8 --
> Here, cxx_eval_outermost_expression gets a sequence of initialization
> statements:
> 
>    D.2912.t = TARGET_EXPR <...>;
>    TARGET_EXPR <D.2922, 1>;
>    D.2922 = 0;
> 
> the last of which wasn't converted to void and so we, since r15-6369,
> do not take the "if (VOID_TYPE_P (type))" path, and try to set
> D.2912 to false.
> 
> The last statement comes from build_disable_temp_cleanup.
> convert_to_void is typically called from finish_expr_stmt, but we are
> adding the cleanup statement via add_stmt which doesn't convert to void.
> So I think we can use finish_expr_stmt instead.
> 
> 	PR c++/118169
> 
> gcc/cp/ChangeLog:
> 
> 	* typeck2.cc (split_nonconstant_init): Call finish_expr_stmt instead
> 	of add_stmt.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/cpp1y/constexpr-prvalue2.C: New test.
> ---
>   gcc/cp/typeck2.cc                               |  2 +-
>   gcc/testsuite/g++.dg/cpp1y/constexpr-prvalue2.C | 13 +++++++++++++
>   2 files changed, 14 insertions(+), 1 deletion(-)
>   create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-prvalue2.C
> 
> diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
> index 381f198d0fe..5dae7fccf19 100644
> --- a/gcc/cp/typeck2.cc
> +++ b/gcc/cp/typeck2.cc
> @@ -757,7 +757,7 @@ split_nonconstant_init (tree dest, tree init)
>   	init = NULL_TREE;
>   
>         for (tree f : flags)
> -	add_stmt (build_disable_temp_cleanup (f));
> +	finish_expr_stmt (build_disable_temp_cleanup (f));
>         release_tree_vector (flags);
>   
>         code = pop_stmt_list (code);
> diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-prvalue2.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-prvalue2.C
> new file mode 100644
> index 00000000000..7076c65b96a
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-prvalue2.C
> @@ -0,0 +1,13 @@
> +// PR c++/118169
> +// { dg-do compile { target c++14 } }
> +// { dg-options "-O" }
> +
> +struct A { constexpr A (int *x) : s(x) {} ~A (); int *s; };
> +struct B { A t; int u = 0; };
> +void foo (B &&);
> +
> +void
> +bar (int &x)
> +{
> +  foo ({ &x });
> +}
> 
> base-commit: d3ccd89fa0d34d44226af47fe82c27ba7833fe65
  

Patch

diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index 381f198d0fe..5dae7fccf19 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -757,7 +757,7 @@  split_nonconstant_init (tree dest, tree init)
 	init = NULL_TREE;
 
       for (tree f : flags)
-	add_stmt (build_disable_temp_cleanup (f));
+	finish_expr_stmt (build_disable_temp_cleanup (f));
       release_tree_vector (flags);
 
       code = pop_stmt_list (code);
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-prvalue2.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-prvalue2.C
new file mode 100644
index 00000000000..7076c65b96a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-prvalue2.C
@@ -0,0 +1,13 @@ 
+// PR c++/118169
+// { dg-do compile { target c++14 } }
+// { dg-options "-O" }
+
+struct A { constexpr A (int *x) : s(x) {} ~A (); int *s; };
+struct B { A t; int u = 0; };
+void foo (B &&);
+
+void
+bar (int &x)
+{
+  foo ({ &x });
+}