Hi,

This patch is the gcc-9 backport of mainline r11-154 / gcc-10 r10-8149.

Bootstrapped and regression tested on x86_64-linux-gnu, and committed to
the gcc-9 branch.

Regards
Iain

---
gcc/d/ChangeLog:

        PR d/94970
        * d-codegen.cc (force_target_expr): Move create_temporary_var
        implementation inline here.
        (create_temporary_var): Remove.
        (maybe_temporary_var): Remove.
        (bind_expr): Remove.
        * d-convert.cc (d_array_convert): Use build_local_temp to generate
        temporaries, and generate its assignment.
        * d-tree.h (create_temporary_var): Remove.
        (maybe_temporary_var): Remove.
        (d_array_convert): Remove vars argument.
        * expr.cc (ExprVisitor::visit (CatExp *)): Use build_local_temp to
        generate temporaries, don't wrap them in a BIND_EXPR.
        (ExprVisitor::visit (NewExp *)): Likewise.

gcc/testsuite/ChangeLog:

        PR d/94970
        * gdc.dg/pr94970.d: New test.
---
 gcc/d/ChangeLog                | 20 ++++++++++
 gcc/d/d-codegen.cc             | 67 +++-------------------------------
 gcc/d/d-convert.cc             | 14 ++++---
 gcc/d/d-tree.h                 |  4 +-
 gcc/d/expr.cc                  | 33 +++++++----------
 gcc/testsuite/ChangeLog        |  8 ++++
 gcc/testsuite/gdc.dg/pr94970.d | 20 ++++++++++
 7 files changed, 77 insertions(+), 89 deletions(-)
 create mode 100644 gcc/testsuite/gdc.dg/pr94970.d

diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog
index c3f56590298..5048d2ab400 100644
--- a/gcc/d/ChangeLog
+++ b/gcc/d/ChangeLog
@@ -1,3 +1,23 @@
+2020-05-17  Iain Buclaw  <ibuc...@gdcproject.org>
+
+       Backport from mainline
+       2020-05-06  Iain Buclaw  <ibuc...@gdcproject.org>
+
+       PR d/94970
+       * d-codegen.cc (force_target_expr): Move create_temporary_var
+       implementation inline here.
+       (create_temporary_var): Remove.
+       (maybe_temporary_var): Remove.
+       (bind_expr): Remove.
+       * d-convert.cc (d_array_convert): Use build_local_temp to generate
+       temporaries, and generate its assignment.
+       * d-tree.h (create_temporary_var): Remove.
+       (maybe_temporary_var): Remove.
+       (d_array_convert): Remove vars argument.
+       * expr.cc (ExprVisitor::visit (CatExp *)): Use build_local_temp to
+       generate temporaries, don't wrap them in a BIND_EXPR.
+       (ExprVisitor::visit (NewExp *)): Likewise.
+
 2020-05-16  Iain Buclaw  <ibuc...@gdcproject.org>
 
        PR d/95155
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 2abff92fc88..17f624b5a4f 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -612,7 +612,12 @@ build_target_expr (tree decl, tree exp)
 tree
 force_target_expr (tree exp)
 {
-  tree decl = create_temporary_var (TREE_TYPE (exp));
+  tree decl = build_decl (input_location, VAR_DECL, NULL_TREE,
+                         TREE_TYPE (exp));
+  DECL_CONTEXT (decl) = current_function_decl;
+  DECL_ARTIFICIAL (decl) = 1;
+  DECL_IGNORED_P (decl) = 1;
+  layout_decl (decl, 0);
 
   return build_target_expr (decl, exp);
 }
@@ -1801,66 +1806,6 @@ array_bounds_check (void)
     }
 }
 
