This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Fortran, Patch] PR 31472 - PRIVATE/PUBLIC statement/attribute checking
- From: Tobias Burnus <burnus at net-b dot de>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>, "'fortran at gcc dot gnu dot org'" <fortran at gcc dot gnu dot org>
- Date: Wed, 11 Apr 2007 17:01:48 +0200
- Subject: [Fortran, Patch] PR 31472 - PRIVATE/PUBLIC statement/attribute checking
:ADDPATCH fortran:
Current gfortran does not support the PRIVATE/PUBLIC attribute for
compounds of derived types which is allowed since Fortran 2003.
The access-attribute for derived types (e.g. "type, public") was allowed
everywhere in modules (e.g. in a subroutine) and not only in the
specification part of a module.
In addition, the PRIVATE/PUBLIC statement could appear essentially
everwhere, however, PUBLIC/PRIVATE [[::] ids] is only allowed in the
module specification. (The "PRIVATE" statement is also allowed in the
derived type declaration in module specifications.)
Thanks to Michael Richmond for finding that access-specifications
statements are allowed in programs, functions and subroutines. This is
by the way related to the 2005-PR 20837 which is about the
access-specification attribute.
Regression tested on x86_64-unknown-linux-gnu with unix and unix/-m32
with no new failures.
Ok for the trunk?
In the standard:
Fortran 95
----------
4.4.1 Derived-type definition
5.1 Type declaration statements / 5.1.2.2 Accessibility attribute
5.2.3 Accessibility statements
Fortran 2003, see also:
------------
4.5.1 Derived-type definition
- New in Fortran 2003: components of a derived-type may have access-spec attributes
2007-04-11 Tobias Burnus <burnus@net-b.de>
PR fortran/31472
* decl.c (match_attr_spec): Allow PRIVATE/PUBLIC
attribute in type definitions.
(gfc_match_private): Allow PRIVATE statement only
in specification part of modules.
(gfc_match_public): Ditto for PUBLIC.
(gfc_match_derived_decl): Allow PRIVATE/PUBLIC attribute only in
specificification part of modules.
2007-04-11 Tobias Burnus <burnus@net-b.de>
PR fortran/31472
* gfortran.dg/access_spec_1.f90: New test.
* gfortran.dg/access_spec_2.f90: New test.
* gfortran.dg/non_module_public.f90: Match new error message.
Index: gcc/fortran/decl.c
===================================================================
*** gcc/fortran/decl.c (revision 123715)
--- gcc/fortran/decl.c (working copy)
*************** match_attr_spec (void)
*** 2292,2304 ****
if (gfc_current_state () == COMP_DERIVED
&& d != DECL_DIMENSION && d != DECL_POINTER
! && d != DECL_COLON && d != DECL_NONE)
{
if (d == DECL_ALLOCATABLE)
{
if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: ALLOCATABLE "
"attribute at %C in a TYPE definition")
! == FAILURE)
{
m = MATCH_ERROR;
goto cleanup;
--- 2292,2305 ----
if (gfc_current_state () == COMP_DERIVED
&& d != DECL_DIMENSION && d != DECL_POINTER
! && d != DECL_COLON && d != DECL_PRIVATE
! && d != DECL_PUBLIC && d != DECL_NONE)
{
if (d == DECL_ALLOCATABLE)
{
if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: ALLOCATABLE "
"attribute at %C in a TYPE definition")
! == FAILURE)
{
m = MATCH_ERROR;
goto cleanup;
*************** match_attr_spec (void)
*** 2307,2313 ****
else
{
gfc_error ("Attribute at %L is not allowed in a TYPE definition",
! &seen_at[d]);
m = MATCH_ERROR;
goto cleanup;
}
--- 2308,2314 ----
else
{
gfc_error ("Attribute at %L is not allowed in a TYPE definition",
! &seen_at[d]);
m = MATCH_ERROR;
goto cleanup;
}
*************** match_attr_spec (void)
*** 2320,2330 ****
attr = "PRIVATE";
else
attr = "PUBLIC";
!
! gfc_error ("%s attribute at %L is not allowed outside of a MODULE",
! attr, &seen_at[d]);
! m = MATCH_ERROR;
! goto cleanup;
}
switch (d)
--- 2321,2346 ----
attr = "PRIVATE";
else
attr = "PUBLIC";
! if (gfc_current_state () == COMP_DERIVED
! && gfc_state_stack->previous
! && gfc_state_stack->previous->state == COMP_MODULE)
! {
! if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: Attribute %s "
! "at %L in a TYPE definition", attr,
! &seen_at[d])
! == FAILURE)
! {
! m = MATCH_ERROR;
! goto cleanup;
! }
! }
! else
! {
! gfc_error ("%s attribute at %L is not allowed outside of the "
! "specification part of a module", attr, &seen_at[d]);
! m = MATCH_ERROR;
! goto cleanup;
! }
}
switch (d)
*************** gfc_match_private (gfc_statement *st)
*** 3916,3921 ****
--- 3932,3947 ----
if (gfc_match ("private") != MATCH_YES)
return MATCH_NO;
+ if (gfc_current_state () != COMP_MODULE
+ && (gfc_current_state () != COMP_DERIVED
+ || !gfc_state_stack->previous
+ || gfc_state_stack->previous->state != COMP_MODULE))
+ {
+ gfc_error ("PRIVATE statement at %C is only allowed in the "
+ "specification part of a module");
+ return MATCH_ERROR;
+ }
+
if (gfc_current_state () == COMP_DERIVED)
{
if (gfc_match_eos () == MATCH_YES)
*************** gfc_match_public (gfc_statement *st)
*** 3946,3951 ****
--- 3972,3984 ----
if (gfc_match ("public") != MATCH_YES)
return MATCH_NO;
+ if (gfc_current_state () != COMP_MODULE)
+ {
+ gfc_error ("PUBLIC statement at %C is only allowed in the "
+ "specification part of a module");
+ return MATCH_ERROR;
+ }
+
if (gfc_match_eos () == MATCH_YES)
{
*st = ST_PUBLIC;
*************** gfc_match_derived_decl (void)
*** 4315,4323 ****
loop:
if (gfc_match (" , private") == MATCH_YES)
{
! if (gfc_find_state (COMP_MODULE) == FAILURE)
{
! gfc_error ("Derived type at %C can only be PRIVATE within a MODULE");
return MATCH_ERROR;
}
--- 4348,4357 ----
loop:
if (gfc_match (" , private") == MATCH_YES)
{
! if (gfc_current_state () != COMP_MODULE)
{
! gfc_error ("Derived type at %C can only be PRIVATE in the "
! "specification part of a module");
return MATCH_ERROR;
}
*************** loop:
*** 4328,4336 ****
if (gfc_match (" , public") == MATCH_YES)
{
! if (gfc_find_state (COMP_MODULE) == FAILURE)
{
! gfc_error ("Derived type at %C can only be PUBLIC within a MODULE");
return MATCH_ERROR;
}
--- 4362,4371 ----
if (gfc_match (" , public") == MATCH_YES)
{
! if (gfc_current_state () != COMP_MODULE)
{
! gfc_error ("Derived type at %C can only be PUBLIC in the "
! "specification part of a module");
return MATCH_ERROR;
}
Index: gcc/testsuite/gfortran.dg/access_spec_1.f90
===================================================================
*** gcc/testsuite/gfortran.dg/access_spec_1.f90 (revision 0)
--- gcc/testsuite/gfortran.dg/access_spec_1.f90 (revision 0)
***************
*** 0 ****
--- 1,18 ----
+ ! { dg-do compile }
+ ! PR fortran/31472
+ ! Access specifications: Valid Fortran 2003 code
+ module mod
+ implicit none
+ private
+ integer, public :: i
+ integer, private :: z
+ integer :: j, x
+ private :: j
+ public :: x
+ type, public :: bar
+ PRIVATE
+ integer, public :: y ! Fortran 2003
+ integer, private :: z ! Fortran 2003
+ end type
+ end module
+ ! { dg-final { cleanup-modules "mod" } }
Index: gcc/testsuite/gfortran.dg/access_spec_2.f90
===================================================================
*** gcc/testsuite/gfortran.dg/access_spec_2.f90 (revision 0)
--- gcc/testsuite/gfortran.dg/access_spec_2.f90 (revision 0)
***************
*** 0 ****
--- 1,40 ----
+ ! { dg-do compile }
+ ! { dg-options "-std=f95" }
+ ! PR fortran/31472
+ ! Access specifications: Invalid Fortran 95 code
+
+ module test
+ implicit none
+ integer, public :: x
+ public :: x ! { dg-error "was already specified" }
+ private :: x ! { dg-error "was already specified" }
+ end module test
+
+ module mod
+ implicit none
+ private
+ type, public :: bar
+ PRIVATE
+ integer, public :: y ! { dg-error "Fortran 2003: Attribute PUBLIC" }
+ integer, public :: z ! { dg-error "Fortran 2003: Attribute PUBLIC" }
+ end type ! { dg-error "Derived type definition at" }
+ contains
+ subroutine foo
+ integer :: x
+ private :: x ! { dg-error "only allowed in the specification part of a module" }
+ type, private :: t ! { dg-error "only be PRIVATE in the specification part of a module" }
+ integer :: z
+ end type t ! { dg-error "Expecting END SUBROUTINE statement" }
+ type :: ttt
+ integer,public :: z ! { dg-error "not allowed outside of the specification part of a module" }
+ end type ttt ! { dg-error "Derived type definition at" }
+ end subroutine
+ end module
+
+ program x
+ implicit none
+ integer :: i
+ public :: i ! { dg-error "only allowed in the specification part of a module" }
+ integer,public :: j ! { dg-error "not allowed outside of the specification part of a module" }
+ end program x
+ ! { dg-final { cleanup-modules "test mod" } }
Index: gcc/testsuite/gfortran.dg/non_module_public.f90
===================================================================
*** gcc/testsuite/gfortran.dg/non_module_public.f90 (revision 123712)
--- gcc/testsuite/gfortran.dg/non_module_public.f90 (working copy)
***************
*** 1,5 ****
! { dg-do compile }
! PR20837 - A symbol may not be declared PUBLIC or PRIVATE outside a module.
! Contributed by Joost VandeVondele <jv244@cam.ac.uk>
! integer, parameter, public :: i=1 ! { dg-error "allowed outside of a MODULE" }
END
--- 1,5 ----
! { dg-do compile }
! PR20837 - A symbol may not be declared PUBLIC or PRIVATE outside a module.
! Contributed by Joost VandeVondele <jv244@cam.ac.uk>
! integer, parameter, public :: i=1 ! { dg-error "outside of the specification part of a module" }
END