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

Reply via email to