aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2023-12-12 22:53:10 -0500
committerJason Merrill <jason@redhat.com>2023-12-13 11:25:19 -0500
commit958940eb3511e341e57606f5a2f5399bc89533cb (patch)
treed831802c51130510adbc9d27d31787f7be55c02a /gcc
parent52b4b7d7f5c7c09f5aaf3934978de9702d8c214b (diff)
downloadgcc-958940eb3511e341e57606f5a2f5399bc89533cb.zip
gcc-958940eb3511e341e57606f5a2f5399bc89533cb.tar.gz
gcc-958940eb3511e341e57606f5a2f5399bc89533cb.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/constexpr.cc16
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/consteval-prop6.C2
-rw-r--r--gcc/testsuite/g++.dg/opt/is_constant_evaluated3.C8
3 files changed, 20 insertions, 6 deletions
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 58187a4..4cf9dd7 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 93ed398..ca7db7c 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 0a1e46e..783127c 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" } }