Please consider the following code: module m implicit none private public :: public_t public :: public_sub !public :: private_t (*) type :: private_t integer :: i end type type :: public_t type(private_t), pointer :: public_comp_with_private_type !(#1) procedure(ifc) , nopass, pointer :: ppc end type abstract interface integer function ifc () end function end interface type(private_t), save, public :: public_var_with_private_type !(#2) contains subroutine public_sub(arg) !(#3) type(private_t) :: arg end subroutine end module m program test use m implicit none type(public_t) :: x integer :: j print *,public_var_with_private_type%i j = x%ppc() ! Error: Can't convert UNKNOWN to INTEGER(4) end With current trunk versions of gfortran, this produces the error indicated in the last line of the program. Of course this error is bogus, since ppc has an explicit interface (with an integer return type). However, I believe this program is invalid for the following reason: The type 'public_t' is public in the module m, and it has a public component, indicated by (#1), whose type is private in the module. So this component is accessible outside of the module, but its type is not. Up to now I was not able to find a rule in the F03 Standard, which explicitly forbids this. But my common sense tells me that it should be invalid (hoping my common sense works alright). Following the same reasoning, the cases (#2) and (#3) should be invalid, too, but none of them is detected by gfortran. Unfortunately, I could not find any other compiler which rejects the program (ifort and g95 accept it). Still I think it is invalid. If the line indicated by (*) is uncommented, the error message goes away. With this modification the program should be valid, and all is fine. Thanks to Juergen Reuter for reporting this.
Without heavily thinking about it: > print *,public_var_with_private_type%i Seems to be valid in Fortran 2003 (but not in 2003). The components are not PRIVATE and thus accessibly, even if the TYPE declaration is not accessible. (I think one only needs the TYPE to declare new variables of this type not to access components of existing entities of that type.) > j = x%ppc() Seems to be valid: The PPC has an explicit interface and thus there is no need for implicit typing. Thus I would reason that g95, ifort and NAG (assuming Juergen Reuter is using it) are correct in accepting it. -- I can try to find it in the standard, but it is not a simple constraint which one can find but it is rather written between the lines.
> Thus I would reason that g95, ifort and NAG (assuming Juergen Reuter is using > it) are correct in accepting it. NAG indeed accepts it with -f2003. With -f95 it reports Extension: c0.f90, line 32: Dummy ARG of PUBLIC_SUB exposes PRIVATE type PRIVATE_T detected at M@<end-of-statement> Extension: c0.f90, line 32: Variable PUBLIC_VAR_WITH_PRIVATE_TYPE exposes PRIVATE type PRIVATE_T detected at M@<end-of-statement> Extension: c0.f90, line 32: Component PUBLIC_COMP_WITH_PRIVATE_TYPE of type PUBLIC_T exposes PRIVATE type PRIVATE_T detected at M@<end-of-statement> Probably it is really valid in F2003, and my common sense just failed. I will try to fix gfortran's bogus error.
Actually gfortran even has the same check as NAG that rejects a private type as component of a public type with -std=f95. And it happens that the bug which leads to the bogus error message lies just in this check. Thus the fix is easy: Index: gcc/fortran/resolve.c =================================================================== --- gcc/fortran/resolve.c (revision 147349) +++ gcc/fortran/resolve.c (working copy) @@ -9088,11 +9088,11 @@ resolve_fl_derived (gfc_symbol *sym) && !gfc_check_access (c->ts.derived->attr.access, c->ts.derived->ns->default_access)) { - gfc_notify_std (GFC_STD_F2003, "Fortran 2003: the component '%s' " + if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: the component '%s' " "is a PRIVATE type and cannot be a component of " "'%s', which is PUBLIC at %L", c->name, - sym->name, &sym->declared_at); - return FAILURE; + sym->name, &sym->declared_at) == FAILURE) + return FAILURE; } if (sym->attr.sequence)
> && !gfc_check_access (c->ts.derived->attr.access, > c->ts.derived->ns->default_access)) > { > - gfc_notify_std (GFC_STD_F2003, "Fortran 2003: the component '%s' " > + if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: the component '%s' > " Or shorter: if (.... && !gfc_check_access && gfc_notify_std (...) == FAILURE) return FAILURE; saves a { } pair and some indentation
Subject: Bug 40089 Author: janus Date: Mon May 11 14:14:38 2009 New Revision: 147379 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=147379 Log: 2009-05-11 Janus Weil <janus@gcc.gnu.org> PR fortran/40089 * resolve.c (resolve_fl_derived): Only return FAILURE if gfc_notify_std fails. 2009-05-11 Janus Weil <janus@gcc.gnu.org> PR fortran/40089 * gfortran.dg/proc_ptr_comp_7.f90: New. Added: trunk/gcc/testsuite/gfortran.dg/proc_ptr_comp_7.f90 Modified: trunk/gcc/fortran/ChangeLog trunk/gcc/fortran/resolve.c trunk/gcc/testsuite/ChangeLog
Fixed with r147379. Closing.