+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-04-30 Iain Buclaw <ibuclaw@gdcproject.org>
* gdc.texi (Options for Linking): Clarify usage of -defaultlib= and
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);
}
}
}
-/* 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(). */
/* 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));
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 *);
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);
else
etype = tb2->nextOf ();
- vec<tree, va_gc> *elemvars = NULL;
tree result;
if (e->e1->op == TOKcat)
/* 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;
? (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));
/* 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));
/* 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;
}
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];
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) */
build_address (var));
result = build_libcall (libcall, tb, 2, tinfo, dims);
- result = bind_expr (var, result);
}
if (e->argprefix)
+2020-05-06 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/94970
+ * gdc.dg/pr94970.d: New test.
+
2020-05-06 Jakub Jelinek <jakub@redhat.com>
PR c++/94951
--- /dev/null
+// 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);
+}