The code below compiles cleanly with the NAG Fortran compiler. I believe the error message is incorrect. Gfotran 8, 9 and 10 give the same message. ± cat shape-mismatch.f90 module foobar type foo contains procedure, nopass :: bar end type interface module subroutine bar(arg) character(len=*) arg(:) end subroutine end interface contains module procedure bar end procedure end module ± gfortran -c shape-mismatch.f90 shape-mismatch.f90:12:22: 12 | module procedure bar | 1 Error: Shape mismatch in argument 'arg' at (1) ± gfortran --version GNU Fortran (GCC) 10.1.0
Confirmed down to GCC7. What do you want to do with your test? Why do you think it is standard conforming?
Hi Dominique, > What do you want to do with your test? I don't understand the question. The submitted code is designed to be a minimal demonstration of the problem so I don't want to do anything with it other than demonstrate the problem. In case you're asking what the original application was doing, it was for handling command-line arguments. > Why do you think it is standard conforming? Fortran 2008 added module subroutine interface bodies specifically to allow interface bodies in the same scope a the corresponding procedure definitions. In order to avoid duplication, the standard also allows the procedure definition to begin with "module procedure" and then to omit all arguments. That's what is done in the submitted code. The code is accepted by the NAG and Intel compilers.
> Fortran 2008 added module subroutine interface bodies specifically to allow > interface bodies in the same scope a the corresponding procedure definitions. > In order to avoid duplication, the standard also allows the procedure definition > to begin with "module procedure" and then to omit all arguments. That's what is > done in the submitted code. The code is accepted by the NAG and Intel compilers. Do you mean this is F2008 extension?
This patch Index: gcc/fortran/resolve.c =================================================================== --- gcc/fortran/resolve.c (revision 280157) +++ gcc/fortran/resolve.c (working copy) @@ -13242,7 +13254,7 @@ resolve_fl_procedure (gfc_symbol *sym, int mp_flag) check_formal: /* Check the characteristics of the formal arguments. */ - if (sym->formal && sym->formal_ns) + if (sym->formal && iface->formal && sym->formal_ns) { for (arg = sym->formal; arg && arg->sym; arg = arg->next) { allows Damian's example to compile without error. Damian's use of 'module precedure' is backwards from the way I use it. That is, I use it to construct generic interfaces like module foo private public bar interface bar ! Make bar generic module procedure bar1 module procedure bar2 end interface contains subroutine bar1(x) real x end subroutine bar1 subroutine bar2(x) double precision x end subroutine bar2 end module foo It seems strange to me to put a subroutine interface in an interface construct, and then in the 'contain' section of a module simply using 'module procedure bar' where there are no details of the interface and implementation details occur. I do not know if the patch permits valid Fortran to compile, nor I have regression tested the patch, nor do I care.
May be better patch. Index: gcc/fortran/resolve.c =================================================================== @@ -13241,6 +13253,9 @@ resolve_fl_procedure (gfc_symbol *sym, int mp_flag) } check_formal: + if (iface && !iface->formal) + return true; + /* Check the characteristics of the formal arguments. */ if (sym->formal && sym->formal_ns) {
I my too simple terms, when you define the interface and then use module procedure in the contains, all of the declarations in the interface exist as if you had them in the declaration of the subroutine or function in the contains. This includes all arguments and whether or not the procedure is a subroutine or a function. I was not aware of this either untill I saw some other code Damian was doing earlier this week that does actually compile fine like this with gfortran. It is a modern feature and if you think about it, very useful in that it saves a lot of typing. One can choose do do it either way, but this way shown truly uses the interface to define everything.
For context, I nearly always put the procedure definition in a submodule. In this case, I'm attempting to use a tool that needs to parse the code and the tool doesn't support submodules so I moved the procedure definition into the module. The workaround is easy: I just eliminate the interface and put all the argument declarations in the procedure definition. So this is not an important bug for me. It just cost me some time to figure out what the problem was.
On Sun, Jul 26, 2020 at 09:35:56PM +0000, jvdelisle at charter dot net wrote: > > I my too simple terms, when you define the interface and then use > module procedure in the contains, all of the declarations in the > interface exist as if you had them in the declaration of the > subroutine or function in the contains. This includes all arguments > and whether or not the procedure is a subroutine or a function. > > I was not aware of this either untill I saw some other code > Damian was doing earlier this week that does actually compile > fine like this with gfortran. It is a modern feature and if you > think about it, very useful in that it saves a lot of typing. > One can choose do do it either way, but this way shown truly uses > the interface to define everything. > I have thought about it, and I have concluded it is rather curious programming paradigm, because ... module foo private public bar interface bar ! Make bar generic module subroutine bar1(x) real, intent(in) :: x end subroutine bar1 end interface integer x contains ! ! Several hundreds to several thousand lines of code may ! appear here, which separates dummy argument declarations ! from where the dummy arguments are used. ! module procedure bar1 print *, x end procedure bar1 end module foo Oh, and at least, this simply test program works with my 2nd patch. program bah use foo real y y = 42. call bar(y) end program bah Likely, yet another patch that will sit in bugzilla.
(In reply to Dominique d'Humieres from comment #3) > > Do you mean this is F2008 extension? Usually I think of "extension" as describing something non-standard. This is a standard feature. I meant simply that it was not allowed before Fortran 2008 introduced submodules. I think the primary purpose of submodules is to facilitate the separation of interfaces and procedure definitions. And for programmers who prefer to not repeat the argument list in two places (and then have to change it in two places), Fortran 2008 (and 2018) allow the "module procedure" syntax used in the submitted code.
Confirmed. The argument in the interface is assumed shape, as expected, while its shadow in the module procedure is tagged as deferred shape. Yet another fix (!): index ba1c8bc322e..9e822f5c396 100644 --- a/gcc/fortran/interface.c +++ b/gcc/fortran/interface.c @@ -1464,8 +1464,12 @@ gfc_check_dummy_characteristics (gfc_symbol *s1, gfc_symb ol *s2, { int i, compval; gfc_expr *shape1, *shape2; + bool module_procedure; - if (s1->as->type != s2->as->type) + module_procedure = s1->ns->proc_name && + s1->ns->proc_name->attr.module_procedure; + + if (s1->as->type != s2->as->type && !module_procedure) { snprintf (errmsg, err_len, "Shape mismatch in argument '%s'", s1->name); This fixes the problem but I rather think that the proper way to do it is further upstream. decl.c(gfc_match_submod_proc) looks as if the array spec is copied as it should be but I need to do a gdb session to check this. I'll have to put my thinking cap on regarding Steve's offering in comment 5. It should be noted that the submodule version works as intended in all versions of gfortran for which submodules are implemented: module foobar type foo contains procedure, nopass :: bar end type interface module subroutine bar(arg) character(len=*) arg(:) end subroutine end interface end module submodule (foobar) sbar contains module procedure bar print *, arg end procedure end submodule use foobar character(4) :: book(2) = ['abcd', 'efgh'] call bar(book) end I'm onto it. Thanks for the report Paul
Created attachment 48935 [details] Proposed patch for the PR I decided that the best way of proceeding was to correct the array spec and benefit from the rest of the tests in gfc_check_dummy_characteristics. My tree is polluted with work on PDTs right now and so I cannot do a full regtest. However, with the patch applied submodule* and module_procedure* test just fine as does 'module_procedure_4.f90': ! { dg-do run } ! ! Test the fix for PR96320 in which the assumed shape of 'arg' in the ! interface for 'bar' was mirrored by the 'arg' in the module procedure ! incorrectly have deferred shape. ! ! Contributed by Damian Rouson <damian@sourceryinstitute.org> ! module foobar type foo contains procedure, nopass :: bar1 procedure, nopass :: bar2 procedure, nopass :: bar3 end type interface module subroutine bar1(arg) character(len=*) arg(:) end subroutine module subroutine bar2(arg) character(len=*) arg(3:) end subroutine module subroutine bar3(arg) character(len=*) arg(2) end subroutine end interface contains module procedure bar1 if (lbound(arg, 1) .ne. 1) stop 1 if (arg(3) .ne. 'hijk') stop 2 end procedure ! Make sure that the lower bound of an assumed shape array dummy, ! if defined, is passed to the module procedure. module procedure bar2 if (lbound(arg, 1) .ne. 3) stop 3 if (arg(3) .ne. 'abcd') stop 4 end procedure ! This makes sure that an dummy with explicit shape has the upper ! bound correctly set in the module procedure. module procedure bar3 if (lbound(arg, 1) .ne. 1) stop 5 if (arg(3) .ne. 'hijk') stop 6 ! { dg-warning "is out of bounds" } end procedure end module use foobar character(4) :: list(3) = ['abcd', 'efgh' , 'hijk'] type(foo) :: f call f%bar1(list) call f%bar2(list) call f%bar3(list) end
Thanks to each of you for looking at and working on this.
With the attached patch I get several ICEs: (lldb) run /opt/gcc/work/gcc/testsuite/gfortran.dg/asan/pointer_assign_16.f90 Process 88073 launched: '/opt/gcc/gcc11w/libexec/gcc/x86_64-apple-darwin19.5.0/11.0.0/f951' (x86_64) Process 88073 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x58) frame #0: 0x000000010004f9e7 f951`gfc_check_dummy_characteristics(s1=0x00000001453175e0, s2=0x00000001453175e0, type_must_agree=<unavailable>, errmsg="\b\x02???, err_len=200) at interface.c:1469:7 1466 int i, compval; 1467 gfc_expr *shape1, *shape2; 1468 -> 1469 if (s1->ns->proc_name->attr.module_procedure 1470 && s1->as->type == AS_ASSUMED_SHAPE 1471 && s2->as->type == AS_DEFERRED) 1472 {
After fixing the ICEs by replacing 's1->ns->proc_name->attr.module_procedure' with 's1->ns->proc_name && s1->ns->proc_name->attr.module_procedure' I am left with two regressions: FAIL: gfortran.dg/proc_decl_26.f90 -O 2 blank line(s) in output FAIL: gfortran.dg/proc_decl_26.f90 -O (test for excess errors) FAIL: gfortran.dg/whole_file_23.f90 -O 1 blank line(s) in output FAIL: gfortran.dg/whole_file_23.f90 -O (test for excess errors) % gfc /opt/gcc/work/gcc/testsuite/gfortran.dg/proc_decl_26.f90 f951: Warning: s1 2 s2 1 /opt/gcc/work/gcc/testsuite/gfortran.dg/proc_decl_26.f90:20:11: 20 | call foo(two) ! { dg-error "Shape mismatch in argument" } | 1 Error: Interface mismatch in dummy procedure 'f1' at (1): Shape mismatch in argument 'a' f951: Warning: s1 2 s2 1 /opt/gcc/work/gcc/testsuite/gfortran.dg/proc_decl_26.f90:21:11: 21 | call bar(two) ! { dg-error "Shape mismatch in argument" } | 1 Error: Interface mismatch in dummy procedure 'f2' at (1): Shape mismatch in argument 'a' % gfc /opt/gcc/work/gcc/testsuite/gfortran.dg/whole_file_23.f90 f951: Warning: s1 3 s2 2 /opt/gcc/work/gcc/testsuite/gfortran.dg/whole_file_23.f90:18:32: 18 | pure integer function lensum (words, sep) | 1 Warning: Interface mismatch in global procedure 'lensum' at (1): Shape mismatch in argument 'words'
Bother - I left the diagnostic line in the patch: + gfc_warning_now (0, "s1 %i s2 %i \n", s1->as->type, s2->as->type); Sorry about that Paul On Tue, 28 Jul 2020 at 10:24, dominiq at lps dot ens.fr < gcc-bugzilla@gcc.gnu.org> wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96320 > > --- Comment #14 from Dominique d'Humieres <dominiq at lps dot ens.fr> --- > After fixing the ICEs by replacing > 's1->ns->proc_name->attr.module_procedure' > with 's1->ns->proc_name && s1->ns->proc_name->attr.module_procedure' I am > left > with two regressions: > > FAIL: gfortran.dg/proc_decl_26.f90 -O 2 blank line(s) in output > FAIL: gfortran.dg/proc_decl_26.f90 -O (test for excess errors) > FAIL: gfortran.dg/whole_file_23.f90 -O 1 blank line(s) in output > FAIL: gfortran.dg/whole_file_23.f90 -O (test for excess errors) > > % gfc /opt/gcc/work/gcc/testsuite/gfortran.dg/proc_decl_26.f90 > f951: Warning: s1 2 s2 1 > > /opt/gcc/work/gcc/testsuite/gfortran.dg/proc_decl_26.f90:20:11: > > 20 | call foo(two) ! { dg-error "Shape mismatch in argument" } > | 1 > Error: Interface mismatch in dummy procedure 'f1' at (1): Shape mismatch in > argument 'a' > f951: Warning: s1 2 s2 1 > > /opt/gcc/work/gcc/testsuite/gfortran.dg/proc_decl_26.f90:21:11: > > 21 | call bar(two) ! { dg-error "Shape mismatch in argument" } > | 1 > Error: Interface mismatch in dummy procedure 'f2' at (1): Shape mismatch in > argument 'a' > % gfc /opt/gcc/work/gcc/testsuite/gfortran.dg/whole_file_23.f90 > f951: Warning: s1 3 s2 2 > > /opt/gcc/work/gcc/testsuite/gfortran.dg/whole_file_23.f90:18:32: > > 18 | pure integer function lensum (words, sep) > | 1 > Warning: Interface mismatch in global procedure 'lensum' at (1): Shape > mismatch > in argument 'words' > > -- > You are receiving this mail because: > You are on the CC list for the bug. > You are the assignee for the bug.
> Bother - I left the diagnostic line in the patch: > > + gfc_warning_now (0, "s1 %i s2 %i \n", s1->as->type, s2->as->type); > >Sorry about that What I guessed, but I still see (not new) /opt/gcc/work/gcc/testsuite/gfortran.dg/whole_file_23.f90:18:32: 18 | pure integer function lensum (words, sep) | 1 Warning: Interface mismatch in global procedure 'lensum' at (1): Shape mismatch in argument 'words'
On Tue, Jul 28, 2020 at 10:32:50AM +0000, dominiq at lps dot ens.fr wrote: > > What I guessed, but I still see (not new) > > /opt/gcc/work/gcc/testsuite/gfortran.dg/whole_file_23.f90:18:32: > > 18 | pure integer function lensum (words, sep) > | 1 > Warning: Interface mismatch in global procedure 'lensum' at (1): Shape mismatch > in argument 'words' > So, change the dg-error to "Interface mismatch in" from "Shape mismatch in". Clearly, Paul's patch detects an error earlier in the parsing than previously detected.
With --- ../_clean/gcc/fortran/interface.c 2020-07-11 20:06:47.000000000 +0200 +++ gcc/fortran/interface.c 2020-07-28 11:41:57.000000000 +0200 @@ -1466,8 +1466,19 @@ gfc_check_dummy_characteristics (gfc_sym int i, compval; gfc_expr *shape1, *shape2; + if (s1->ns->proc_name && s1->ns->proc_name->attr.module_procedure + && s1->as->type == AS_ASSUMED_SHAPE + && s2->as->type == AS_DEFERRED) + { + s2->as->type = AS_ASSUMED_SHAPE; + for (i = 0; i < s2->as->rank; i++) + if (s1->as->lower[i] != NULL) + s2->as->lower[i] = gfc_copy_expr (s1->as->lower[i]); + } + if (s1->as->type != s2->as->type) { +/* gfc_warning_now (0, "s1 %i s2 %i \n", s1->as->type, s2->as->type); */ snprintf (errmsg, err_len, "Shape mismatch in argument '%s'", s1->name); return false; the patch regtest without regression. > > /opt/gcc/work/gcc/testsuite/gfortran.dg/whole_file_23.f90:18:32: > > > > 18 | pure integer function lensum (words, sep) > > Warning: Interface mismatch in global procedure 'lensum' at (1): Shape mismatch > > in argument 'words' > > So, change the dg-error to "Interface mismatch in" from > "Shape mismatch in". Clearly, Paul's patch detects an > error earlier in the parsing than previously detected. The warning is at least as old as GCC7 but is suppressed in the testsuite by -pedantic-errors (very surprising) thus doesn't fail.
The master branch has been updated by Paul Thomas <pault@gcc.gnu.org>: https://gcc.gnu.org/g:a5baf71b0a5bd79923c095cf81218b8194008f60 commit r11-2489-ga5baf71b0a5bd79923c095cf81218b8194008f60 Author: Paul Thomas <pault@gcc.gnu.org> Date: Sun Aug 2 10:57:59 2020 +0100 This patch fixes PR96320. See the explanatory comment in the testcase. 2020-08-01 Paul Thomas <pault@gcc.gnu.org> gcc/fortran PR target/96320 * interface.c (gfc_check_dummy_characteristics): If a module procedure arrives with assumed shape in the interface and deferred shape in the procedure itself, update the latter and copy the lower bounds. gcc/testsuite/ PR target/96320 * gfortran.dg/module_procedure_4.f90 : New test.
(In reply to CVS Commits from comment #19) > The master branch has been updated by Paul Thomas <pault@gcc.gnu.org>: > > https://gcc.gnu.org/g:a5baf71b0a5bd79923c095cf81218b8194008f60 > > commit r11-2489-ga5baf71b0a5bd79923c095cf81218b8194008f60 > Author: Paul Thomas <pault@gcc.gnu.org> > Date: Sun Aug 2 10:57:59 2020 +0100 > > This patch fixes PR96320. See the explanatory comment in the testcase. > > 2020-08-01 Paul Thomas <pault@gcc.gnu.org> > > gcc/fortran > PR target/96320 > * interface.c (gfc_check_dummy_characteristics): If a module > procedure arrives with assumed shape in the interface and > deferred shape in the procedure itself, update the latter and > copy the lower bounds. > > gcc/testsuite/ > PR target/96320 > * gfortran.dg/module_procedure_4.f90 : New test. 'target' has been replaced with 'fortran' in the ChangeLog commit :-) Paul
Now that the patch fixing this PR has been committed to the trunk, should it be marked as "Resolved" instead of "Assigned?"
On Mon, Aug 03, 2020 at 11:45:20PM +0000, damian at sourceryinstitute dot org wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96320 > > --- Comment #21 from Damian Rouson <damian at sourceryinstitute dot org> --- > Now that the patch fixing this PR has been committed to the trunk, should it be > marked as "Resolved" instead of "Assigned?" > Depends on if someone (whomever committed the patch) is going to backport it to 9 and 10 branch.
A related issue arises if the procedure in question is a pure function as demonstrated below. The code compiles cleanly if either 1. The result-spec is absent and the procedure is renamed new_foo in both the interface body and in the procedure definition, or 2. The interface body is repeated in the procedure definition instead the "module procedure" syntax. ± cat pure-shape-mismatch.f90 module foobar implicit none type foo integer bar end type interface pure module function create() result(new_foo) implicit none type(foo) new_foo end function end interface contains module procedure create new_foo%bar = 1 end procedure end module ± gfortran -c pure-shape-mismatch.f90 pure-shape-mismatch.f90:17:4: 17 | new_foo%bar = 1 | 1 Error: Variable ‘new_foo’ cannot appear in a variable definition context (assignment) at (1) in PURE procedure ± gfortran --version GNU Fortran (GCC) 11.0.0 20200804 (experimental)
This appears to be another example of an issue with a module procedure defined in the same module as its interface body. In this case, the compiler doesn't recognize a reference to the procedure: ± cat subroutine-call.f90 module hole_interface type hole_t contains procedure set_user_defined end type interface module subroutine set_diameter (this) class(hole_t) this end subroutine module subroutine set_user_defined(this) class(hole_t) this end subroutine end interface contains module procedure set_user_defined end procedure module procedure set_diameter call this%set_user_defined end procedure end module use hole_interface end ± gfortran subroutine-call.f90 subroutine-call.f90:26:6: 26 | use hole_interface | 1 Error: ‘set_user_defined’ must be a module procedure or an external procedure with an explicit interface at (1) ± gfortran --version GNU Fortran (GCC) 11.0.0 20200804 (experimental)
The releases/gcc-10 branch has been updated by Paul Thomas <pault@gcc.gnu.org>: https://gcc.gnu.org/g:c2840cf16aaa665aaac4f51345104c5766fb2406 commit r10-9180-gc2840cf16aaa665aaac4f51345104c5766fb2406 Author: Paul Thomas <pault@gcc.gnu.org> Date: Sun Aug 2 10:57:59 2020 +0100 This patch fixes PR96320. See the explanatory comment in the testcase. 2020-08-01 Paul Thomas <pault@gcc.gnu.org> gcc/fortran PR target/96320 * interface.c (gfc_check_dummy_characteristics): If a module procedure arrives with assumed shape in the interface and deferred shape in the procedure itself, update the latter and copy the lower bounds. gcc/testsuite/ PR target/96320 * gfortran.dg/module_procedure_4.f90 : New test. (cherry picked from commit a5baf71b0a5bd79923c095cf81218b8194008f60)
The releases/gcc-9 branch has been updated by Paul Thomas <pault@gcc.gnu.org>: https://gcc.gnu.org/g:101873f243237de4d868af95b89120a48cf86f6e commit r9-9149-g101873f243237de4d868af95b89120a48cf86f6e Author: Paul Thomas <pault@gcc.gnu.org> Date: Mon Jan 4 14:42:10 2021 +0000 This patch fixes PR96320. See the explanatory comment in the testcase. 2021-01-04 Paul Thomas <pault@gcc.gnu.org> gcc/fortran PR fortran/96320 * interface.c (gfc_check_dummy_characteristics): If a module procedure arrives with assumed shape in the interface and deferred shape in the procedure itself, update the latter and copy the lower bounds. gcc/testsuite/ PR fortran/96320 * gfortran.dg/module_procedure_4.f90 : New test.
Created attachment 49875 [details] Fix for the cases in comments 23 and 24 Hi Damian, Happy New Year! ....or I wish you a better one anyway. I have been doing a bit of catching up. The original patch for this PR is now applied as far back as I want to go. The new attachment fixes the testcases in comments 23 and 24. It even regtests OK. Thanks for your patience. Paul
The master branch has been updated by Paul Thomas <pault@gcc.gnu.org>: https://gcc.gnu.org/g:eaf883710c0039eca5caea5115e848adb4ab67bd commit r11-6832-geaf883710c0039eca5caea5115e848adb4ab67bd Author: Paul Thomas <pault@gcc.gnu.org> Date: Thu Jan 21 10:00:00 2021 +0000 Fortran: This patch fixes comments 23 and 24 of PR96320. 2021-01-21 Paul Thomas <pault@gcc.gnu.org> gcc/fortran PR fortran/96320 * decl.c (gfc_match_modproc): It is not an error to find a module procedure declaration within a contains block. * expr.c (gfc_check_vardef_context): Pure procedure result is assignable. Change 'own_scope' accordingly. * resolve.c (resolve_typebound_procedure): A procedure that has the module procedure attribute is almost certainly a module procedure, whatever its interface. gcc/testsuite/ PR fortran/96320 * gfortran.dg/module_procedure_5.f90 : New test. * gfortran.dg/module_procedure_6.f90 : New test.
This was completely fixed way back when :-) Thanks for the report, Damian. Closing Paul