aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/resolve.c
diff options
context:
space:
mode:
authorPaul Thomas <pault@gcc.gnu.org>2007-11-27 20:47:55 +0000
committerPaul Thomas <pault@gcc.gnu.org>2007-11-27 20:47:55 +0000
commit908a22351801ee5f0f364d14a55ae38f546565b4 (patch)
tree02fd93e8d327aa79aa562c5f974746f1257b83be /gcc/fortran/resolve.c
parent0e5a218b31eb720caa70b19439e26f658f151070 (diff)
downloadgcc-908a22351801ee5f0f364d14a55ae38f546565b4.zip
gcc-908a22351801ee5f0f364d14a55ae38f546565b4.tar.gz
gcc-908a22351801ee5f0f364d14a55ae38f546565b4.tar.bz2
re PR fortran/29389 (Statement functions are not recognized as pure when they are)
2007-11-27 Paul Thomas <pault@gcc.gnu.org> PR fortran/29389 *resolve.c (resolve_ordinary_assign): Use find_sym_in_expr to test if a temporary should be written for a vector subscript on the lhs. PR fortran/33850 * restore.c (pure_stmt_function): Add prototype and new function. Calls impure_stmt_fcn. (pure_function): Call it. (impure_stmt_fcn): New function. * expr.c (gfc_traverse_expr): Call *func for all expression types, not just variables. Add traversal of character lengths, iterators and component character lengths and arrayspecs. (expr_set_symbols_referenced): Return false if not a variable. * trans-stmt.c (forall_replace, forall_restore): Ditto. * resolve.c (forall_index): Ditto. (sym_in_expr): New function. (find_sym_in_expr): Rewrite to traverse expression calling sym_in_expr. *trans-decl.c (expr_decls): New function. (generate_expr_decls): Rewrite to traverse expression calling expr_decls. *match.c (check_stmt_fcn): New function. (recursive_stmt_fcn): Rewrite to traverse expression calling check_stmt_fcn. 2007-11-27 Paul Thomas <pault@gcc.gnu.org> PR fortran/29389 * gfortran.dg/stfunc_6.f90: New test. PR fortran/33850 * gfortran.dg/assign_10.f90: New test. From-SVN: r130472
Diffstat (limited to 'gcc/fortran/resolve.c')
-rw-r--r--gcc/fortran/resolve.c125
1 files changed, 45 insertions, 80 deletions
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 0fe5d32..eaa15d3 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -1665,6 +1665,8 @@ is_external_proc (gfc_symbol *sym)
/* Figure out if a function reference is pure or not. Also set the name
of the function for a potential error message. Return nonzero if the
function is PURE, zero if not. */
+static int
+pure_stmt_function (gfc_expr *, gfc_symbol *);
static int
pure_function (gfc_expr *e, const char **name)
@@ -1676,7 +1678,7 @@ pure_function (gfc_expr *e, const char **name)
if (e->symtree != NULL
&& e->symtree->n.sym != NULL
&& e->symtree->n.sym->attr.proc == PROC_ST_FUNCTION)
- return 1;
+ return pure_stmt_function (e, e->symtree->n.sym);
if (e->value.function.esym)
{
@@ -1700,6 +1702,31 @@ pure_function (gfc_expr *e, const char **name)
}
+static bool
+impure_stmt_fcn (gfc_expr *e, gfc_symbol *sym,
+ int *f ATTRIBUTE_UNUSED)
+{
+ const char *name;
+
+ /* Don't bother recursing into other statement functions
+ since they will be checked individually for purity. */
+ if (e->expr_type != EXPR_FUNCTION
+ || !e->symtree
+ || e->symtree->n.sym == sym
+ || e->symtree->n.sym->attr.proc == PROC_ST_FUNCTION)
+ return false;
+
+ return pure_function (e, &name) ? false : true;
+}
+
+
+static int
+pure_stmt_function (gfc_expr *e, gfc_symbol *sym)
+{
+ return gfc_traverse_expr (e, sym, impure_stmt_fcn, 0) ? 0 : 1;
+}
+
+
static try
is_scalar_expr_ptr (gfc_expr *expr)
{
@@ -4369,8 +4396,9 @@ gfc_resolve_iterator (gfc_iterator *iter, bool real_ok)
static bool
forall_index (gfc_expr *expr, gfc_symbol *sym, int *f)
{
- gcc_assert (expr->expr_type == EXPR_VARIABLE);
-
+ if (expr->expr_type != EXPR_VARIABLE)
+ return false;
+
/* A scalar assignment */
if (!expr->ref || *f == 1)
{
@@ -4552,85 +4580,20 @@ resolve_deallocate_expr (gfc_expr *e)
}
-/* Returns true if the expression e contains a reference the symbol sym. */
+/* Returns true if the expression e contains a reference to the symbol sym. */
static bool
-find_sym_in_expr (gfc_symbol *sym, gfc_expr *e)
+sym_in_expr (gfc_expr *e, gfc_symbol *sym, int *f ATTRIBUTE_UNUSED)
{
- gfc_actual_arglist *arg;
- gfc_ref *ref;
- int i;
- bool rv = false;
-
- if (e == NULL)
- return rv;
-
- switch (e->expr_type)
- {
- case EXPR_FUNCTION:
- for (arg = e->value.function.actual; arg; arg = arg->next)
- rv = rv || find_sym_in_expr (sym, arg->expr);
- break;
-
- /* If the variable is not the same as the dependent, 'sym', and
- it is not marked as being declared and it is in the same
- namespace as 'sym', add it to the local declarations. */
- case EXPR_VARIABLE:
- if (sym == e->symtree->n.sym)
- return true;
- break;
-
- case EXPR_OP:
- rv = rv || find_sym_in_expr (sym, e->value.op.op1);
- rv = rv || find_sym_in_expr (sym, e->value.op.op2);
- break;
-
- default:
- break;
- }
-
- if (e->ref)
- {
- for (ref = e->ref; ref; ref = ref->next)
- {
- switch (ref->type)
- {
- case REF_ARRAY:
- for (i = 0; i < ref->u.ar.dimen; i++)
- {
- rv = rv || find_sym_in_expr (sym, ref->u.ar.start[i]);
- rv = rv || find_sym_in_expr (sym, ref->u.ar.end[i]);
- rv = rv || find_sym_in_expr (sym, ref->u.ar.stride[i]);
- }
- break;
-
- case REF_SUBSTRING:
- rv = rv || find_sym_in_expr (sym, ref->u.ss.start);
- rv = rv || find_sym_in_expr (sym, ref->u.ss.end);
- break;
+ if (e->expr_type == EXPR_VARIABLE && e->symtree->n.sym == sym)
+ return true;
- case REF_COMPONENT:
- if (ref->u.c.component->ts.type == BT_CHARACTER
- && ref->u.c.component->ts.cl->length->expr_type
- != EXPR_CONSTANT)
- rv = rv
- || find_sym_in_expr (sym,
- ref->u.c.component->ts.cl->length);
+ return false;
+}
- if (ref->u.c.component->as)
- for (i = 0; i < ref->u.c.component->as->rank; i++)
- {
- rv = rv
- || find_sym_in_expr (sym,
- ref->u.c.component->as->lower[i]);
- rv = rv
- || find_sym_in_expr (sym,
- ref->u.c.component->as->upper[i]);
- }
- break;
- }
- }
- }
- return rv;
+static bool
+find_sym_in_expr (gfc_symbol *sym, gfc_expr *e)
+{
+ return gfc_traverse_expr (e, sym, sym_in_expr, 0);
}
@@ -5970,14 +5933,16 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns)
}
/* Ensure that a vector index expression for the lvalue is evaluated
- to a temporary. */
+ to a temporary if the lvalue symbol is referenced in it. */
if (lhs->rank)
{
for (ref = lhs->ref; ref; ref= ref->next)
if (ref->type == REF_ARRAY)
{
for (n = 0; n < ref->u.ar.dimen; n++)
- if (ref->u.ar.dimen_type[n] == DIMEN_VECTOR)
+ if (ref->u.ar.dimen_type[n] == DIMEN_VECTOR
+ && find_sym_in_expr (lhs->symtree->n.sym,
+ ref->u.ar.start[n]))
ref->u.ar.start[n]
= gfc_get_parentheses (ref->u.ar.start[n]);
}