[Bug fortran/52846] [F2008] Support submodules - part 2/3 - redux
Paul Richard Thomas
paul.richard.thomas@gmail.com
Thu Jul 16 15:08:00 GMT 2015
Dear Reinhold, dear all,
Please find attached a new version of the patch that fixes the
inconsistency with the standard, pointed out by Reinhold. It is weird
but a read the appropriate part of the standard several times and
simply did not pick up the critical information :-)
Note that the delimiter used for submodule file name is '@', whereas
the internal identifiers is '.'.
I have added a procedure to cleanup submodules produced by the
testsuite and implemented them in submodule_[1-8].f90. Submodule_8.f90
tests the resolution of the spurious error found by Reinhold.
Booststraps and regtests on FC_21/x86_64 - OK for trunk?
Paul
2015-07-16 Paul Thomas <pault@gcc.gnu.org>
PR fortran/52846
* decl.c (gfc_match_end): Pick out declared submodule name from
the composite identifier.
* gfortran.h : Add 'submodule_name' to gfc_use_list structure.
* module.c (gfc_match_submodule): Define submodule_name and add
static 'submodule_name'.
(gfc_match_submodule): Build up submodule filenames, using '@'
as a delimiter. Store the output filename in 'submodule_name'.
Similarly, the submodule identifier is built using '.' as an
identifier.
(gfc_dump_module): If current state is COMP_SUBMODULE, write
to file 'submodule_name', using SUBMODULE_EXTENSION.
(gfc_use_module): Similarly, use the 'submodule_name' field in
the gfc_use_list structure and SUBMODULE_EXTENSION to read the
implicitly used submodule files.
2015-07-16 Paul Thomas <pault@gcc.gnu.org>
PR fortran/52846
* lib/fortran-modules.exp (proc cleanup-submodules): New proc..
* gfortran.dg/submodule_1.f90: Clean up submodules
* gfortran.dg/submodule_2.f90: Clean up submodules
* gfortran.dg/submodule_3.f90: Clean up submodules
* gfortran.dg/submodule_4.f90: Clean up submodules
* gfortran.dg/submodule_5.f90: Clean up submodules
* gfortran.dg/submodule_6.f90: Clean up submodules
* gfortran.dg/submodule_7.f90: Clean up submodules
* gfortran.dg/submodule_8.f90: New test
On 14 July 2015 at 13:10, Paul Richard Thomas
<paul.richard.thomas@gmail.com> wrote:
> Dear All,
>
> Reinhold Bader has pointed out the naming the submodule files after
> the submodule name and using .mod as the extension can potentially
> lead to clashes. Therefore, I have written a patch to change gfortran
> to follow the naming convention of another leading brand:
>
> submodule filename = module@ancestor@....@submodule.smod
>
> The implementation is straightforward and the ChangeLog and the patch
> provide an adequate description.
>
> Bootstraps and regtests on x86_64 - OK for trunk?
>
> Paul
>
> 2015-07-14 Paul Thomas <pault@gcc.gnu.org>
>
> PR fortran/52846
> * gfortran.h : Add 'submodule_name' to gfc_use_list structure.
> * module.c (gfc_match_submodule): Define submodule_name and add
> static 'submodule_name'.
> (gfc_match_submodule): Build up submodule filenames, using '@'
> as a delimiter. Store the output filename in 'submodule_name'.
> (gfc_dump_module): If current state is COMP_SUBMODULE, write
> to file 'submodule_name', using SUBMODULE_EXTENSION.
> (gfc_use_module): Similarly, use the 'submodule_name' field in
> the gfc_use_list structure and SUBMODULE_EXTENSION to read the
> implicitly used submodule files.
--
Outside of a dog, a book is a man's best friend. Inside of a dog it's
too dark to read.
Groucho Marx
-------------- next part --------------
Index: gcc/fortran/decl.c
===================================================================
*** gcc/fortran/decl.c (revision 225410)
--- gcc/fortran/decl.c (working copy)
*************** gfc_match_end (gfc_statement *st)
*** 6451,6456 ****
--- 6451,6461 ----
if (block_name == NULL)
goto syntax;
+ /* We have to pick out the declared submodule name from the composite
+ required by F2008:11.2.3 para 2, which ends in the declared name. */
+ if (state == COMP_SUBMODULE)
+ block_name = strchr (block_name, '.') + 1;
+
if (strcmp (name, block_name) != 0 && strcmp (block_name, "ppr@") != 0)
{
gfc_error ("Expected label %qs for %s statement at %C", block_name,
Index: gcc/fortran/gfortran.h
===================================================================
*** gcc/fortran/gfortran.h (revision 225410)
--- gcc/fortran/gfortran.h (working copy)
*************** gfc_use_rename;
*** 1556,1561 ****
--- 1556,1562 ----
typedef struct gfc_use_list
{
const char *module_name;
+ const char *submodule_name;
bool intrinsic;
bool non_intrinsic;
bool only_flag;
Index: gcc/fortran/module.c
===================================================================
*** gcc/fortran/module.c (revision 225410)
--- gcc/fortran/module.c (working copy)
*************** along with GCC; see the file COPYING3.
*** 82,87 ****
--- 82,88 ----
#include <zlib.h>
#define MODULE_EXTENSION ".mod"
+ #define SUBMODULE_EXTENSION ".smod"
/* Don't put any single quote (') in MOD_VERSION, if you want it to be
recognized. */
*************** static gzFile module_fp;
*** 191,196 ****
--- 192,199 ----
/* The name of the module we're reading (USE'ing) or writing. */
static const char *module_name;
+ /* The name of the .smod file that the submodule will write to. */
+ static const char *submodule_name;
static gfc_use_list *module_list;
/* If we're reading an intrinsic module, this is its ID. */
*************** cleanup:
*** 716,722 ****
}
! /* Match a SUBMODULE statement. */
match
gfc_match_submodule (void)
--- 719,735 ----
}
! /* Match a SUBMODULE statement.
!
! According to F2008:11.2.3.2, "The submodule identifier is the
! ordered pair whose first element is the ancestor module name and
! whose second element is the submodule name. 'Submodule_name' is
! used for the submodule filename and uses '@' as a separator, whilst
! the name of the symbol for the module uses '.' as a a separator.
! The reasons for these choices are:
! (i) To follow another leading brand in the submodule filenames;
! (ii) Since '.' is not particularly visible in the filenames; and
! (iii) The linker does not permit '@' in mnemonics. */
match
gfc_match_submodule (void)
*************** gfc_match_submodule (void)
*** 741,747 ****
goto syntax;
use_list = gfc_get_use_list ();
- use_list->module_name = gfc_get_string (name);
use_list->where = gfc_current_locus;
if (module_list)
--- 754,759 ----
*************** gfc_match_submodule (void)
*** 750,758 ****
--- 762,778 ----
while (last->next)
last = last->next;
last->next = use_list;
+ use_list->module_name
+ = gfc_get_string ("%s.%s", module_list->module_name, name);
+ use_list->submodule_name
+ = gfc_get_string ("%s@%s", module_list->module_name, name);
}
else
+ {
module_list = use_list;
+ use_list->module_name = gfc_get_string (name);
+ use_list->submodule_name = use_list->module_name;
+ }
if (gfc_match_char (')') == MATCH_YES)
break;
*************** gfc_match_submodule (void)
*** 765,774 ****
--- 785,810 ----
if (m != MATCH_YES)
goto syntax;
+ submodule_name = gfc_get_string ("%s@%s", module_list->module_name,
+ gfc_new_block->name);
+
+ gfc_new_block->name = gfc_get_string ("%s.%s",
+ module_list->module_name,
+ gfc_new_block->name);
+
if (!gfc_add_flavor (&gfc_new_block->attr, FL_MODULE,
gfc_new_block->name, NULL))
return MATCH_ERROR;
+ /* Just retain the ultimate .(s)mod file for reading, since it
+ contains all the information in its ancestors. */
+ use_list = module_list;
+ for (; module_list->next; use_list = use_list->next)
+ {
+ module_list = use_list->next;
+ free (use_list);
+ }
+
return MATCH_YES;
syntax:
*************** gfc_dump_module (const char *name, int d
*** 5933,5939 ****
--- 5969,5984 ----
char *filename, *filename_tmp;
uLong crc, crc_old;
+ module_name = gfc_get_string (name);
+
+ if (gfc_state_stack->state == COMP_SUBMODULE)
+ {
+ name = submodule_name;
+ n = strlen (name) + strlen (SUBMODULE_EXTENSION) + 1;
+ }
+ else
n = strlen (name) + strlen (MODULE_EXTENSION) + 1;
+
if (gfc_option.module_dir != NULL)
{
n += strlen (gfc_option.module_dir);
*************** gfc_dump_module (const char *name, int d
*** 5946,5951 ****
--- 5991,6000 ----
filename = (char *) alloca (n);
strcpy (filename, name);
}
+
+ if (gfc_state_stack->state == COMP_SUBMODULE)
+ strcat (filename, SUBMODULE_EXTENSION);
+ else
strcat (filename, MODULE_EXTENSION);
/* Name of the temporary file used to write the module. */
*************** gfc_dump_module (const char *name, int d
*** 5975,5981 ****
/* Write the module itself. */
iomode = IO_OUTPUT;
- module_name = gfc_get_string (name);
init_pi_tree ();
--- 6024,6029 ----
*************** gfc_use_module (gfc_use_list *module)
*** 6706,6715 ****
gfc_warning_now (OPT_Wuse_without_only,
"USE statement at %C has no ONLY qualifier");
! filename = XALLOCAVEC (char, strlen (module_name) + strlen (MODULE_EXTENSION)
! + 1);
strcpy (filename, module_name);
strcat (filename, MODULE_EXTENSION);
/* First, try to find an non-intrinsic module, unless the USE statement
specified that the module is intrinsic. */
--- 6754,6775 ----
gfc_warning_now (OPT_Wuse_without_only,
"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);
strcpy (filename, module_name);
strcat (filename, MODULE_EXTENSION);
+ }
+ else
+ {
+ filename = XALLOCAVEC (char, strlen (module->submodule_name)
+ + strlen (SUBMODULE_EXTENSION) + 1);
+ strcpy (filename, module->submodule_name);
+ strcat (filename, SUBMODULE_EXTENSION);
+ }
/* First, try to find an non-intrinsic module, unless the USE statement
specified that the module is intrinsic. */
Index: gcc/testsuite/lib/fortran-modules.exp
===================================================================
*** gcc/testsuite/lib/fortran-modules.exp (revision 225410)
--- gcc/testsuite/lib/fortran-modules.exp (working copy)
*************** proc cleanup-modules { modlist } {
*** 29,34 ****
--- 29,47 ----
}
}
+ # Remove files for specified Fortran modules.
+ proc cleanup-submodules { modlist } {
+ global clean
+ foreach mod [concat $modlist $clean] {
+ set m [string tolower $mod].smod
+ verbose "cleanup-submodule `$m'" 2
+ if [is_remote host] {
+ remote_file host delete $m
+ }
+ remote_file build delete $m
+ }
+ }
+
proc keep-modules { modlist } {
global clean
# if the modlist is empty, keep everything
Index: gcc/testsuite/gfortran.dg/submodule_1.f90
===================================================================
*** gcc/testsuite/gfortran.dg/submodule_1.f90 (revision 225410)
--- gcc/testsuite/gfortran.dg/submodule_1.f90 (working copy)
***************
*** 170,172 ****
--- 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" } }
Index: gcc/testsuite/gfortran.dg/submodule_2.f90
===================================================================
*** gcc/testsuite/gfortran.dg/submodule_2.f90 (revision 225410)
--- gcc/testsuite/gfortran.dg/submodule_2.f90 (working copy)
***************
*** 98,100 ****
--- 98,102 ----
if (any (arg%greeting .ne. ["adieu, people!", "adieu, people!"])) call abort
contains
end program
+ ! { dg-final { cleanup-submodules "foo_interface_son" } }
+ ! { dg-final { cleanup-submodules "foo_interface_daughter" } }
Index: gcc/testsuite/gfortran.dg/submodule_6.f90
===================================================================
*** gcc/testsuite/gfortran.dg/submodule_6.f90 (revision 225410)
--- gcc/testsuite/gfortran.dg/submodule_6.f90 (working copy)
*************** program p
*** 88,91 ****
--- 88,93 ----
call p_a(a, create_b([3,4,5]))
call print(a)
end program p
+ ! { dg-final { cleanup-submodules "imp_p_a" } }
+ ! { dg-final { cleanup-submodules "imp_create" } }
Index: gcc/testsuite/gfortran.dg/submodule_7.f90
===================================================================
*** gcc/testsuite/gfortran.dg/submodule_7.f90 (revision 225410)
--- gcc/testsuite/gfortran.dg/submodule_7.f90 (working copy)
*************** program main
*** 145,147 ****
--- 145,149 ----
call verify_cleanup (c_1, c_2)
!...
end program main
+ ! { dg-final { cleanup-submodules "color_points_a" } }
+ ! { dg-final { cleanup-submodules "color_points_b" } }
Index: gcc/testsuite/gfortran.dg/submodule_8.f90
===================================================================
*** gcc/testsuite/gfortran.dg/submodule_8.f90 (revision 0)
--- gcc/testsuite/gfortran.dg/submodule_8.f90 (working copy)
***************
*** 0 ****
--- 1,44 ----
+ ! { dg-do run }
+ !
+ ! Checks that F2008:11.2.3 para 2 is correctly implemented so that
+ ! no error results from using 'mod_s' for both a module name and
+ ! a submodule name. The submodule is now identified as 'mod_a.mod_s'
+ ! internally and the submodule file as 'mod_a@mod_s.smod'.
+ !
+ ! Contributed by Reinhold Bader <reinhold.bader@lrz.de>
+ !
+ module mod_a
+ implicit none
+ interface
+ module subroutine p()
+ end subroutine
+ end interface
+ end module
+
+ submodule (mod_a) mod_s
+ implicit none
+ integer :: i=-2
+ contains
+ module procedure p
+ if (i .ne. -2) then
+ call abort
+ end if
+ end procedure
+ end submodule
+
+ module mod_s
+ use mod_a
+ implicit none
+ integer :: i=2
+ end module
+
+ program a_s
+ use mod_s
+ implicit none
+ if (i==2) then
+ call p()
+ else
+ call abort
+ end if
+ end program
+ ! { dg-final { cleanup-submodules "mod_s" } }
More information about the Fortran
mailing list