]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
d: Fix ICE in verify_gimple_stmt, at tree-cfg.c:4959
authorIain Buclaw <ibuclaw@gdcproject.org>
Sun, 17 May 2020 14:28:24 +0000 (16:28 +0200)
committerIain Buclaw <ibuclaw@gdcproject.org>
Sun, 17 May 2020 14:28:24 +0000 (16:28 +0200)
Both array concat and array new expressions wrapped any temporaries
created into a BIND_EXPR.  This does not work if an expression used to
construct the result requires scope destruction, which is represented by
a TARGET_EXPR with a clean-up, and a CLEANUP_POINT_EXPR at the
location where the temporaries logically go out of scope.  The reason
for this not working is because the lowering of cleanup point
expressions does not traverse inside BIND_EXPRs to expand any gimple
cleanup expressions within.

The use of creating BIND_EXPR has been removed at both locations, and
replaced with a normal temporary variable that has initialization
delayed until its address is taken.

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
gcc/d/d-codegen.cc
gcc/d/d-convert.cc
gcc/d/d-tree.h
gcc/d/expr.cc
gcc/testsuite/ChangeLog
gcc/testsuite/gdc.dg/pr94970.d [new file with mode: 0644]

index c3f565902985cec9769f684b223edc5cd8e92f8e..5048d2ab4003beac18d5df9b63e39154e79acc2a 100644 (file)
@@ -1,3 +1,23 @@
+2020-05-17  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       Backport from mainline
+       2020-05-06  Iain Buclaw  <ibuclaw@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  <ibuclaw@gdcproject.org>
 
        PR d/95155
index 2abff92fc8864b38cebc5defdb5fefc59b59d44a..17f624b5a4f2f1125b6f67d8c6fdd94239b7639b 100644 (file)
@@ -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().  */
 
index e9aa457d852b3d884a5ca01bb06d684d14f97827..761ab3c543575500a4ece43e471e93942e7b81e5 100644 (file)
@@ -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));
index a514bc3902fe54cfdc3df1f1fd078939ad11a0a0..7a54dfbc59eac8b1405c7a7621bb046780010f98 100644 (file)
@@ -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);
index 6497619e5fdeb130dffe17d48694d9f0dbe67aa1..3a2823d6e46c8772a337015c86e7a97f53bbe2d6 100644 (file)
@@ -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)
index 0b70f660fb85ab532fa9430fc39f5347fe26e046..984db29ccac12c901af55344dd3c8b268729a133 100644 (file)
@@ -1,3 +1,11 @@
+2020-05-17  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       Backport from mainline
+       2020-05-06  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       PR d/94970
+       * gdc.dg/pr94970.d: New test.
+
 2020-05-16  Iain Buclaw  <ibuclaw@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 (file)
index 0000000..4c3387e
--- /dev/null
@@ -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);
+}