aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Thomas <pault@gcc.gnu.org>2007-07-24 19:15:27 +0000
committerPaul Thomas <pault@gcc.gnu.org>2007-07-24 19:15:27 +0000
commit08113c7398f734fdabf27af9d143af83ebde3767 (patch)
tree32b8097802564b8678cba249265de7ae9a445e64
parentb21a6ea1002424fcb2b3d5d5661526ce7abbb358 (diff)
downloadgcc-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/ChangeLog24
-rw-r--r--gcc/fortran/gfortran.h2
-rw-r--r--gcc/fortran/matchexp.c17
-rw-r--r--gcc/fortran/resolve.c72
-rw-r--r--gcc/fortran/symbol.c29
-rw-r--r--gcc/fortran/trans-decl.c35
-rw-r--r--gcc/fortran/trans-expr.c11
-rw-r--r--gcc/testsuite/ChangeLog11
-rw-r--r--gcc/testsuite/gfortran.dg/alloc_comp_basics_1.f902
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" } }