2013-04-18 Tobias Burnus <burnus@net-b.de>
* expr.c (find_array_element): Don't copy expr.
* data.c (create_character_initializer): Free expr.
* frontend-passes.c (combine_array_constructor): Ditto.
* match.c (match_typebound_call, gfc_match_select_type): Ditto.
* resolve.c (resolve_typebound_function): Free gfc_ref.
@@ -93,60 +93,66 @@ find_con_by_component (gfc_component *com, gfc_constructor_base base)
return NULL;
}
/* Create a character type initialization expression from RVALUE.
TS [and REF] describe [the substring of] the variable being initialized.
INIT is the existing initializer, not NULL. Initialization is performed
according to normal assignment rules. */
static gfc_expr *
create_character_initializer (gfc_expr *init, gfc_typespec *ts,
gfc_ref *ref, gfc_expr *rvalue)
{
int len, start, end;
gfc_char_t *dest;
+ bool alloced_init = false;
gfc_extract_int (ts->u.cl->length, &len);
if (init == NULL)
{
/* Create a new initializer. */
init = gfc_get_character_expr (ts->kind, NULL, NULL, len);
init->ts = *ts;
+ alloced_init = true;
}
dest = init->value.character.string;
if (ref)
{
gfc_expr *start_expr, *end_expr;
gcc_assert (ref->type == REF_SUBSTRING);
/* Only set a substring of the destination. Fortran substring bounds
are one-based [start, end], we want zero based [start, end). */
start_expr = gfc_copy_expr (ref->u.ss.start);
end_expr = gfc_copy_expr (ref->u.ss.end);
if ((!gfc_simplify_expr(start_expr, 1))
|| !(gfc_simplify_expr(end_expr, 1)))
{
gfc_error ("failure to simplify substring reference in DATA "
"statement at %L", &ref->u.ss.start->where);
+ gfc_free_expr (start_expr);
+ gfc_free_expr (end_expr);
+ if (alloced_init)
+ gfc_free_expr (init);
return NULL;
}
gfc_extract_int (start_expr, &start);
gfc_free_expr (start_expr);
start--;
gfc_extract_int (end_expr, &end);
gfc_free_expr (end_expr);
}
else
{
/* Set the whole string. */
start = 0;
end = len;
}
@@ -1196,33 +1196,33 @@ find_array_element (gfc_constructor_base base, gfc_array_ref *ar,
e = NULL;
mpz_init_set_ui (offset, 0);
mpz_init (delta);
mpz_init (tmp);
mpz_init_set_ui (span, 1);
for (i = 0; i < ar->dimen; i++)
{
if (!gfc_reduce_init_expr (ar->as->lower[i])
|| !gfc_reduce_init_expr (ar->as->upper[i]))
{
t = false;
cons = NULL;
goto depart;
}
- e = gfc_copy_expr (ar->start[i]);
+ e = ar->start[i];
if (e->expr_type != EXPR_CONSTANT)
{
cons = NULL;
goto depart;
}
gcc_assert (ar->as->upper[i]->expr_type == EXPR_CONSTANT
&& ar->as->lower[i]->expr_type == EXPR_CONSTANT);
/* Check the bounds. */
if ((ar->as->upper[i]
&& mpz_cmp (e->value.integer,
ar->as->upper[i]->value.integer) > 0)
|| (mpz_cmp (e->value.integer,
ar->as->lower[i]->value.integer) < 0))
{
@@ -1245,34 +1245,32 @@ find_array_element (gfc_constructor_base base, gfc_array_ref *ar,
for (cons = gfc_constructor_first (base), nelemen = mpz_get_ui (offset);
cons && nelemen > 0; cons = gfc_constructor_next (cons), nelemen--)
{
if (cons->iterator)
{
cons = NULL;
goto depart;
}
}
depart:
mpz_clear (delta);
mpz_clear (offset);
mpz_clear (span);
mpz_clear (tmp);
- if (e)
- gfc_free_expr (e);
*rval = cons;
return t;
}
/* Find a component of a structure constructor. */
static gfc_constructor *
find_component_ref (gfc_constructor_base base, gfc_ref *ref)
{
gfc_component *comp;
gfc_component *pick;
gfc_constructor *c = gfc_constructor_first (base);
comp = ref->u.c.sym->components;
pick = ref->u.c.component;
@@ -1060,32 +1060,33 @@ combine_array_constructor (gfc_expr *e)
new_expr->value.op.op1 = gfc_copy_expr (scalar);
new_expr->value.op.op2 = gfc_copy_expr (c->expr);
}
else
{
new_expr->value.op.op1 = gfc_copy_expr (c->expr);
new_expr->value.op.op2 = gfc_copy_expr (scalar);
}
new_c = gfc_constructor_append_expr (&newbase, new_expr, &(e->where));
new_c->iterator = c->iterator;
c->iterator = NULL;
}
gfc_free_expr (op1);
gfc_free_expr (op2);
+ gfc_free_expr (scalar);
e->value.constructor = newbase;
return true;
}
/* Recursive optimization of operators. */
static bool
optimize_op (gfc_expr *e)
{
bool changed;
gfc_intrinsic_op op = e->value.op.op;
changed = false;
@@ -4064,48 +4064,53 @@ done:
static match
match_typebound_call (gfc_symtree* varst)
{
gfc_expr* base;
match m;
base = gfc_get_expr ();
base->expr_type = EXPR_VARIABLE;
base->symtree = varst;
base->where = gfc_current_locus;
gfc_set_sym_referenced (varst->n.sym);
m = gfc_match_varspec (base, 0, true, true);
if (m == MATCH_NO)
gfc_error ("Expected component reference at %C");
if (m != MATCH_YES)
- return MATCH_ERROR;
+ {
+ gfc_free_expr (base);
+ return MATCH_ERROR;
+ }
if (gfc_match_eos () != MATCH_YES)
{
gfc_error ("Junk after CALL at %C");
+ gfc_free_expr (base);
return MATCH_ERROR;
}
if (base->expr_type == EXPR_COMPCALL)
new_st.op = EXEC_COMPCALL;
else if (base->expr_type == EXPR_PPC)
new_st.op = EXEC_CALL_PPC;
else
{
gfc_error ("Expected type-bound procedure or procedure pointer component "
"at %C");
+ gfc_free_expr (base);
return MATCH_ERROR;
}
new_st.expr1 = base;
return MATCH_YES;
}
/* Match a CALL statement. The tricky part here are possible
alternate return specifiers. We handle these by having all
"subroutines" actually return an integer via a register that gives
the return number. If the call specifies alternate returns, we
generate code for a SELECT statement whose case clauses contain
GOTOs to the various labels. */
match
@@ -5358,33 +5363,33 @@ gfc_match_select_type (void)
}
sym = expr1->symtree->n.sym;
if (expr2->ts.type == BT_UNKNOWN)
sym->attr.untyped = 1;
else
copy_ts_from_selector_to_associate (expr1, expr2);
sym->attr.flavor = FL_VARIABLE;
sym->attr.referenced = 1;
sym->attr.class_ok = 1;
}
else
{
m = gfc_match (" %e ", &expr1);
if (m != MATCH_YES)
- goto cleanup;
+ return m;
}
m = gfc_match (" )%t");
if (m != MATCH_YES)
{
gfc_error ("parse error in SELECT TYPE statement at %C");
goto cleanup;
}
/* This ghastly expression seems to be needed to distinguish a CLASS
array, which can have a reference, from other expressions that
have references, such as derived type components, and are not
allowed by the standard.
TODO: see if it is sufficient to exclude component and substring
references. */
class_array = expr1->expr_type == EXPR_VARIABLE
@@ -5404,32 +5409,34 @@ gfc_match_select_type (void)
gfc_error ("Selector in SELECT TYPE at %C is not a named variable; "
"use associate-name=>");
m = MATCH_ERROR;
goto cleanup;
}
new_st.op = EXEC_SELECT_TYPE;
new_st.expr1 = expr1;
new_st.expr2 = expr2;
new_st.ext.block.ns = gfc_current_ns;
select_type_push (expr1->symtree->n.sym);
return MATCH_YES;
cleanup:
+ gfc_free_expr (expr1);
+ gfc_free_expr (expr2);
return m;
}
/* Match a CASE statement. */
match
gfc_match_case (void)
{
gfc_case *c, *head, *tail;
match m;
head = tail = NULL;
if (gfc_current_state () != COMP_SELECT)
{
@@ -5706,32 +5706,34 @@ resolve_typebound_function (gfc_expr* e)
e->value.function.esym = NULL;
e->symtree = st;
if (new_ref)
e->ref = new_ref;
/* '_vptr' points to the vtab, which contains the procedure pointers. */
gfc_add_vptr_component (e);
gfc_add_component_ref (e, name);
/* Recover the typespec for the expression. This is really only
necessary for generic procedures, where the additional call
to gfc_add_component_ref seems to throw the collection of the
correct typespec. */
e->ts = ts;
}
+ else if (new_ref)
+ gfc_free_ref_list (new_ref);
return true;
}
/* Resolve a typebound subroutine, or 'method'. First separate all
the non-CLASS references by calling resolve_typebound_call
directly. */
static bool
resolve_typebound_subroutine (gfc_code *code)
{
gfc_symbol *declared;
gfc_component *c;
gfc_ref *new_ref;
gfc_ref *class_ref;
gfc_symtree *st;