Dear All,

On 24 July 2015 at 10:08, Damian Rouson <dam...@sourceryinstitute.org> wrote:
> I love this idea and had similar thoughts as well.
>
> :D
>
> Sent from my iPhone
>
>> On Jul 24, 2015, at 1:06 AM, Paul Richard Thomas 
>> <paul.richard.tho...@gmail.com> wrote:
>>
>> Dear Mikael,
>>
>> It had crossed my mind also that a .mod and a .smod file could be
>> written. Normally, the .smod files are produced by the submodules
>> themselves, so that their descendants can pick up the symbols that
>> they generate. There is no reason at all why this could not be
>> implemented; early on in the development I did just this, although I
>> think that it would now be easier to modify this patch.
>>
>> One huge advantage of proceeding in this way is that any resulting
>> library can be distributed with the .mod file alone so that the
>> private entities are never exposed. The penalty is that a second file
>> is output.
>>
>> With best regards
>>
>> Paul
>>

Please find attached the implementation of this suggestion.

Bootstraps and regtests on FC21/x86_64 - OK for trunk or is the
original preferred?

Cheers

Paul

2015-07-29  Paul Thomas  <pa...@gcc.gnu.org>

    PR fortran/52846
    * module.c (check_access): Return true if new static flag
    'dump_smod' is true..
    (gfc_dump_module): Rename original 'dump_module' and call from
    new version. Use 'dump_smod' rather than the stack state to
    determine if a submodule is being processed. The new version of
    this procedure sets 'dump_smod' depending on the stack state and
    then writes both the mod and smod files if a module is being
    processed or just the smod for a submodule.
    (gfc_use_module): Eliminate the check for module_name and
    submodule_name being the same.
    * trans-decl.c (gfc_finish_var_decl, gfc_build_qualified_array,
    get_proc_pointer_decl): Set TREE_PUBLIC unconditionally and use
    the conditions to set DECL_VISIBILITY as hidden and to set as
    true DECL_VISIBILITY_SPECIFIED.

2015-07-29  Paul Thomas  <pa...@gcc.gnu.org>

    PR fortran/52846

    * lib/fortran-modules.exp: Call cleanup-submodules from
    cleanup-modules.
    * gfortran.dg/public_private_module_2.f90: Add two XFAILS to
    cover the cases where private entities are no longer optimized
    away.
    * gfortran.dg/public_private_module_6.f90: Add an XFAIL for the
    same reason.
    * gfortran.dg/submodule_1.f08: Change cleanup module names.
    * gfortran.dg/submodule_5.f08: The same.
    * gfortran.dg/submodule_9.f08: The same.
    * gfortran.dg/submodule_10.f08: New test
Index: gcc/fortran/module.c
===================================================================
*** gcc/fortran/module.c        (revision 226054)
--- gcc/fortran/module.c        (working copy)
*************** read_module (void)
*** 5283,5291 ****
--- 5283,5296 ----
     PRIVATE, then private, and otherwise it is public unless the default
     access in this context has been declared PRIVATE.  */