-/* Return an undeclared local temporary of type TYPE
-   for use with BIND_EXPR.  */
-
-tree
-create_temporary_var (tree type)
-{
-  tree decl = build_decl (input_location, VAR_DECL, NULL_TREE, type);
-
-  DECL_CONTEXT (decl) = current_function_decl;
-  DECL_ARTIFICIAL (decl) = 1;
-  DECL_IGNORED_P (decl) = 1;
-  layout_decl (decl, 0);
-
-  return decl;
-}
-
-/* Return an undeclared local temporary OUT_VAR initialized
-   with result of expression EXP.  */
-
-tree
-maybe_temporary_var (tree exp, tree *out_var)
-{
-  tree t = exp;
-
-  /* Get the base component.  */
-  while (TREE_CODE (t) == COMPONENT_REF)
-    t = TREE_OPERAND (t, 0);
-
-  if (!DECL_P (t) && !REFERENCE_CLASS_P (t))
-    {
-      *out_var = create_temporary_var (TREE_TYPE (exp));
-      DECL_INITIAL (*out_var) = exp;
-      return *out_var;
-    }
-  else
-    {
-      *out_var = NULL_TREE;
-      return exp;
-    }
-}
-
-/* Builds a BIND_EXPR around BODY for the variables VAR_CHAIN.  */
-
-tree
-bind_expr (tree var_chain, tree body)
-{
-  /* Only handles one var.  */
-  gcc_assert (TREE_CHAIN (var_chain) == NULL_TREE);
-
-  if (DECL_INITIAL (var_chain))
-    {
-      tree ini = build_assign (INIT_EXPR, var_chain, DECL_INITIAL (var_chain));
-      DECL_INITIAL (var_chain) = NULL_TREE;
-      body = compound_expr (ini, body);
-    }
-
-  return d_save_expr (build3 (BIND_EXPR, TREE_TYPE (body),
-                             var_chain, body, NULL_TREE));
-}
-
 /* Returns the TypeFunction class for Type T.
    Assumes T is already ->toBasetype().  */
 
diff --git a/gcc/d/d-convert.cc b/gcc/d/d-convert.cc
index e9aa457d852..761ab3c5435 100644
--- a/gcc/d/d-convert.cc
+++ b/gcc/d/d-convert.cc
@@ -775,21 +775,23 @@ d_array_convert (Expression *exp)
 
 /* Convert EXP to a dynamic array, where ETYPE is the element type.
    Similar to above, except that EXP is allowed to be an element of an array.
-   Temporary variables that need some kind of BIND_EXPR are pushed to VARS.  */
+   Temporary variables are created inline if EXP is not an lvalue.  */
 
 tree
-d_array_convert (Type *etype, Expression *exp, vec<tree, va_gc> **vars)
+d_array_convert (Type *etype, Expression *exp)
 {
   Type *tb = exp->type->toBasetype ();
 
   if ((tb->ty != Tarray && tb->ty != Tsarray) || same_type_p (tb, etype))
     {
       /* Convert single element to an array.  */
-      tree var = NULL_TREE;
-      tree expr = maybe_temporary_var (build_expr (exp), &var);
+      tree expr = build_expr (exp);
 
-      if (var != NULL_TREE)
-       vec_safe_push (*vars, var);
+      if (!exp->isLvalue ())
+       {
+         tree var = build_local_temp (TREE_TYPE (expr));
+         expr = compound_expr (modify_expr (var, expr), var);
+       }
 
       return d_array_value (build_ctype (exp->type->arrayOf ()),
                            size_int (1), build_address (expr));
diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h
index a514bc3902f..7a54dfbc59e 100644
--- a/gcc/d/d-tree.h
+++ b/gcc/d/d-tree.h
@@ -558,8 +558,6 @@ extern tree build_array_from_val (Type *, tree);
 extern tree void_okay_p (tree);
 extern tree build_bounds_condition (const Loc &, tree, tree, bool);
 extern bool array_bounds_check (void);
-extern tree create_temporary_var (tree);
-extern tree maybe_temporary_var (tree, tree *);
 extern tree bind_expr (tree, tree);
 extern TypeFunction *get_function_type (Type *);
 extern bool call_by_alias_p (FuncDeclaration *, FuncDeclaration *);
@@ -583,7 +581,7 @@ extern tree convert_for_assignment (tree, Type *, Type *);
 extern tree convert_for_argument (tree, Parameter *);
 extern tree convert_for_condition (tree, Type *);
 extern tree d_array_convert (Expression *);
-extern tree d_array_convert (Type *, Expression *, vec<tree, va_gc> **);
+extern tree d_array_convert (Type *, Expression *);
 
 /* In d-incpath.cc.  */
 extern void add_import_paths (const char *, const char *, bool);
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 6497619e5fd..3a2823d6e46 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -691,7 +691,6 @@ public:
     else
       etype = tb2->nextOf ();
 
-    vec<tree, va_gc> *elemvars = NULL;
     tree result;
 
     if (e->e1->op == TOKcat)
@@ -711,9 +710,7 @@ public:
 
        /* Store all concatenation args to a temporary byte[][ndims] array.  */
        Type *targselem = Type::tint8->arrayOf ();
-       tree var = create_temporary_var (make_array_type (targselem, ndims));
-       tree init = build_constructor (TREE_TYPE (var), NULL);
-       vec_safe_push (elemvars, var);
+       tree var = build_local_temp (make_array_type (targselem, ndims));
 
        /* Loop through each concatenation from right to left.  */
        vec<constructor_elt, va_gc> *elms = NULL;
@@ -725,7 +722,7 @@ public:
              ? (oe = ce->e1)
              : (ce = (CatExp *)ce->e1, oe = ce->e2)))
          {
-           tree arg = d_array_convert (etype, oe, &elemvars);
+           tree arg = d_array_convert (etype, oe);
            tree index = size_int (dim);
            CONSTRUCTOR_APPEND_ELT (elms, index, d_save_expr (arg));
 
@@ -738,8 +735,8 @@ public:
 
        /* Check there is no logic bug in constructing byte[][] of arrays.  */
        gcc_assert (dim == 0);
-       CONSTRUCTOR_ELTS (init) = elms;
-       DECL_INITIAL (var) = init;
+       tree init = build_constructor (TREE_TYPE (var), elms);
+       var = compound_expr (modify_expr (var, init), var);
 
        tree arrs = d_array_value (build_ctype (targselem->arrayOf ()),
                                   size_int (ndims), build_address (var));
@@ -752,13 +749,10 @@ public:
        /* Handle single concatenation (a ~ b).  */
        result = build_libcall (LIBCALL_ARRAYCATT, e->type, 3,
                                build_typeinfo (e->loc, e->type),
-                               d_array_convert (etype, e->e1, &elemvars),
-                               d_array_convert (etype, e->e2, &elemvars));
+                               d_array_convert (etype, e->e1),
+                               d_array_convert (etype, e->e2));
       }
 
