aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/resolve.c
diff options
context:
space:
mode:
authorPaul Thomas <pault@gcc.gnu.org>2007-05-12 06:19:43 +0000
committerPaul Thomas <pault@gcc.gnu.org>2007-05-12 06:19:43 +0000
commiteb77cddf4276f2ae7c6745cd7cf82dd49327dc4f (patch)
treedd588c8fbf0e9cef5549e43a87d6b2ca8e4a03a1 /gcc/fortran/resolve.c
parente39187d4f39e1ce1184316fa1e3886439dd23818 (diff)
downloadgcc-eb77cddf4276f2ae7c6745cd7cf82dd49327dc4f.zip
gcc-eb77cddf4276f2ae7c6745cd7cf82dd49327dc4f.tar.gz
gcc-eb77cddf4276f2ae7c6745cd7cf82dd49327dc4f.tar.bz2
re PR fortran/30746 (50th Anniversary Bug - Forward reference to contained function)
2007-05-12 Paul Thomas <pault@gcc.gnu.org> PR fortran/30746 * resolve.c (check_host_association): New function that detects incorrect host association and corrects it. (gfc_resolve_expr): Call the new function for variables and functions. * match.h : Remove prototype for gfc_match_rvalue. * gfortran.h : Add prototype for gfc_match_rvalue. 2007-05-12 Paul Thomas <pault@gcc.gnu.org> PR fortran/30746 * gfortran.dg/host_assoc_function_1.f90: New test. From-SVN: r124633
Diffstat (limited to 'gcc/fortran/resolve.c')
-rw-r--r--gcc/fortran/resolve.c79
1 files changed, 73 insertions, 6 deletions
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index dbb36d3..b6d1f3b 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -3204,6 +3204,70 @@ resolve_variable (gfc_expr *e)
}
+/* Checks to see that the correct symbol has been host associated.
+ The only situation where this arises is that in which a twice
+ contained function is parsed after the host association is made.
+ Therefore, on detecting this, the line is rematched, having got
+ rid of the existing references and actual_arg_list. */
+static bool
+check_host_association (gfc_expr *e)
+{
+ gfc_symbol *sym, *old_sym;
+ locus temp_locus;
+ gfc_expr *expr;
+ int n;
+
+ if (e->symtree == NULL || e->symtree->n.sym == NULL)
+ return e->expr_type == EXPR_FUNCTION;
+
+ old_sym = e->symtree->n.sym;
+ if (gfc_current_ns->parent
+ && gfc_current_ns->parent->parent
+ && old_sym->ns != gfc_current_ns)
+ {
+ gfc_find_symbol (old_sym->name, gfc_current_ns->parent, 1, &sym);
+ if (sym && old_sym != sym && sym->attr.flavor == FL_PROCEDURE)
+ {
+ temp_locus = gfc_current_locus;
+ gfc_current_locus = e->where;
+
+ gfc_buffer_error (1);
+
+ gfc_free_ref_list (e->ref);
+ e->ref = NULL;
+
+ if (e->expr_type == EXPR_FUNCTION)
+ {
+ gfc_free_actual_arglist (e->value.function.actual);
+ e->value.function.actual = NULL;
+ }
+
+ if (e->shape != NULL)
+ {
+ for (n = 0; n < e->rank; n++)
+ mpz_clear (e->shape[n]);
+
+ gfc_free (e->shape);
+ }
+
+ gfc_match_rvalue (&expr);
+ gfc_clear_error ();
+ gfc_buffer_error (0);
+
+ gcc_assert (expr && sym == expr->symtree->n.sym);
+
+ *e = *expr;
+ gfc_free (expr);
+ sym->refs++;
+
+ gfc_current_locus = temp_locus;
+ }
+ }
+
+ return e->expr_type == EXPR_FUNCTION;
+}
+
+
/* Resolve an expression. That is, make sure that types of operands agree
with their operators, intrinsic operators are converted to function calls
for overloaded types and unresolved function references are resolved. */
@@ -3223,13 +3287,16 @@ gfc_resolve_expr (gfc_expr *e)
break;
case EXPR_FUNCTION:
- t = resolve_function (e);
- break;
-
case EXPR_VARIABLE:
- t = resolve_variable (e);
- if (t == SUCCESS)
- expression_rank (e);
+
+ if (check_host_association (e))
+ t = resolve_function (e);
+ else
+ {
+ t = resolve_variable (e);
+ if (t == SUCCESS)
+ expression_rank (e);
+ }
break;
case EXPR_SUBSTRING: