This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]