+ static bool dump_smod = false;
+
  static bool
  check_access (gfc_access specific_access, gfc_access default_access)
  {
+   if (dump_smod)
+     return true;
+
    if (specific_access == ACCESS_PUBLIC)
      return TRUE;
    if (specific_access == ACCESS_PRIVATE)
*************** read_crc32_from_module_file (const char*
*** 5961,5968 ****
     processing the module, dump_flag will be set to zero and we delete
     the module file, even if it was already there.  */

! void
! gfc_dump_module (const char *name, int dump_flag)
  {
    int n;
    char *filename, *filename_tmp;
--- 5966,5973 ----
     processing the module, dump_flag will be set to zero and we delete
     the module file, even if it was already there.  */

! static void
! dump_module (const char *name, int dump_flag)
  {
    int n;
    char *filename, *filename_tmp;
*************** gfc_dump_module (const char *name, int d
*** 5970,5976 ****

    module_name = gfc_get_string (name);

!   if (gfc_state_stack->state == COMP_SUBMODULE)
      {
        name = submodule_name;
        n = strlen (name) + strlen (SUBMODULE_EXTENSION) + 1;
--- 5975,5981 ----

    module_name = gfc_get_string (name);

!   if (dump_smod)
      {
        name = submodule_name;
        n = strlen (name) + strlen (SUBMODULE_EXTENSION) + 1;
*************** gfc_dump_module (const char *name, int d
*** 5991,5997 ****
        strcpy (filename, name);
      }

!   if (gfc_state_stack->state == COMP_SUBMODULE)
      strcat (filename, SUBMODULE_EXTENSION);
    else
    strcat (filename, MODULE_EXTENSION);
--- 5996,6002 ----
        strcpy (filename, name);
      }

!   if (dump_smod)
      strcat (filename, SUBMODULE_EXTENSION);
    else
    strcat (filename, MODULE_EXTENSION);
*************** gfc_dump_module (const char *name, int d
*** 6060,6065 ****
--- 6065,6091 ----
  }


+ void
+ gfc_dump_module (const char *name, int dump_flag)
+ {
+   if (gfc_state_stack->state == COMP_SUBMODULE)
+     dump_smod = true;
+   else
+     dump_smod =false;
+
+   dump_module (name, dump_flag);
+
+   if (dump_smod)
+     return;
+
+   /* Write a submodule file from a module.  The 'dump_smod' flag switches
+      off the check for PRIVATE entities.  */
+   dump_smod = true;
+   submodule_name = module_name;
+   dump_module (name, dump_flag);
+   dump_smod = false;
+ }
+
  static void
  create_intrinsic_function (const char *name, int id,
                           const char *modname, intmod_id module,
*************** gfc_use_module (gfc_use_list *module)
*** 6754,6761 ****
                     "USE statement at %C has no ONLY qualifier");

    if (gfc_state_stack->state == COMP_MODULE
!       || module->submodule_name == NULL
!       || strcmp (module_name, module->submodule_name) == 0)
      {
        filename = XALLOCAVEC (char, strlen (module_name)
                                   + strlen (MODULE_EXTENSION) + 1);
--- 6780,6786 ----
                     "USE statement at %C has no ONLY qualifier");

    if (gfc_state_stack->state == COMP_MODULE
!       || module->submodule_name == NULL)
      {
        filename = XALLOCAVEC (char, strlen (module_name)
                                   + strlen (MODULE_EXTENSION) + 1);
Index: gcc/fortran/trans-decl.c
===================================================================
*** gcc/fortran/trans-decl.c    (revision 226054)
--- gcc/fortran/trans-decl.c    (working copy)
*************** gfc_finish_var_decl (tree decl, gfc_symb
*** 596,601 ****
--- 596,606 ----
         both, of course.) (J3/04-007, section 15.3).  */
        TREE_PUBLIC(decl) = 1;
        DECL_COMMON(decl) = 1;
+       if (sym->attr.access == ACCESS_PRIVATE && !sym->attr.public_used)
+       {
+         DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+         DECL_VISIBILITY_SPECIFIED (decl) = true;
+       }
      }

    /* If a variable is USE associated, it's always external.  */
*************** gfc_finish_var_decl (tree decl, gfc_symb
*** 609,617 ****
        /* TODO: Don't set sym->module for result or dummy variables.  */
        gcc_assert (current_function_decl == NULL_TREE || sym->result == sym);

-       if (sym->attr.access != ACCESS_PRIVATE || sym->attr.public_used)
        TREE_PUBLIC (decl) = 1;
        TREE_STATIC (decl) = 1;
      }

    /* Derived types are a bit peculiar because of the possibility of
--- 614,626 ----
        /* TODO: Don't set sym->module for result or dummy variables.  */
        gcc_assert (current_function_decl == NULL_TREE || sym->result == sym);

        TREE_PUBLIC (decl) = 1;
        TREE_STATIC (decl) = 1;
+       if (sym->attr.access == ACCESS_PRIVATE && !sym->attr.public_used)
+       {
+         DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+         DECL_VISIBILITY_SPECIFIED (decl) = true;
+       }
      }

    /* Derived types are a bit peculiar because of the possibility of
*************** gfc_build_qualified_array (tree decl, gf
*** 837,845 ****
          else
            TREE_STATIC (token) = 1;

-         if (sym->attr.use_assoc || sym->attr.access != ACCESS_PRIVATE ||
-             sym->attr.public_used)
            TREE_PUBLIC (token) = 1;
        }
        else
        {
--- 846,858 ----
          else
            TREE_STATIC (token) = 1;

          TREE_PUBLIC (token) = 1;
+
+         if (sym->attr.access == ACCESS_PRIVATE && !sym->attr.public_used)
+           {
+             DECL_VISIBILITY (token) = VISIBILITY_HIDDEN;
+             DECL_VISIBILITY_SPECIFIED (token) = true;
+           }
        }
        else
        {
*************** get_proc_pointer_decl (gfc_symbol *sym)
*** 1747,1755 ****
    else if (sym->module && sym->ns->proc_name->attr.flavor == FL_MODULE)
      {
        /* This is the declaration of a module variable.  */
-       if (sym->ns->proc_name->attr.flavor == FL_MODULE
-         && (sym->attr.access != ACCESS_PRIVATE || sym->attr.public_used))
        TREE_PUBLIC (decl) = 1;
        TREE_STATIC (decl) = 1;
      }

--- 1760,1771 ----
    else if (sym->module && sym->ns->proc_name->attr.flavor == FL_MODULE)
      {
        /* This is the declaration of a module variable.  */
        TREE_PUBLIC (decl) = 1;
+       if (sym->attr.access == ACCESS_PRIVATE && !sym->attr.public_used)
+       {
+         DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+         DECL_VISIBILITY_SPECIFIED (decl) = true;
+       }
        TREE_STATIC (decl) = 1;
      }

Index: gcc/testsuite/lib/fortran-modules.exp
===================================================================
*** gcc/testsuite/lib/fortran-modules.exp       (revision 226054)
--- gcc/testsuite/lib/fortran-modules.exp       (working copy)
***************
*** 17,22 ****
--- 17,23 ----
  # helper to deal with fortran modules

  # Remove files for specified Fortran modules.
+ # This includes both .mod and .smod files.
  proc cleanup-modules { modlist } {
      global clean
      foreach mod [concat $modlist $clean] {
*************** proc cleanup-modules { modlist } {
*** 27,32 ****
--- 28,34 ----
        }
        remote_file build delete $m
      }
+     cleanup-submodules $modlist
  }

  # Remove files for specified Fortran submodules.
Index: gcc/testsuite/gfortran.dg/public_private_module_2.f90
===================================================================
*** gcc/testsuite/gfortran.dg/public_private_module_2.f90       (revision 
226054)
--- gcc/testsuite/gfortran.dg/public_private_module_2.f90       (working copy)
***************
*** 18,29 ****
          integer, bind(C,name='') :: qq
        end module mod

        ! { dg-final { scan-assembler "__mod_MOD_aa" } }
!       ! { dg-final { scan-assembler-not "iii" } }
        ! { dg-final { scan-assembler "jj" } }
        ! { dg-final { scan-assembler "lll" } }
        ! { dg-final { scan-assembler-not "kk" } }
!       ! { dg-final { scan-assembler-not "mmmm" } }
        ! { dg-final { scan-assembler "nnn" } }
        ! { dg-final { scan-assembler "oo" } }
        ! { dg-final { scan-assembler "__mod_MOD_qq" } }
--- 18,32 ----
          integer, bind(C,name='') :: qq
        end module mod

+ ! The two xfails below have appeared with the introduction of submodules. 
'iii' and
+ ! 'mmm' now are TREE_PUBLIC but has DECL_VISIBILITY (decl) = 
VISIBILITY_HIDDEN set.
+
        ! { dg-final { scan-assembler "__mod_MOD_aa" } }
!       ! { dg-final { scan-assembler-not "iii" { xfail *-*-* } } }
        ! { dg-final { scan-assembler "jj" } }
        ! { dg-final { scan-assembler "lll" } }
        ! { dg-final { scan-assembler-not "kk" } }
!       ! { dg-final { scan-assembler-not "mmmm" { xfail *-*-* } } }
        ! { dg-final { scan-assembler "nnn" } }
        ! { dg-final { scan-assembler "oo" } }
        ! { dg-final { scan-assembler "__mod_MOD_qq" } }
Index: gcc/testsuite/gfortran.dg/public_private_module_6.f90
===================================================================
*** gcc/testsuite/gfortran.dg/public_private_module_6.f90       (revision 
226054)
--- gcc/testsuite/gfortran.dg/public_private_module_6.f90       (working copy)
*************** module m
*** 11,14 ****
    integer, save :: aaaa
  end module m

! ! { dg-final { scan-assembler-not "aaaa" } }
--- 11,17 ----
    integer, save :: aaaa
  end module m

! ! The xfail below has appeared with the introduction of submodules. 'aaaa'
! ! now is TREE_PUBLIC but has DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN set.
!
! ! { dg-final { scan-assembler-not "aaaa" { xfail *-*-* } } }
Index: gcc/testsuite/gfortran.dg/submodule_1.f08
===================================================================
*** gcc/testsuite/gfortran.dg/submodule_1.f08   (revision 226054)
--- gcc/testsuite/gfortran.dg/submodule_1.f08   (working copy)
***************
*** 170,175 ****
       message2 = ""
     end subroutine
   end program
! ! { dg-final { cleanup-submodules "foo_interface_son" } }
! ! { dg-final { cleanup-submodules "foo_interface_grandson" } }
! ! { dg-final { cleanup-submodules "foo_interface_daughter" } }
--- 170,175 ----
       message2 = ""
     end subroutine
   end program
! ! { dg-final { cleanup-submodules "foo_interface@foo_interface_son" } }
! ! { dg-final { cleanup-submodules "foo_interface@foo_interface_grandson" } }
! ! { dg-final { cleanup-submodules "foo_interface@foo_interface_daughter" } }
Index: gcc/testsuite/gfortran.dg/submodule_10.f08
===================================================================
*** gcc/testsuite/gfortran.dg/submodule_10.f08  (revision 0)
--- gcc/testsuite/gfortran.dg/submodule_10.f08  (working copy)
***************
*** 0 ****
--- 1,170 ----
+ ! { dg-do compile }
+ !
+ ! Checks that PRIVATE enities are visible to submodules.
+ !
+ ! Contributed by Salvatore Filippone  <salvatore.filipp...@uniroma2.it>
+ !
+ module const_mod
+   integer, parameter  :: ndig=8
+   integer, parameter  :: ipk_ = selected_int_kind(ndig)
+   integer, parameter  :: longndig=12
+   integer, parameter  :: long_int_k_ = selected_int_kind(longndig)
+   integer, parameter  :: mpik_ = kind(1)
+
+   integer(ipk_), parameter, public :: success_=0
+
+ end module const_mod
+
+
+ module error_mod
+   use const_mod
+
+   integer(ipk_), parameter, public :: act_ret_=0
+   integer(ipk_), parameter, public :: act_print_=1
+   integer(ipk_), parameter, public :: act_abort_=2
+
+   integer(ipk_), parameter, public ::  no_err_ = 0
+
+   public error, errcomm, get_numerr, &
+        & error_handler, &
+        & ser_error_handler, par_error_handler
+
+
+   interface error_handler
+     module subroutine ser_error_handler(err_act)
+       integer(ipk_), intent(inout) ::  err_act
+     end subroutine ser_error_handler
+     module subroutine par_error_handler(ictxt,err_act)
+       integer(mpik_), intent(in) ::  ictxt
+       integer(ipk_), intent(in) ::  err_act
+     end subroutine par_error_handler
+   end interface
+
+   interface error
+     module subroutine serror()
+     end subroutine serror
+     module subroutine perror(ictxt,abrt)
+       integer(mpik_), intent(in) ::  ictxt
+       logical, intent(in), optional  :: abrt
+     end subroutine perror
+   end interface
+
+
+   interface error_print_stack
+     module subroutine par_error_print_stack(ictxt)
+       integer(mpik_), intent(in) ::  ictxt
+     end subroutine par_error_print_stack
+     module subroutine ser_error_print_stack()
+     end subroutine ser_error_print_stack
+   end interface
+
+   interface errcomm
+     module subroutine errcomm(ictxt, err)
+       integer(mpik_), intent(in)   :: ictxt
+       integer(ipk_), intent(inout):: err
+     end subroutine errcomm
+   end interface errcomm
+
+
+   private
+
+   type errstack_node
+
+     integer(ipk_) ::   err_code=0
+     character(len=20)        ::   routine=''
+     integer(ipk_),dimension(5)     ::   i_err_data=0
+     character(len=40)        ::   a_err_data=''
+     type(errstack_node), pointer :: next
+
+   end type errstack_node
+
+
+   type errstack
+     type(errstack_node), pointer :: top => null()
+     integer(ipk_) :: n_elems=0
+   end type errstack
+
+
+   type(errstack), save  :: error_stack
+   integer(ipk_), save   :: error_status    = no_err_
+   integer(ipk_), save   :: verbosity_level = 1
+   integer(ipk_), save   :: err_action      = act_abort_
+   integer(ipk_), save   :: debug_level     = 0, debug_unit, 
serial_debug_level=0
+
+ contains
+ end module error_mod
+
+ submodule (error_mod) error_impl_mod
+   use const_mod
+ contains
+   ! checks whether an error has occurred on one of the processes in the 
execution pool
+   subroutine errcomm(ictxt, err)
+     integer(mpik_), intent(in)   :: ictxt
+     integer(ipk_), intent(inout):: err
+
+
+   end subroutine errcomm
+
+   subroutine ser_error_handler(err_act)
+     implicit none
+     integer(ipk_), intent(inout) ::  err_act
+
+     if (err_act /= act_ret_)     &
+          &  call error()
+     if (err_act == act_abort_) stop
+
+     return
+   end subroutine ser_error_handler
+
+   subroutine par_error_handler(ictxt,err_act)
+     implicit none
+     integer(mpik_), intent(in) ::  ictxt
+     integer(ipk_), intent(in) ::  err_act
+
+     if (err_act == act_print_)     &
+          &  call error(ictxt, abrt=.false.)
+     if (err_act == act_abort_)      &
+          &  call error(ictxt, abrt=.true.)
+
+     return
+
+   end subroutine par_error_handler
+
+   subroutine par_error_print_stack(ictxt)
+     integer(mpik_), intent(in) ::  ictxt
+
+     call error(ictxt, abrt=.false.)
+
+   end subroutine par_error_print_stack
+
+   subroutine ser_error_print_stack()
+
+     call error()
+   end subroutine ser_error_print_stack
+
+   subroutine serror()
+
+     implicit none
+
+   end subroutine serror
+
+   subroutine perror(ictxt,abrt)
+     use const_mod
+     implicit none
+     integer(mpik_), intent(in) :: ictxt
+     logical, intent(in), optional  :: abrt
+
+   end subroutine perror
+
+ end submodule error_impl_mod
+
+ program testlk
+   use error_mod
+   implicit none
+
+   call error()
+
+   stop
+ end program testlk
+ ! { dg-final { cleanup-submodules "error_mod@error_impl_mod" } }
+
Index: gcc/testsuite/gfortran.dg/submodule_5.f08
===================================================================
*** gcc/testsuite/gfortran.dg/submodule_5.f08   (revision 226054)
--- gcc/testsuite/gfortran.dg/submodule_5.f08   (working copy)
*************** contains
*** 49,51 ****
--- 49,52 ----
  end SUBMODULE foo_interface_daughter

  end
+ ! { dg-final { cleanup-submodules "foo_interface@foo_interface_daughter" } }
Index: gcc/testsuite/gfortran.dg/submodule_9.f08
===================================================================
*** gcc/testsuite/gfortran.dg/submodule_9.f08   (revision 226054)
--- gcc/testsuite/gfortran.dg/submodule_9.f08   (working copy)
*************** program a_s
*** 38,40 ****
--- 38,41 ----
    implicit none
    call p()
  end program
+ ! { dg-final { cleanup-submodules "mod_a@b" } }

Reply via email to