See attached patch. It includes my previous patch and patch to check for C1550. OK to commit?
2019-10-14 Steven G. Kargl <ka...@gcc.gnu.org> PR fortran/89943 decl.c (gfc_match_function_decl): Ignore duplicate BIND(C) for function declaration in submodule. Implement at check for F2018 C1550. (gfc_match_entry): Use temporary for locus, which allows removal of one gfc_error_now(). (gfc_match_subroutine): Ignore duplicate BIND(C) for subroutine declaration in submodule. Implement at check for F2018 C1550. 2019-10-14 Steven G. Kargl <ka...@gcc.gnu.org> PR fortran/89943 * gfortran.dg/pr89943_1.f90: New test. * gfortran.dg/pr89943_2.f90: Ditto. * gfortran.dg/pr89943_3.f90: Ditto. * gfortran.dg/pr89943_4.f90: Ditto. On Sat, Oct 12, 2019 at 02:57:25PM +0100, Paul Richard Thomas wrote: > Hi Steve, > > In the F2018 standard: C1550 (R1526) If MODULE appears in the prefix > of a module subprogram and a binding label is specified, it > shall be the same as the binding label specified in the corresponding > module procedure interface body. > > While it does not say explicitly that a repeat binding label is > allowed, I think that the implication is clear enough. > > The patch is OK as it is but it would be nice if C1550 is or would be > implemented. > > Thanks > > Paul > > On Fri, 11 Oct 2019 at 19:31, Steve Kargl > <s...@troutmask.apl.washington.edu> wrote: > > > > PING. > > > > On Fri, Oct 04, 2019 at 03:26:53PM -0700, Steve Kargl wrote: > > > The attached patch allows the declaration of a BIND(C) > > > module function or module subroutine to appear in a > > > submodule (see testcases). Regression test was clean. > > > OK to commit? > > > > > > Before a rubber stamped 'OK'. I do NOT use submodules. > > > A submodule user needs to pipe up on the validity of > > > the patch. > > > > > > > > > 2019-10-04 Steven G. Kargl <ka...@gcc.gnu.org> > > > > > > PR fortran/89943 > > > decl.c (gfc_match_function_decl): Ignore duplicate BIND(C) for > > > function > > > declaration in submodule. > > > (gfc_match_entry): Use temporary for locus, which allows removal of > > > one gfc_error_now(). > > > (gfc_match_subroutine): Ignore duplicate BIND(C) for subroutine > > > declaration in submodule. > > > > > > 2019-10-04 Steven G. Kargl <ka...@gcc.gnu.org> > > > > > > PR fortran/89943 > > > * gfortran.dg/pr89943_1.f90: New test. > > > * gfortran.dg/pr89943_2.f90: Ditto. > > > > > > -- > > > Steve > > > > > Index: gcc/fortran/decl.c > > > =================================================================== > > > --- gcc/fortran/decl.c (revision 276601) > > > +++ gcc/fortran/decl.c (working copy) > > > @@ -7259,13 +7259,16 @@ gfc_match_function_decl (void) > > > if (sym->attr.is_bind_c == 1) > > > { > > > sym->attr.is_bind_c = 0; > > > - if (sym->old_symbol != NULL) > > > - gfc_error_now ("BIND(C) attribute at %L can only be used for " > > > - "variables or common blocks", > > > - &(sym->old_symbol->declared_at)); > > > - else > > > - gfc_error_now ("BIND(C) attribute at %L can only be used for " > > > - "variables or common blocks", &gfc_current_locus); > > > + > > > + if (gfc_state_stack->previous > > > + && gfc_state_stack->previous->state != COMP_SUBMODULE) > > > + { > > > + locus loc; > > > + loc = sym->old_symbol != NULL > > > + ? sym->old_symbol->declared_at : gfc_current_locus; > > > + gfc_error_now ("BIND(C) attribute at %L can only be used for " > > > + "variables or common blocks", &loc); > > > + } > > > } > > > > > > if (found_match != MATCH_YES) > > > @@ -7517,16 +7520,16 @@ gfc_match_entry (void) > > > not allowed for procedures. */ > > > if (entry->attr.is_bind_c == 1) > > > { > > > + locus loc; > > > + > > > entry->attr.is_bind_c = 0; > > > - if (entry->old_symbol != NULL) > > > - gfc_error_now ("BIND(C) attribute at %L can only be used for " > > > - "variables or common blocks", > > > - &(entry->old_symbol->declared_at)); > > > - else > > > - gfc_error_now ("BIND(C) attribute at %L can only be used for " > > > - "variables or common blocks", &gfc_current_locus); > > > - } > > > > > > + loc = entry->old_symbol != NULL > > > + ? entry->old_symbol->declared_at : gfc_current_locus; > > > + gfc_error_now ("BIND(C) attribute at %L can only be used for " > > > + "variables or common blocks", &loc); > > > + } > > > + > > > /* Check what next non-whitespace character is so we can tell if there > > > is the required parens if we have a BIND(C). */ > > > old_loc = gfc_current_locus; > > > @@ -7725,13 +7728,16 @@ gfc_match_subroutine (void) > > > if (sym->attr.is_bind_c == 1) > > > { > > > sym->attr.is_bind_c = 0; > > > - if (sym->old_symbol != NULL) > > > - gfc_error_now ("BIND(C) attribute at %L can only be used for " > > > - "variables or common blocks", > > > - &(sym->old_symbol->declared_at)); > > > - else > > > - gfc_error_now ("BIND(C) attribute at %L can only be used for " > > > - "variables or common blocks", &gfc_current_locus); > > > + > > > + if (gfc_state_stack->previous > > > + && gfc_state_stack->previous->state != COMP_SUBMODULE) > > > + { > > > + locus loc; > > > + loc = sym->old_symbol != NULL > > > + ? sym->old_symbol->declared_at : gfc_current_locus; > > > + gfc_error_now ("BIND(C) attribute at %L can only be used for " > > > + "variables or common blocks", &loc); > > > + } > > > } > > > > > > /* C binding names are not allowed for internal procedures. */ > > > Index: gcc/testsuite/gfortran.dg/pr89943_1.f90 > > > =================================================================== > > > --- gcc/testsuite/gfortran.dg/pr89943_1.f90 (nonexistent) > > > +++ gcc/testsuite/gfortran.dg/pr89943_1.f90 (working copy) > > > @@ -0,0 +1,31 @@ > > > +! { dg-do compile } > > > +! PR fortran/89943 > > > +! Code contributed by Alberto Luaces <aluaces at udc dot se> > > > +module Foo_mod > > > + > > > + implicit none > > > + > > > + interface > > > + module subroutine runFoo4C(ndim) bind(C, name="runFoo") > > > + use, intrinsic :: iso_c_binding > > > + implicit none > > > + integer(c_int32_t) , intent(in) :: ndim > > > + end subroutine runFoo4C > > > + end interface > > > + > > > + contains > > > + > > > +end module Foo_mod > > > + > > > +submodule(Foo_mod) Foo_smod > > > + > > > + contains > > > + > > > + module subroutine runFoo4C(ndim) bind(C, name="runFoo") > > > + use, intrinsic :: iso_c_binding > > > + implicit none > > > + integer(c_int32_t) , intent(in) :: ndim > > > + end subroutine runFoo4C > > > + > > > +end submodule Foo_smod > > > + > > > Index: gcc/testsuite/gfortran.dg/pr89943_2.f90 > > > =================================================================== > > > --- gcc/testsuite/gfortran.dg/pr89943_2.f90 (nonexistent) > > > +++ gcc/testsuite/gfortran.dg/pr89943_2.f90 (working copy) > > > @@ -0,0 +1,33 @@ > > > +! { dg-do compile } > > > +! PR fortran/89943 > > > +! Code contributed by Alberto Luaces <aluaces at udc dot se> > > > +module Foo_mod > > > + > > > + implicit none > > > + > > > + interface > > > + module function runFoo4C(ndim) bind(C, name="runFoo") > > > + use, intrinsic :: iso_c_binding > > > + implicit none > > > + integer runFoo4c > > > + integer(c_int32_t) , intent(in) :: ndim > > > + end function runFoo4C > > > + end interface > > > + > > > + contains > > > + > > > +end module Foo_mod > > > + > > > +submodule(Foo_mod) Foo_smod > > > + > > > + contains > > > + > > > + module function runFoo4C(ndim) bind(C, name="runFoo") > > > + use, intrinsic :: iso_c_binding > > > + implicit none > > > + integer runFoo4c > > > + integer(c_int32_t) , intent(in) :: ndim > > > + end function runFoo4C > > > + > > > +end submodule Foo_smod > > > + > > > > > > -- > > Steve > > 20170425 https://www.youtube.com/watch?v=VWUpyCsUKR4 > > 20161221 https://www.youtube.com/watch?v=IbCHE-hONow > > > > -- > "If you can't explain it simply, you don't understand it well enough" > - Albert Einstein -- Steve 20170425 https://www.youtube.com/watch?v=VWUpyCsUKR4 20161221 https://www.youtube.com/watch?v=IbCHE-hONow
Index: gcc/fortran/decl.c =================================================================== --- gcc/fortran/decl.c (revision 276967) +++ gcc/fortran/decl.c (working copy) @@ -7263,13 +7263,16 @@ gfc_match_function_decl (void) if (sym->attr.is_bind_c == 1) { sym->attr.is_bind_c = 0; - if (sym->old_symbol != NULL) - gfc_error_now ("BIND(C) attribute at %L can only be used for " - "variables or common blocks", - &(sym->old_symbol->declared_at)); - else - gfc_error_now ("BIND(C) attribute at %L can only be used for " - "variables or common blocks", &gfc_current_locus); + + if (gfc_state_stack->previous + && gfc_state_stack->previous->state != COMP_SUBMODULE) + { + locus loc; + loc = sym->old_symbol != NULL + ? sym->old_symbol->declared_at : gfc_current_locus; + gfc_error_now ("BIND(C) attribute at %L can only be used for " + "variables or common blocks", &loc); + } } if (found_match != MATCH_YES) @@ -7283,6 +7286,24 @@ gfc_match_function_decl (void) found_match = suffix_match; } + /* F2018 C1550 (R1526) If MODULE appears in the prefix of a module + subprogram and a binding label is specified, it shall be the + same as the binding label specified in the corresponding module + procedure interface body. */ + if (sym->attr.is_bind_c && sym->attr.module_procedure && sym->old_symbol + && strcmp (sym->name, sym->old_symbol->name) == 0 + && strcmp (sym->binding_label, sym->old_symbol->binding_label) != 0) + { + const char *null = "NULL", *s1, *s2; + s1 = sym->binding_label; + if (!s1) s1 = null; + s2 = sym->old_symbol->binding_label; + if (!s2) s2 = null; + gfc_error ("Mismatch in BIND(C) names (%qs/%qs) at %C", s1, s2); + sym->refs++; /* Needed to avoid an ICE in gfc_release_symbol */ + return MATCH_ERROR; + } + if(found_match != MATCH_YES) m = MATCH_ERROR; else @@ -7521,16 +7542,16 @@ gfc_match_entry (void) not allowed for procedures. */ if (entry->attr.is_bind_c == 1) { + locus loc; + entry->attr.is_bind_c = 0; - if (entry->old_symbol != NULL) - gfc_error_now ("BIND(C) attribute at %L can only be used for " - "variables or common blocks", - &(entry->old_symbol->declared_at)); - else - gfc_error_now ("BIND(C) attribute at %L can only be used for " - "variables or common blocks", &gfc_current_locus); - } + loc = entry->old_symbol != NULL + ? entry->old_symbol->declared_at : gfc_current_locus; + gfc_error_now ("BIND(C) attribute at %L can only be used for " + "variables or common blocks", &loc); + } + /* Check what next non-whitespace character is so we can tell if there is the required parens if we have a BIND(C). */ old_loc = gfc_current_locus; @@ -7729,13 +7750,16 @@ gfc_match_subroutine (void) if (sym->attr.is_bind_c == 1) { sym->attr.is_bind_c = 0; - if (sym->old_symbol != NULL) - gfc_error_now ("BIND(C) attribute at %L can only be used for " - "variables or common blocks", - &(sym->old_symbol->declared_at)); - else - gfc_error_now ("BIND(C) attribute at %L can only be used for " - "variables or common blocks", &gfc_current_locus); + + if (gfc_state_stack->previous + && gfc_state_stack->previous->state != COMP_SUBMODULE) + { + locus loc; + loc = sym->old_symbol != NULL + ? sym->old_symbol->declared_at : gfc_current_locus; + gfc_error_now ("BIND(C) attribute at %L can only be used for " + "variables or common blocks", &loc); + } } /* C binding names are not allowed for internal procedures. */ @@ -7776,6 +7800,24 @@ gfc_match_subroutine (void) gfc_error ("Missing required parentheses before BIND(C) at %C"); return MATCH_ERROR; } + + /* F2018 C1550 (R1526) If MODULE appears in the prefix of a module + subprogram and a binding label is specified, it shall be the + same as the binding label specified in the corresponding module + procedure interface body. */ + if (sym->attr.module_procedure && sym->old_symbol + && strcmp (sym->name, sym->old_symbol->name) == 0 + && strcmp (sym->binding_label, sym->old_symbol->binding_label) != 0) + { + const char *null = "NULL", *s1, *s2; + s1 = sym->binding_label; + if (!s1) s1 = null; + s2 = sym->old_symbol->binding_label; + if (!s2) s2 = null; + gfc_error ("Mismatch in BIND(C) names (%qs/%qs) at %C", s1, s2); + sym->refs++; /* Needed to avoid an ICE in gfc_release_symbol */ + return MATCH_ERROR; + } /* Scan the dummy arguments for an alternate return. */ for (arg = sym->formal; arg; arg = arg->next) Index: gcc/testsuite/gfortran.dg/pr89943_1.f90 =================================================================== --- gcc/testsuite/gfortran.dg/pr89943_1.f90 (nonexistent) +++ gcc/testsuite/gfortran.dg/pr89943_1.f90 (working copy) @@ -0,0 +1,31 @@ +! { dg-do compile } +! PR fortran/89943 +! Code contributed by Alberto Luaces <aluaces at udc dot se> +module Foo_mod + + implicit none + + interface + module subroutine runFoo4C(ndim) bind(C, name="runFoo") + use, intrinsic :: iso_c_binding + implicit none + integer(c_int32_t) , intent(in) :: ndim + end subroutine runFoo4C + end interface + + contains + +end module Foo_mod + +submodule(Foo_mod) Foo_smod + + contains + + module subroutine runFoo4C(ndim) bind(C, name="runFoo") + use, intrinsic :: iso_c_binding + implicit none + integer(c_int32_t) , intent(in) :: ndim + end subroutine runFoo4C + +end submodule Foo_smod + Index: gcc/testsuite/gfortran.dg/pr89943_2.f90 =================================================================== --- gcc/testsuite/gfortran.dg/pr89943_2.f90 (nonexistent) +++ gcc/testsuite/gfortran.dg/pr89943_2.f90 (working copy) @@ -0,0 +1,33 @@ +! { dg-do compile } +! PR fortran/89943 +! Code contributed by Alberto Luaces <aluaces at udc dot se> +module Foo_mod + + implicit none + + interface + module function runFoo4C(ndim) bind(C, name="runFoo") + use, intrinsic :: iso_c_binding + implicit none + integer runFoo4c + integer(c_int32_t) , intent(in) :: ndim + end function runFoo4C + end interface + + contains + +end module Foo_mod + +submodule(Foo_mod) Foo_smod + + contains + + module function runFoo4C(ndim) bind(C, name="runFoo") + use, intrinsic :: iso_c_binding + implicit none + integer runFoo4c + integer(c_int32_t) , intent(in) :: ndim + end function runFoo4C + +end submodule Foo_smod + Index: gcc/testsuite/gfortran.dg/pr89943_3.f90 =================================================================== --- gcc/testsuite/gfortran.dg/pr89943_3.f90 (nonexistent) +++ gcc/testsuite/gfortran.dg/pr89943_3.f90 (working copy) @@ -0,0 +1,28 @@ +! { dg-do compile } +module Foo_mod + + implicit none + + interface + module subroutine runFoo4C(ndim) bind(C, name="runFoo") + use, intrinsic :: iso_c_binding + implicit none + integer(c_int32_t) , intent(in) :: ndim + end subroutine runFoo4C + end interface + + contains + +end module Foo_mod + +submodule(Foo_mod) Foo_smod + + contains + + module subroutine runFoo4C(ndim) bind(C, name="runFu") ! { dg-error "Mismatch in BIND" } + use, intrinsic :: iso_c_binding ! { dg-error "Unexpected USE statement" } + implicit none ! { dg-error "Unexpected IMPLICIT NONE statement" } + integer(c_int32_t) , intent(in) :: ndim ! { dg-error "Unexpected data declaration" } + end subroutine runFoo4C ! { dg-error " Expecting END SUBMODULE" } + +end submodule Foo_smod Index: gcc/testsuite/gfortran.dg/pr89943_4.f90 =================================================================== --- gcc/testsuite/gfortran.dg/pr89943_4.f90 (nonexistent) +++ gcc/testsuite/gfortran.dg/pr89943_4.f90 (working copy) @@ -0,0 +1,29 @@ +! { dg-do compile } +module Foo_mod + + implicit none + + interface + module function runFoo4C(ndim) bind(C, name="runFoo") + use, intrinsic :: iso_c_binding + implicit none + integer runFoo4c + integer(c_int32_t) , intent(in) :: ndim + end function runFoo4C + end interface + + contains + +end module Foo_mod + +submodule(Foo_mod) Foo_smod + + contains + + module function runFoo4C(ndim) bind(C, name="runFu") ! { dg-error "Mismatch in BIND" } + use, intrinsic :: iso_c_binding ! { dg-error "Unexpected USE statement in" } + implicit none ! { dg-error "Unexpected IMPLICIT NONE statement" } + integer(c_int32_t) , intent(in) :: ndim ! { dg-error "Unexpected data declaration" } + end function runFoo4C ! { dg-error "Expecting END SUBMODULE" } + +end submodule Foo_smod