-    for (size_t i = 0; i < vec_safe_length (elemvars); ++i)
-      result = bind_expr ((*elemvars)[i], result);
-
     this->result_ = result;
   }
 
@@ -2480,12 +2474,13 @@ public:
        else
          {
            /* Multidimensional array allocations.  */
-           vec<constructor_elt, va_gc> *elms = NULL;
-           Type *telem = e->newtype->toBasetype ();
            tree tarray = make_array_type (Type::tsize_t, e->arguments->dim);
-           tree var = create_temporary_var (tarray);
-           tree init = build_constructor (TREE_TYPE (var), NULL);
+           tree var = build_local_temp (tarray);
+           vec<constructor_elt, va_gc> *elms = NULL;
 
+           /* Get the base element type for the array, generating the
+              initializer for the dims parameter along the way.  */
+           Type *telem = e->newtype->toBasetype ();
            for (size_t i = 0; i < e->arguments->dim; i++)
              {
                Expression *arg = (*e->arguments)[i];
@@ -2496,8 +2491,9 @@ public:
                gcc_assert (telem);
              }
 
-           CONSTRUCTOR_ELTS (init) = elms;
-           DECL_INITIAL (var) = init;
+           /* Initialize the temporary.  */
+           tree init = modify_expr (var, build_constructor (tarray, elms));
+           var = compound_expr (init, var);
 
            /* Generate: _d_newarraymTX(ti, dims)
                     or: _d_newarraymiTX(ti, dims)  */
@@ -2510,7 +2506,6 @@ public:
                                       build_address (var));
 
            result = build_libcall (libcall, tb, 2, tinfo, dims);
-           result = bind_expr (var, result);
          }
 
        if (e->argprefix)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 0b70f660fb8..984db29ccac 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2020-05-17  Iain Buclaw  <ibuc...@gdcproject.org>
+
+       Backport from mainline
+       2020-05-06  Iain Buclaw  <ibuc...@gdcproject.org>
+
+       PR d/94970
+       * gdc.dg/pr94970.d: New test.
+
 2020-05-16  Iain Buclaw  <ibuc...@gdcproject.org>
 
        PR d/95155
diff --git a/gcc/testsuite/gdc.dg/pr94970.d b/gcc/testsuite/gdc.dg/pr94970.d
new file mode 100644
index 00000000000..4c3387e3d4b
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr94970.d
@@ -0,0 +1,20 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94970
+// { dg-do compile }
+
+struct S94970
+{
+    string index() { return null; }
+    ~this() { }
+}
+
+static m() { return S94970(); }
+
+auto concat()
+{
+    return m.index ~ ' ';
+}
+
+auto newarray()
+{
+    return new int[][](m.index.length, 1);
+}
-- 
2.20.1

Reply via email to