[pushed,2/4] c++: constant direct-initialization [PR108243]

Message ID 20231213164740.1591535-2-jason@redhat.com
State Committed
Commit 958940eb3511e341e57606f5a2f5399bc89533cb
Headers
Series [pushed,1/4] c++: copy location to AGGR_INIT_EXPR |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm warning Patch is already merged
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 warning Patch is already merged

Commit Message

Jason Merrill Dec. 13, 2023, 4:47 p.m. UTC
  Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

When testing the proposed patch for PR71093 I noticed that it changed the
diagnostic for consteval-prop6.C.  I then noticed that the diagnostic wasn't
very helpful either way; it was complaining about modification of the 'x'
variable, but it's not a problem to initialize a local variable with a
consteval constructor as long as the value is actually constant, we want to
know why the value isn't constant.  And then it turned out that this also
fixed a missed-optimization bug in the testsuite.

	PR c++/108243

gcc/cp/ChangeLog:

	* constexpr.cc (cxx_eval_outermost_constant_expr): Turn
	a constructor CALL_EXPR into a TARGET_EXPR.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp2a/consteval-prop6.C: Adjust diagnostic.
	* g++.dg/opt/is_constant_evaluated3.C: Remove xfails.
---
 gcc/cp/constexpr.cc                              | 16 +++++++++++++++-
 gcc/testsuite/g++.dg/cpp2a/consteval-prop6.C     |  2 +-
 .../g++.dg/opt/is_constant_evaluated3.C          |  8 ++++----
 3 files changed, 20 insertions(+), 6 deletions(-)
  

Patch

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 58187a4fd12..4cf9dd71b05 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -8651,7 +8651,21 @@  cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
 	}
       if (!object)
 	{
-	  if (TREE_CODE (t) == TARGET_EXPR)
+	  if (TREE_CODE (t) == CALL_EXPR)
+	    {
+	      /* If T is calling a constructor to initialize an object, reframe
+		 it as an AGGR_INIT_EXPR to avoid trying to modify an object
+		 from outside the constant evaluation, which will fail even if
+		 the value is actually constant (is_constant_evaluated3.C).  */
+	      tree fn = cp_get_callee_fndecl_nofold (t);
+	      if (fn && DECL_CONSTRUCTOR_P (fn))
+		{
+		  object = CALL_EXPR_ARG (t, 0);
+		  object = build_fold_indirect_ref (object);
+		  r = build_aggr_init_expr (type, r);
+		}
+	    }
+	  else if (TREE_CODE (t) == TARGET_EXPR)
 	    object = TARGET_EXPR_SLOT (t);
 	  else if (TREE_CODE (t) == AGGR_INIT_EXPR)
 	    object = AGGR_INIT_EXPR_SLOT (t);
diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval-prop6.C b/gcc/testsuite/g++.dg/cpp2a/consteval-prop6.C
index 93ed398d9bf..ca7db7c63d3 100644
--- a/gcc/testsuite/g++.dg/cpp2a/consteval-prop6.C
+++ b/gcc/testsuite/g++.dg/cpp2a/consteval-prop6.C
@@ -48,7 +48,7 @@  struct X {
   int a = sizeof(undef(0));
   int x = undef(0);
 
-  X() = default; // { dg-error "modification of .x. is not a constant expression" }
+  X() = default; // { dg-error {'consteval int undef\(int\)' used before its definition} }
 };
 
 void
diff --git a/gcc/testsuite/g++.dg/opt/is_constant_evaluated3.C b/gcc/testsuite/g++.dg/opt/is_constant_evaluated3.C
index 0a1e46e5638..783127cf909 100644
--- a/gcc/testsuite/g++.dg/opt/is_constant_evaluated3.C
+++ b/gcc/testsuite/g++.dg/opt/is_constant_evaluated3.C
@@ -17,7 +17,7 @@  int main() {
 }
 
 // { dg-final { scan-tree-dump "a1 = {\\.n=42, \\.m=0}" "original" } }
-// { dg-final { scan-tree-dump "a2 = {\\.n=42, \\.m=0}" "original" { xfail *-*-* } } }
-// { dg-final { scan-tree-dump "a3 = {\\.n=42, \\.m=0}" "original" { xfail *-*-* } } }
-// { dg-final { scan-tree-dump "a4 = {\\.n=42, \\.m=0}" "original" { xfail *-*-* } } }
-// { dg-final { scan-tree-dump "a5 = {\\.n=42, \\.m=0}" "original" { xfail *-*-* } } }
+// { 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" } }
+// { dg-final { scan-tree-dump "a5 = {\\.n=42, \\.m=0}" "original" } }