[PATCH 3/2] c++: INIT_EXPR trial constexpr folding

Patrick Palka <[email protected]> Thu, 6 Aug 2026 17:11:09 -0400
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK
for trunk only?

-- >8 --

This patch adds trial constexpr folding of INIT_EXPR that mirrors the
existing TARGET_EXPR folding added by r15-6052.  Since local copy-init
is represented as INIT_EXPR, this addresses the xfails in
is_constant_evaluated3{a,b}.C.

gcc/cp/ChangeLog:

	* cp-gimplify.cc (cp_fold_r) <case INIT_EXPR>: Add trial
	maybe_constant_init logic like for TARGET_EXPR.

gcc/testsuite/ChangeLog:

	* g++.dg/opt/is_constant_evaluated3a.C: Remove xfail.
	* g++.dg/opt/is_constant_evaluated3b.C: Likewise.
---
 gcc/cp/cp-gimplify.cc                             | 15 ++++++++++++++-
 .../g++.dg/opt/is_constant_evaluated3a.C          |  2 +-
 .../g++.dg/opt/is_constant_evaluated3b.C          |  2 +-
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index 23a1b7ea2ccd..927062f0121c 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -1736,7 +1736,20 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data_)
 	 reference transition.  */
     case INIT_EXPR:
       if (data->flags & ff_genericize)
-	cp_genericize_init_expr (stmt_p);
+	{
+	  if (!flag_no_inline)
+	    {
+	      tree to = TREE_OPERAND (*stmt_p, 0);
+	      tree &from = TREE_OPERAND (*stmt_p, 1);
+	      tree folded = maybe_constant_init (from, to,
+						 (data->flags & ff_mce_false
+						  ? mce_false : mce_unknown));
+	      if (folded != from && TREE_CONSTANT (folded))
+		from = folded;
+	    }
+
+	  cp_genericize_init_expr (stmt_p);
+	}
       break;
 
     case TARGET_EXPR:
diff --git a/gcc/testsuite/g++.dg/opt/is_constant_evaluated3a.C b/gcc/testsuite/g++.dg/opt/is_constant_evaluated3a.C
index 4ec3ecdf7b5d..e5c8b7f57895 100644
--- a/gcc/testsuite/g++.dg/opt/is_constant_evaluated3a.C
+++ b/gcc/testsuite/g++.dg/opt/is_constant_evaluated3a.C
@@ -17,7 +17,7 @@ constexpr void f() {
   A a5{};
 }
 
-// { dg-final { scan-tree-dump "a1 = {\\.n=42, \\.m=0}" "original" { xfail *-*-* } } }
+// { dg-final { scan-tree-dump "a1 = {\\.n=42, \\.m=0}" "original" } }
 // { dg-final { scan-tree-dump "a2 = {\\.n=42, \\.m=0}" "original" } }
 // { dg-final { scan-tree-dump "a3 = {\\.n=42, \\.m=0}" "original" } }
 // { dg-final { scan-tree-dump "a4 = {\\.n=42, \\.m=0}" "original" } }
diff --git a/gcc/testsuite/g++.dg/opt/is_constant_evaluated3b.C b/gcc/testsuite/g++.dg/opt/is_constant_evaluated3b.C
index ac6d21d632e1..ff708e23832b 100644
--- a/gcc/testsuite/g++.dg/opt/is_constant_evaluated3b.C
+++ b/gcc/testsuite/g++.dg/opt/is_constant_evaluated3b.C
@@ -17,7 +17,7 @@ auto f = [] {
   A a5{};
 };
 
-// { dg-final { scan-tree-dump "a1 = {\\.n=42, \\.m=0}" "original" { xfail *-*-* } } }
+// { dg-final { scan-tree-dump "a1 = {\\.n=42, \\.m=0}" "original" } }
 // { dg-final { scan-tree-dump "a2 = {\\.n=42, \\.m=0}" "original" } }
 // { dg-final { scan-tree-dump "a3 = {\\.n=42, \\.m=0}" "original" } }
 // { dg-final { scan-tree-dump "a4 = {\\.n=42, \\.m=0}" "original" } }
-- 
2.55.0.481.ga97fcc37c2