This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Patch, fortran] PR87127 - External function not recognised from within an associate block
- From: Paul Richard Thomas <paul dot richard dot thomas at gmail dot com>
- To: "fortran at gcc dot gnu dot org" <fortran at gcc dot gnu dot org>, gcc-patches <gcc-patches at gcc dot gnu dot org>
- Cc: gscfq at t-online dot de
- Date: Sat, 30 Mar 2019 12:40:19 +0000
- Subject: [Patch, fortran] PR87127 - External function not recognised from within an associate block
This patch is pretty self-explanatory. I have checked that a sensible
errors are given if 'exfunc' in the testcase is referenced if it is a
variable.
Bootstrapped and regtested on FC29/x86_64 - OK for trunk?
Paul
2019-03-30 Paul Thomas <pault@gcc.gnu.org>
PR fortran/87127
* resolve.c (check_host_association): If an external function
is typed but not declared explicitly to be external, change the
old symbol from a variable to an external function.
2019-03-30 Paul Thomas <pault@gcc.gnu.org>
PR fortran/87127
* gfortran.dg/external_procedures_4.f90: New test.
Index: gcc/fortran/resolve.c
===================================================================
*** gcc/fortran/resolve.c (revision 269160)
--- gcc/fortran/resolve.c (working copy)
*************** resolve_procedure:
*** 5615,5625 ****
/* 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, change the symbol in the expression
! and convert the array reference into an actual arglist if the old
! symbol is a variable. */
static bool
check_host_association (gfc_expr *e)
{
--- 5615,5628 ----
/* Checks to see that the correct symbol has been host associated.
! The only situations where this arises are:
! (i) That in which a twice contained function is parsed after
! the host association is made. On detecting this, change
! the symbol in the expression and convert the array reference
! into an actual arglist if the old symbol is a variable; or
! (ii) That in which an external function is typed but not declared
! explicitly to be external. Here, the old symbol is changed
! from a variable to an external function. */
static bool
check_host_association (gfc_expr *e)
{
*************** check_host_association (gfc_expr *e)
*** 5709,5714 ****
--- 5712,5737 ----
gfc_resolve_expr (e);
sym->refs++;
}
+ /* This case corresponds to a call, from a block or a contained
+ procedure, to an external function, which has not been declared
+ as being external in the main program but has been typed. */
+ else if (sym && old_sym != sym
+ && !e->ref
+ && sym->ts.type == BT_UNKNOWN
+ && old_sym->ts.type != BT_UNKNOWN
+ && sym->attr.flavor == FL_PROCEDURE
+ && old_sym->attr.flavor == FL_VARIABLE
+ && sym->ns->parent == old_sym->ns
+ && sym->ns->proc_name
+ && (sym->ns->proc_name->attr.flavor == FL_LABEL
+ || sym->ns->proc_name->attr.flavor == FL_PROCEDURE))
+ {
+ old_sym->attr.flavor = FL_PROCEDURE;
+ old_sym->attr.external = 1;
+ old_sym->attr.function = 1;
+ old_sym->result = old_sym;
+ gfc_resolve_expr (e);
+ }
}
/* This might have changed! */
return e->expr_type == EXPR_FUNCTION;
Index: gcc/testsuite/gfortran.dg/external_procedures_4.f90
===================================================================
*** gcc/testsuite/gfortran.dg/external_procedures_4.f90 (nonexistent)
--- gcc/testsuite/gfortran.dg/external_procedures_4.f90 (working copy)
***************
*** 0 ****
--- 1,28 ----
+ ! { dg-do run }
+ !
+ ! Test the fix for PR87127 in which the references to exfunc cause
+ ! the error "‘exfunc’ at (1) is not a function".
+ !
+ ! Contributed by Gerhard Steinmetz <gscfq@t-online.de>
+ !
+ function exfunc(i)
+ implicit none
+ integer :: exfunc,i
+ exfunc = 2*i
+ end function
+
+ ! contents of test.f90
+ program test
+ implicit none
+ integer :: exfunc,i
+ integer,parameter :: array(2)=[6,7]
+ associate(i=>array(2)) ! Original bug
+ if (exfunc(i) .ne. 2*i) stop 1
+ end associate
+ i = 99
+ call foo
+ contains
+ subroutine foo() ! Comment #3
+ if (exfunc(i) .ne. 2*i) stop 2
+ end subroutine foo
+ end program