Dear All,
On 24 July 2015 at 10:08, Damian Rouson <[email protected]> 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
>> <[email protected]> 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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
+ !
+ 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" } }