Commit eb77cddf by Paul Thomas

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
parent e39187d4
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-11 Paul Thomas <pault@gcc.gnu.org> 2007-05-11 Paul Thomas <pault@gcc.gnu.org>
PR fortran/30876 PR fortran/30876
......
...@@ -2160,6 +2160,7 @@ bool gfc_check_access (gfc_access, gfc_access); ...@@ -2160,6 +2160,7 @@ bool gfc_check_access (gfc_access, gfc_access);
/* primary.c */ /* primary.c */
symbol_attribute gfc_variable_attr (gfc_expr *, gfc_typespec *); symbol_attribute gfc_variable_attr (gfc_expr *, gfc_typespec *);
symbol_attribute gfc_expr_attr (gfc_expr *); symbol_attribute gfc_expr_attr (gfc_expr *);
match gfc_match_rvalue (gfc_expr **);
/* trans.c */ /* trans.c */
void gfc_generate_code (gfc_namespace *); void gfc_generate_code (gfc_namespace *);
......
...@@ -153,7 +153,6 @@ match gfc_match_volatile (void); ...@@ -153,7 +153,6 @@ match gfc_match_volatile (void);
/* primary.c */ /* primary.c */
match gfc_match_structure_constructor (gfc_symbol *, gfc_expr **); match gfc_match_structure_constructor (gfc_symbol *, gfc_expr **);
match gfc_match_rvalue (gfc_expr **);
match gfc_match_variable (gfc_expr **, int); match gfc_match_variable (gfc_expr **, int);
match gfc_match_equiv_variable (gfc_expr **); match gfc_match_equiv_variable (gfc_expr **);
match gfc_match_actual_arglist (int, gfc_actual_arglist **); match gfc_match_actual_arglist (int, gfc_actual_arglist **);
......
...@@ -3204,6 +3204,70 @@ resolve_variable (gfc_expr *e) ...@@ -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 /* Resolve an expression. That is, make sure that types of operands agree
with their operators, intrinsic operators are converted to function calls with their operators, intrinsic operators are converted to function calls
for overloaded types and unresolved function references are resolved. */ for overloaded types and unresolved function references are resolved. */
...@@ -3223,13 +3287,16 @@ gfc_resolve_expr (gfc_expr *e) ...@@ -3223,13 +3287,16 @@ gfc_resolve_expr (gfc_expr *e)
break; break;
case EXPR_FUNCTION: case EXPR_FUNCTION:
t = resolve_function (e);
break;
case EXPR_VARIABLE: case EXPR_VARIABLE:
t = resolve_variable (e);
if (t == SUCCESS) if (check_host_association (e))
expression_rank (e); t = resolve_function (e);
else
{
t = resolve_variable (e);
if (t == SUCCESS)
expression_rank (e);
}
break; break;
case EXPR_SUBSTRING: case EXPR_SUBSTRING:
......
2007-05-12 Paul Thomas <pault@gcc.gnu.org>
PR fortran/30746
* gfortran.dg/host_assoc_function_1.f90: New test.
2007-05-11 Steve Ellcey <sje@cup.hp.com> 2007-05-11 Steve Ellcey <sje@cup.hp.com>
PR c++/31829 PR c++/31829
! { dg-do run }
! Tests the fix for the bug PR30746, in which the reference to 'x'
! in 'inner' wrongly host-associated with the variable 'x' rather
! than the function.
!
! Testcase is due to Malcolm Cohen, NAG.
!
real function z (i)
integer :: i
z = real (i)**i
end function
MODULE m
REAL :: x(3) = (/ 1.5, 2.5, 3.5 /)
interface
real function z (i)
integer :: i
end function
end interface
CONTAINS
SUBROUTINE s
if (x(2) .ne. 2.5) call abort ()
if (z(3) .ne. real (3)**3) call abort ()
CALL inner
CONTAINS
SUBROUTINE inner
i = 7
if (x(i, 7) .ne. real (7)**7) call abort ()
if (z(i, 7) .ne. real (7)**7) call abort ()
END SUBROUTINE
FUNCTION x(n, m)
x = REAL(n)**m
END FUNCTION
FUNCTION z(n, m)
z = REAL(n)**m
END FUNCTION
END SUBROUTINE
END MODULE
use m
call s()
end
! { dg-final { cleanup-modules "m" } }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment