[pushed,2/4] c++: constant direct-initialization [PR108243]
Checks
Commit Message
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(-)
@@ -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);
@@ -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
@@ -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" } }