Commit 79f2ae6e by Iain Buclaw

d: Fix ICE in verify_gimple_stmt, at tree-cfg.c:4959

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.
parent bc709bc9
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-07 Release Manager 2020-05-07 Release Manager
* GCC 10.1.0 released. * GCC 10.1.0 released.
......
...@@ -619,7 +619,12 @@ build_target_expr (tree decl, tree exp) ...@@ -619,7 +619,12 @@ build_target_expr (tree decl, tree exp)
tree tree
force_target_expr (tree exp) 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); return build_target_expr (decl, exp);
} }
...@@ -1766,66 +1771,6 @@ array_bounds_check (void) ...@@ -1766,66 +1771,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. /* Returns the TypeFunction class for Type T.
Assumes T is already ->toBasetype(). */ Assumes T is already ->toBasetype(). */
......
...@@ -774,21 +774,23 @@ d_array_convert (Expression *exp) ...@@ -774,21 +774,23 @@ d_array_convert (Expression *exp)
/* Convert EXP to a dynamic array, where ETYPE is the element type. /* 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. 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 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 (); Type *tb = exp->type->toBasetype ();
if ((tb->ty != Tarray && tb->ty != Tsarray) || same_type_p (tb, etype)) if ((tb->ty != Tarray && tb->ty != Tsarray) || same_type_p (tb, etype))
{ {
/* Convert single element to an array. */ /* Convert single element to an array. */
tree var = NULL_TREE; tree expr = build_expr (exp);
tree expr = maybe_temporary_var (build_expr (exp), &var);
if (var != NULL_TREE) if (!exp->isLvalue ())
vec_safe_push (*vars, var); {
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 ()), return d_array_value (build_ctype (exp->type->arrayOf ()),
size_int (1), build_address (expr)); size_int (1), build_address (expr));
......
...@@ -561,8 +561,6 @@ extern tree build_array_from_val (Type *, tree); ...@@ -561,8 +561,6 @@ extern tree build_array_from_val (Type *, tree);
extern tree void_okay_p (tree); extern tree void_okay_p (tree);
extern tree build_bounds_condition (const Loc &, tree, tree, bool); extern tree build_bounds_condition (const Loc &, tree, tree, bool);
extern bool array_bounds_check (void); 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 tree bind_expr (tree, tree);
extern TypeFunction *get_function_type (Type *); extern TypeFunction *get_function_type (Type *);
extern bool call_by_alias_p (FuncDeclaration *, FuncDeclaration *); extern bool call_by_alias_p (FuncDeclaration *, FuncDeclaration *);
...@@ -586,7 +584,7 @@ extern tree convert_for_assignment (tree, Type *, Type *); ...@@ -586,7 +584,7 @@ extern tree convert_for_assignment (tree, Type *, Type *);
extern tree convert_for_argument (tree, Parameter *); extern tree convert_for_argument (tree, Parameter *);
extern tree convert_for_condition (tree, Type *); extern tree convert_for_condition (tree, Type *);
extern tree d_array_convert (Expression *); 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. */ /* In d-incpath.cc. */
extern void add_import_paths (const char *, const char *, bool); extern void add_import_paths (const char *, const char *, bool);
......
...@@ -691,7 +691,6 @@ public: ...@@ -691,7 +691,6 @@ public:
else else
etype = tb2->nextOf (); etype = tb2->nextOf ();
vec<tree, va_gc> *elemvars = NULL;
tree result; tree result;
if (e->e1->op == TOKcat) if (e->e1->op == TOKcat)
...@@ -711,9 +710,7 @@ public: ...@@ -711,9 +710,7 @@ public:
/* Store all concatenation args to a temporary byte[][ndims] array. */ /* Store all concatenation args to a temporary byte[][ndims] array. */
Type *targselem = Type::tint8->arrayOf (); Type *targselem = Type::tint8->arrayOf ();
tree var = create_temporary_var (make_array_type (targselem, ndims)); tree var = build_local_temp (make_array_type (targselem, ndims));
tree init = build_constructor (TREE_TYPE (var), NULL);
vec_safe_push (elemvars, var);
/* Loop through each concatenation from right to left. */ /* Loop through each concatenation from right to left. */
vec<constructor_elt, va_gc> *elms = NULL; vec<constructor_elt, va_gc> *elms = NULL;
...@@ -725,7 +722,7 @@ public: ...@@ -725,7 +722,7 @@ public:
? (oe = ce->e1) ? (oe = ce->e1)
: (ce = (CatExp *)ce->e1, oe = ce->e2))) : (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); tree index = size_int (dim);
CONSTRUCTOR_APPEND_ELT (elms, index, d_save_expr (arg)); CONSTRUCTOR_APPEND_ELT (elms, index, d_save_expr (arg));
...@@ -738,8 +735,8 @@ public: ...@@ -738,8 +735,8 @@ public:
/* Check there is no logic bug in constructing byte[][] of arrays. */ /* Check there is no logic bug in constructing byte[][] of arrays. */
gcc_assert (dim == 0); gcc_assert (dim == 0);
CONSTRUCTOR_ELTS (init) = elms; tree init = build_constructor (TREE_TYPE (var), elms);
DECL_INITIAL (var) = init; var = compound_expr (modify_expr (var, init), var);
tree arrs = d_array_value (build_ctype (targselem->arrayOf ()), tree arrs = d_array_value (build_ctype (targselem->arrayOf ()),
size_int (ndims), build_address (var)); size_int (ndims), build_address (var));
...@@ -752,13 +749,10 @@ public: ...@@ -752,13 +749,10 @@ public:
/* Handle single concatenation (a ~ b). */ /* Handle single concatenation (a ~ b). */
result = build_libcall (LIBCALL_ARRAYCATT, e->type, 3, result = build_libcall (LIBCALL_ARRAYCATT, e->type, 3,
build_typeinfo (e->loc, e->type), build_typeinfo (e->loc, e->type),
d_array_convert (etype, e->e1, &elemvars), d_array_convert (etype, e->e1),
d_array_convert (etype, e->e2, &elemvars)); 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; this->result_ = result;
} }
...@@ -2494,12 +2488,13 @@ public: ...@@ -2494,12 +2488,13 @@ public:
else else
{ {
/* Multidimensional array allocations. */ /* 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 tarray = make_array_type (Type::tsize_t, e->arguments->dim);
tree var = create_temporary_var (tarray); tree var = build_local_temp (tarray);
tree init = build_constructor (TREE_TYPE (var), NULL); 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++) for (size_t i = 0; i < e->arguments->dim; i++)
{ {
Expression *arg = (*e->arguments)[i]; Expression *arg = (*e->arguments)[i];
...@@ -2510,8 +2505,9 @@ public: ...@@ -2510,8 +2505,9 @@ public:
gcc_assert (telem); gcc_assert (telem);
} }
CONSTRUCTOR_ELTS (init) = elms; /* Initialize the temporary. */
DECL_INITIAL (var) = init; tree init = modify_expr (var, build_constructor (tarray, elms));
var = compound_expr (init, var);
/* Generate: _d_newarraymTX(ti, dims) /* Generate: _d_newarraymTX(ti, dims)
or: _d_newarraymiTX(ti, dims) */ or: _d_newarraymiTX(ti, dims) */
...@@ -2524,7 +2520,6 @@ public: ...@@ -2524,7 +2520,6 @@ public:
build_address (var)); build_address (var));
result = build_libcall (libcall, tb, 2, tinfo, dims); result = build_libcall (libcall, tb, 2, tinfo, dims);
result = bind_expr (var, result);
} }
if (e->argprefix) if (e->argprefix)
......
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-13 Mark Eggleston <markeggleston@gcc.gnu.org> 2020-05-13 Mark Eggleston <markeggleston@gcc.gnu.org>
Backport from master Backport from master
......
// 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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment