From 958940eb3511e341e57606f5a2f5399bc89533cb Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 12 Dec 2023 22:53:10 -0500 Subject: [PATCH] c++: constant direct-initialization [PR108243] 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 +- gcc/testsuite/g++.dg/opt/is_constant_evaluated3.C | 8 ++++---- 3 files changed, 20 insertions(+), 6 deletions(-) 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" } } -- 2.11.4.GIT