Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/14? -- >8 -- We've had a wrong-code problem since r14-4140, due to which we forget to initialize a variable.
In consteval39.C, we evaluate struct QQQ q; <<cleanup_point <<< Unknown tree: expr_stmt QQQ::QQQ (&q, TARGET_EXPR <D.2687, <<< Unknown tree: aggr_init_expr 5 __ct_comp D.2687 (struct basic_string_view *) <<< Unknown tree: void_cst >>> (const char *) "" >>>>) >>>>>; into struct QQQ q; <<cleanup_point <<< Unknown tree: expr_stmt {.data={._M_len=42, ._M_str=0}} >>>>>; and then the useless expr_stmt is dropped on the floor, so q isn't initialized. As pre-r14-4140, we need to handle constructors specially. With this patch, we generate: struct QQQ q; <<cleanup_point <<< Unknown tree: expr_stmt q = {.data={._M_len=42, ._M_str=0}} >>>>>; initializing q properly. PR c++/117501 gcc/cp/ChangeLog: * cp-gimplify.cc (cp_fold_immediate_r): If DECL is a constructor, build up an INIT_EXPR to initialize its object. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/consteval39.C: New test. * g++.dg/cpp2a/consteval40.C: New test. --- gcc/cp/cp-gimplify.cc | 13 ++++++++++-- gcc/testsuite/g++.dg/cpp2a/consteval39.C | 27 ++++++++++++++++++++++++ gcc/testsuite/g++.dg/cpp2a/consteval40.C | 25 ++++++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/consteval39.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/consteval40.C diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc index 4ec3de13008..65b486ab943 100644 --- a/gcc/cp/cp-gimplify.cc +++ b/gcc/cp/cp-gimplify.cc @@ -1259,7 +1259,16 @@ cp_fold_immediate_r (tree *stmt_p, int *walk_subtrees, void *data_) not need to produce a constant expression. */ if (DECL_IMMEDIATE_FUNCTION_P (decl)) { - tree e = cxx_constant_value (stmt, tf_none); + tree obj_arg = NULL_TREE; + if (call_p && DECL_CONSTRUCTOR_P (decl)) + if (tree o = get_nth_callarg (stmt, 0)) + if (!is_dummy_object (o)) + { + obj_arg = o; + if (TREE_CODE (obj_arg) == ADDR_EXPR) + obj_arg = TREE_OPERAND (obj_arg, 0); + } + tree e = cxx_constant_value (stmt, obj_arg, tf_none); if (e == error_mark_node) { /* This takes care of, e.g., @@ -1297,7 +1306,7 @@ cp_fold_immediate_r (tree *stmt_p, int *walk_subtrees, void *data_) } /* We've evaluated the consteval function call. */ if (call_p) - *stmt_p = e; + *stmt_p = obj_arg ? cp_build_init_expr (obj_arg, e) : e; } /* We've encountered a function call that may turn out to be consteval later. Store its caller so that we can ensure that the call is diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval39.C b/gcc/testsuite/g++.dg/cpp2a/consteval39.C new file mode 100644 index 00000000000..523e8260eab --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/consteval39.C @@ -0,0 +1,27 @@ +// PR c++/117501 +// { dg-do run { target c++20 } } + +constexpr unsigned +length () +{ + bool __trans_tmp_1 = __builtin_is_constant_evaluated(); + if (__trans_tmp_1) + return 42; + return 1; +} +struct basic_string_view { + constexpr basic_string_view(const char *) : _M_len{length()}, _M_str{} {} + long _M_len; + char _M_str; +}; +struct QQQ { + consteval QQQ(basic_string_view d) : data(d) {} + basic_string_view data; +}; +int +main () +{ + QQQ q(""); + if (q.data._M_len != 42) + __builtin_abort (); +} diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval40.C b/gcc/testsuite/g++.dg/cpp2a/consteval40.C new file mode 100644 index 00000000000..4d3ba20092b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/consteval40.C @@ -0,0 +1,25 @@ +// PR c++/117501 +// { dg-do run { target c++20 } } + +constexpr int +twiddle (int i) +{ + if (__builtin_is_constant_evaluated ()) + return 3; + return i; +} +struct S { + constexpr S(int i) : i{twiddle (i)} {} + int i; +}; +struct Q { + consteval Q(S s_) : s{s_, s_} {} + S s[2]; +}; +int +main () +{ + Q q(twiddle (42)); + if (q.s[0].i != 3 || q.s[1].i != 3) + __builtin_abort (); +} base-commit: ceabea405ffdc851736e240111be9b297ad86c53 -- 2.48.1