diff options
author | Paul Thomas <pault@gcc.gnu.org> | 2007-07-24 19:15:27 +0000 |
---|---|---|
committer | Paul Thomas <pault@gcc.gnu.org> | 2007-07-24 19:15:27 +0000 |
commit | 08113c7398f734fdabf27af9d143af83ebde3767 (patch) | |
tree | 32b8097802564b8678cba249265de7ae9a445e64 | |
parent | b21a6ea1002424fcb2b3d5d5661526ce7abbb358 (diff) | |
download | gcc-08113c7398f734fdabf27af9d143af83ebde3767.zip gcc-08113c7398f734fdabf27af9d143af83ebde3767.tar.gz gcc-08113c7398f734fdabf27af9d143af83ebde3767.tar.bz2 |
re PR fortran/31205 (aliased operator assignment produces wrong result)
2007-07-24 Paul Thomas <pault@gcc.gnu.org>
PR fortran/31205
PR fortran/32842
* trans-expr.c (gfc_conv_function_call): Remove the default
initialization of intent(out) derived types.
* symbol.c (gfc_lval_expr_from_sym): New function.
* matchexp.c (gfc_get_parentheses): Return argument, if it is
character and posseses a ref.
* gfortran.h : Add prototype for gfc_lval_expr_from_sym.
* resolve.c (has_default_initializer): Move higher up in file.
(resolve_code): On detecting an interface assignment, check
if the rhs and the lhs are the same symbol. If this is so,
enclose the rhs in parenetheses to generate a temporary and
prevent any possible aliasing.
(apply_default_init): Remove code making the lval and call
gfc_lval_expr_from_sym instead.
(resolve_operator): Give a parentheses expression a type-
spec if it has no type.
* trans-decl.c (gfc_trans_deferred_vars): Apply the a default
initializer, if any, to an intent(out) derived type, using
gfc_lval_expr_from_sym and gfc_trans_assignment. Check if
the dummy is present.
2007-07-24 Paul Thomas <pault@gcc.gnu.org>
PR fortran/31205
* gfortran.dg/alloc_comp_basics_1.f90 : Restore number of
"deallocates" to 24, since patch has code rid of much spurious
code.
* gfortran.dg/interface_assignment_1.f90 : New test.
PR fortran/32842
* gfortran.dg/interface_assignment_2.f90 : New test.
From-SVN: r126885
-rw-r--r-- | gcc/fortran/ChangeLog | 24 | ||||
-rw-r--r-- | gcc/fortran/gfortran.h | 2 | ||||
-rw-r--r-- | gcc/fortran/matchexp.c | 17 | ||||
-rw-r--r-- | gcc/fortran/resolve.c | 72 | ||||
-rw-r--r-- | gcc/fortran/symbol.c | 29 | ||||
-rw-r--r-- | gcc/fortran/trans-decl.c | 35 | ||||
-rw-r--r-- | gcc/fortran/trans-expr.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/alloc_comp_basics_1.f90 | 2 |
9 files changed, 144 insertions, 59 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 62489c8..7050f52 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,27 @@ +2007-07-24 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/31205 + PR fortran/32842 + * trans-expr.c (gfc_conv_function_call): Remove the default + initialization of intent(out) derived types. + * symbol.c (gfc_lval_expr_from_sym): New function. + * matchexp.c (gfc_get_parentheses): Return argument, if it is + character and posseses a ref. + * gfortran.h : Add prototype for gfc_lval_expr_from_sym. + * resolve.c (has_default_initializer): Move higher up in file. + (resolve_code): On detecting an interface assignment, check + if the rhs and the lhs are the same symbol. If this is so, + enclose the rhs in parenetheses to generate a temporary and + prevent any possible aliasing. + (apply_default_init): Remove code making the lval and call + gfc_lval_expr_from_sym instead. + (resolve_operator): Give a parentheses expression a type- + spec if it has no type. + * trans-decl.c (gfc_trans_deferred_vars): Apply the a default + initializer, if any, to an intent(out) derived type, using + gfc_lval_expr_from_sym and gfc_trans_assignment. Check if + the dummy is present. + 2007-07-24 Daniel Franke <franke.daniel@gmail.com> PR fortran/32867 diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index c59aa65..f475c1e 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -2120,6 +2120,8 @@ void gfc_free_st_label (gfc_st_label *); void gfc_define_st_label (gfc_st_label *, gfc_sl_type, locus *); try gfc_reference_st_label (gfc_st_label *, gfc_sl_type); +gfc_expr * gfc_lval_expr_from_sym (gfc_symbol *); + gfc_namespace *gfc_get_namespace (gfc_namespace *, int); gfc_symtree *gfc_new_symtree (gfc_symtree **, const char *); gfc_symtree *gfc_find_symtree (gfc_symtree *, const char *); diff --git a/gcc/fortran/matchexp.c b/gcc/fortran/matchexp.c index f681e66..f67871b 100644 --- a/gcc/fortran/matchexp.c +++ b/gcc/fortran/matchexp.c @@ -131,6 +131,13 @@ gfc_get_parentheses (gfc_expr *e) { gfc_expr *e2; + /* This is a temporary fix, awaiting the patch for various + other character problems. The resolution and translation + of substrings and concatenations are so kludged up that + putting parentheses around them breaks everything. */ + if (e->ts.type == BT_CHARACTER && e->ref) + return e; + e2 = gfc_get_expr(); e2->expr_type = EXPR_OP; e2->ts = e->ts; @@ -181,13 +188,9 @@ match_primary (gfc_expr **result) gfc_error ("Expected a right parenthesis in expression at %C"); /* Now we have the expression inside the parentheses, build the - expression pointing to it. By 7.1.7.2 the integrity of - parentheses is only conserved in numerical calculations, so we - don't bother to keep the parentheses otherwise. */ - if(!gfc_numeric_ts(&e->ts)) - *result = e; - else - *result = gfc_get_parentheses (e); + expression pointing to it. By 7.1.7.2, any expression in + parentheses shall be treated as a data entity. */ + *result = gfc_get_parentheses (e); if (m != MATCH_YES) { diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index ceb8473..7580d80 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -2937,16 +2937,24 @@ resolve_operator (gfc_expr *e) break; + case INTRINSIC_PARENTHESES: + + /* This is always correct and sometimes necessary! */ + if (e->ts.type == BT_UNKNOWN) + e->ts = op1->ts; + + if (e->ts.type == BT_CHARACTER && !e->ts.cl) + e->ts.cl = op1->ts.cl; + case INTRINSIC_NOT: case INTRINSIC_UPLUS: case INTRINSIC_UMINUS: - case INTRINSIC_PARENTHESES: + /* Simply copy arrayness attribute */ e->rank = op1->rank; if (e->shape == NULL) e->shape = gfc_copy_shape (op1->shape, op1->rank); - /* Simply copy arrayness attribute */ break; default: @@ -5710,6 +5718,21 @@ gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns) } +static gfc_component * +has_default_initializer (gfc_symbol *der) +{ + gfc_component *c; + for (c = der->components; c; c = c->next) + if ((c->ts.type != BT_DERIVED && c->initializer) + || (c->ts.type == BT_DERIVED + && !c->pointer + && has_default_initializer (c->ts.derived))) + break; + + return c; +} + + /* Given a block of code, recursively resolve everything pointed to by this code block. */ @@ -5829,6 +5852,9 @@ resolve_code (gfc_code *code, gfc_namespace *ns) if (gfc_extend_assign (code, ns) == SUCCESS) { + gfc_expr *lhs = code->ext.actual->expr; + gfc_expr *rhs = code->ext.actual->next->expr; + if (gfc_pure (NULL) && !gfc_pure (code->symtree->n.sym)) { gfc_error ("Subroutine '%s' called instead of assignment at " @@ -5836,6 +5862,15 @@ resolve_code (gfc_code *code, gfc_namespace *ns) &code->loc); break; } + + /* Make a temporary rhs when there is a default initializer + and rhs is the same symbol as the lhs. */ + if (rhs->expr_type == EXPR_VARIABLE + && rhs->symtree->n.sym->ts.type == BT_DERIVED + && has_default_initializer (rhs->symtree->n.sym->ts.derived) + && (lhs->symtree->n.sym == rhs->symtree->n.sym)) + code->ext.actual->next->expr = gfc_get_parentheses (rhs); + goto call; } @@ -6413,23 +6448,7 @@ apply_default_init (gfc_symbol *sym) } /* Build an l-value expression for the result. */ - lval = gfc_get_expr (); - lval->expr_type = EXPR_VARIABLE; - lval->where = sym->declared_at; - lval->ts = sym->ts; - lval->symtree = gfc_find_symtree (sym->ns->sym_root, sym->name); - - /* It will always be a full array. */ - lval->rank = sym->as ? sym->as->rank : 0; - if (lval->rank) - { - lval->ref = gfc_get_ref (); - lval->ref->type = REF_ARRAY; - lval->ref->u.ar.type = AR_FULL; - lval->ref->u.ar.dimen = lval->rank; - lval->ref->u.ar.where = sym->declared_at; - lval->ref->u.ar.as = sym->as; - } + lval = gfc_lval_expr_from_sym (sym); /* Add the code at scope entry. */ init_st = gfc_get_code (); @@ -6485,21 +6504,6 @@ resolve_fl_var_and_proc (gfc_symbol *sym, int mp_flag) } -static gfc_component * -has_default_initializer (gfc_symbol *der) -{ - gfc_component *c; - for (c = der->components; c; c = c->next) - if ((c->ts.type != BT_DERIVED && c->initializer) - || (c->ts.type == BT_DERIVED - && !c->pointer - && has_default_initializer (c->ts.derived))) - break; - - return c; -} - - /* Resolve symbols with flavor variable. */ static try diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c index 32fe1f1..af42e9b 100644 --- a/gcc/fortran/symbol.c +++ b/gcc/fortran/symbol.c @@ -1959,6 +1959,35 @@ done: } +/*******A helper function for creating new expressions*************/ + + +gfc_expr * +gfc_lval_expr_from_sym (gfc_symbol *sym) +{ + gfc_expr *lval; + lval = gfc_get_expr (); + lval->expr_type = EXPR_VARIABLE; + lval->where = sym->declared_at; + lval->ts = sym->ts; + lval->symtree = gfc_find_symtree (sym->ns->sym_root, sym->name); + + /* It will always be a full array. */ + lval->rank = sym->as ? sym->as->rank : 0; + if (lval->rank) + { + lval->ref = gfc_get_ref (); + lval->ref->type = REF_ARRAY; + lval->ref->u.ar.type = AR_FULL; + lval->ref->u.ar.dimen = lval->rank; + lval->ref->u.ar.where = sym->declared_at; + lval->ref->u.ar.as = sym->as; + } + + return lval; +} + + /************** Symbol table management subroutines ****************/ /* Basic details: Fortran 95 requires a potentially unlimited number diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index 1fd4373..6c6cba0 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -2725,12 +2725,35 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, tree fnbody) gfc_init_block (&body); for (f = proc_sym->formal; f; f = f->next) - if (f->sym && f->sym->tlink == NULL && f->sym->ts.type == BT_CHARACTER) - { - gcc_assert (f->sym->ts.cl->backend_decl != NULL); - if (TREE_CODE (f->sym->ts.cl->backend_decl) == PARM_DECL) - gfc_trans_vla_type_sizes (f->sym, &body); - } + { + if (f->sym && f->sym->tlink == NULL && f->sym->ts.type == BT_CHARACTER) + { + gcc_assert (f->sym->ts.cl->backend_decl != NULL); + if (TREE_CODE (f->sym->ts.cl->backend_decl) == PARM_DECL) + gfc_trans_vla_type_sizes (f->sym, &body); + } + + /* If an INTENT(OUT) dummy of derived type has a default + initializer, it must be initialized here. */ + if (f->sym && f->sym->attr.referenced + && f->sym->attr.intent == INTENT_OUT + && f->sym->ts.type == BT_DERIVED + && !f->sym->ts.derived->attr.alloc_comp + && f->sym->value) + { + gfc_expr *tmpe; + tree tmp, present; + gcc_assert (!f->sym->attr.allocatable); + tmpe = gfc_lval_expr_from_sym (f->sym); + tmp = gfc_trans_assignment (tmpe, f->sym->value, false); + + present = gfc_conv_expr_present (f->sym); + tmp = build3 (COND_EXPR, TREE_TYPE (tmp), present, + tmp, build_empty_stmt ()); + gfc_add_expr_to_block (&body, tmp); + gfc_free_expr (tmpe); + } + } if (gfc_return_by_reference (proc_sym) && proc_sym->ts.type == BT_CHARACTER && current_fake_result_decl != NULL) diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 898a626..2436574 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -2245,17 +2245,6 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym, && fsym->attr.optional) gfc_conv_missing_dummy (&parmse, e, fsym->ts); - /* If an INTENT(OUT) dummy of derived type has a default - initializer, it must be (re)initialized here. */ - if (fsym->attr.intent == INTENT_OUT - && fsym->ts.type == BT_DERIVED - && fsym->value) - { - gcc_assert (!fsym->attr.allocatable); - tmp = gfc_trans_assignment (e, fsym->value, false); - gfc_add_expr_to_block (&se->pre, tmp); - } - /* Obtain the character length of an assumed character length procedure from the typespec. */ if (fsym->ts.type == BT_CHARACTER diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3b36d6a..6a39a3a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2007-07-24 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/31205 + * gfortran.dg/alloc_comp_basics_1.f90 : Restore number of + "deallocates" to 24, since patch has code rid of much spurious + code. + * gfortran.dg/interface_assignment_1.f90 : New test. + + PR fortran/32842 + * gfortran.dg/interface_assignment_2.f90 : New test. + 2007-07-24 Daniel Franke <franke.daniel@gmail.com> PR fortran/32867 diff --git a/gcc/testsuite/gfortran.dg/alloc_comp_basics_1.f90 b/gcc/testsuite/gfortran.dg/alloc_comp_basics_1.f90 index 7099001..a4617cb 100644 --- a/gcc/testsuite/gfortran.dg/alloc_comp_basics_1.f90 +++ b/gcc/testsuite/gfortran.dg/alloc_comp_basics_1.f90 @@ -139,6 +139,6 @@ contains end subroutine check_alloc2 end program alloc -! { dg-final { scan-tree-dump-times "deallocate" 33 "original" } } +! { dg-final { scan-tree-dump-times "deallocate" 24 "original" } } ! { dg-final { cleanup-tree-dump "original" } } ! { dg-final { cleanup-modules "alloc_m" } } |