Hello world, the attached patch fixes three very closely related 7/8/9 regressions. The common root cause of these PRs was that , if a binding label existed, gfc_get_extern_function_decl first looked for that name in the global symbol table for that function and used its backend_decl. If there was a module procedure with the same name as the BIND(C) routine (perfectly legal), the wrong procedure would then be called.
The approach is straightforward: In the global symbol table, record whether we are looking at a "normal" or a BIND(C) name, and if we come across the wrong kind of entry in gfc_get_extern_function_decl, just ignore it. Regressoin-tested. OK for trunk? Regards Thomas 2019-03-12 Thomas Koenig <tkoe...@gcc.gnu.org> PR fortran/66695 PR fortran/77746 PR fortran/79485 * gfortran.h (gfc_symbol): Add bind_c component. (gfc_get_gsymbol): Add argument bind_c. * decl.c (add_global_entry): Add bind_c argument to gfc_get_symbol. * parse.c (parse_block_data): Likewise. (parse_module): Likewise. (add_global_procedure): Likewise. (add_global_program): Likewise. * resolve.c (resolve_common_blocks): Likewise. (resolve_global_procedure): Likewise. (gfc_verify_binding_labels): Likewise. * symbol.c (gfc_get_gsymbol): Add argument bind_c. Set bind_c in gsym. * trans-decl.c (gfc_get_module_backend_decl): Add bind_c argument to gfc_get_symbol. (gfc_get_extern_function_decl): If the sym has a binding label and it cannot be found in the global symbol tabel, it is the wrong one and vice versa. 2019-03-12 Thomas Koenig <tkoe...@gcc.gnu.org> PR fortran/66695 PR fortran/77746 PR fortran/79485 * gfortran.dg/binding_label_tests_24.f90: New test. * gfortran.dg/binding_label_tests_25.f90: New test. * gfortran.dg/binding_label_tests_26.f90: New test. * gfortran.dg/binding_label_tests_27.f90: New test.
Index: gfortran.h =================================================================== --- gfortran.h (Revision 269624) +++ gfortran.h (Arbeitskopie) @@ -1891,6 +1891,7 @@ typedef struct gfc_gsymbol enum gfc_symbol_type type; int defined, used; + bool bind_c; locus where; gfc_namespace *ns; } @@ -3114,7 +3115,7 @@ void gfc_enforce_clean_symbol_state (void); void gfc_free_dt_list (void); -gfc_gsymbol *gfc_get_gsymbol (const char *); +gfc_gsymbol *gfc_get_gsymbol (const char *, bool bind_c); gfc_gsymbol *gfc_find_gsymbol (gfc_gsymbol *, const char *); gfc_gsymbol *gfc_find_case_gsymbol (gfc_gsymbol *, const char *); Index: decl.c =================================================================== --- decl.c (Revision 269624) +++ decl.c (Arbeitskopie) @@ -7248,7 +7248,7 @@ add_global_entry (const char *name, const char *bi name is a global identifier. */ if (!binding_label || gfc_notification_std (GFC_STD_F2008)) { - s = gfc_get_gsymbol (name); + s = gfc_get_gsymbol (name, false); if (s->defined || (s->type != GSYM_UNKNOWN && s->type != type)) { @@ -7270,7 +7270,7 @@ add_global_entry (const char *name, const char *bi && (!gfc_notification_std (GFC_STD_F2008) || strcmp (name, binding_label) != 0)) { - s = gfc_get_gsymbol (binding_label); + s = gfc_get_gsymbol (binding_label, true); if (s->defined || (s->type != GSYM_UNKNOWN && s->type != type)) { Index: parse.c =================================================================== --- parse.c (Revision 269624) +++ parse.c (Arbeitskopie) @@ -5839,7 +5839,7 @@ parse_block_data (void) } else { - s = gfc_get_gsymbol (gfc_new_block->name); + s = gfc_get_gsymbol (gfc_new_block->name, false); if (s->defined || (s->type != GSYM_UNKNOWN && s->type != GSYM_BLOCK_DATA)) gfc_global_used (s, &gfc_new_block->declared_at); @@ -5921,7 +5921,7 @@ parse_module (void) gfc_gsymbol *s; bool error; - s = gfc_get_gsymbol (gfc_new_block->name); + s = gfc_get_gsymbol (gfc_new_block->name, false); if (s->defined || (s->type != GSYM_UNKNOWN && s->type != GSYM_MODULE)) gfc_global_used (s, &gfc_new_block->declared_at); else @@ -5985,7 +5985,7 @@ add_global_procedure (bool sub) name is a global identifier. */ if (!gfc_new_block->binding_label || gfc_notification_std (GFC_STD_F2008)) { - s = gfc_get_gsymbol (gfc_new_block->name); + s = gfc_get_gsymbol (gfc_new_block->name, false); if (s->defined || (s->type != GSYM_UNKNOWN @@ -6010,7 +6010,7 @@ add_global_procedure (bool sub) && (!gfc_notification_std (GFC_STD_F2008) || strcmp (gfc_new_block->name, gfc_new_block->binding_label) != 0)) { - s = gfc_get_gsymbol (gfc_new_block->binding_label); + s = gfc_get_gsymbol (gfc_new_block->binding_label, true); if (s->defined || (s->type != GSYM_UNKNOWN @@ -6042,7 +6042,7 @@ add_global_program (void) if (gfc_new_block == NULL) return; - s = gfc_get_gsymbol (gfc_new_block->name); + s = gfc_get_gsymbol (gfc_new_block->name, false); if (s->defined || (s->type != GSYM_UNKNOWN && s->type != GSYM_PROGRAM)) gfc_global_used (s, &gfc_new_block->declared_at); Index: resolve.c =================================================================== --- resolve.c (Revision 269624) +++ resolve.c (Arbeitskopie) @@ -1050,7 +1050,7 @@ resolve_common_blocks (gfc_symtree *common_root) } if (!gsym) { - gsym = gfc_get_gsymbol (common_root->n.common->name); + gsym = gfc_get_gsymbol (common_root->n.common->name, false); gsym->type = GSYM_COMMON; gsym->where = common_root->n.common->where; gsym->defined = 1; @@ -1072,7 +1072,7 @@ resolve_common_blocks (gfc_symtree *common_root) } if (!gsym) { - gsym = gfc_get_gsymbol (common_root->n.common->binding_label); + gsym = gfc_get_gsymbol (common_root->n.common->binding_label, true); gsym->type = GSYM_COMMON; gsym->where = common_root->n.common->where; gsym->defined = 1; @@ -2487,7 +2487,8 @@ resolve_global_procedure (gfc_symbol *sym, locus * type = sub ? GSYM_SUBROUTINE : GSYM_FUNCTION; - gsym = gfc_get_gsymbol (sym->binding_label ? sym->binding_label : sym->name); + gsym = gfc_get_gsymbol (sym->binding_label ? sym->binding_label : sym->name, + sym->binding_label != NULL); if ((gsym->type != GSYM_UNKNOWN && gsym->type != type)) gfc_global_used (gsym, where); @@ -11847,7 +11848,7 @@ gfc_verify_binding_labels (gfc_symbol *sym) && (gsym->type == GSYM_FUNCTION || gsym->type == GSYM_SUBROUTINE))) { if (!gsym) - gsym = gfc_get_gsymbol (sym->binding_label); + gsym = gfc_get_gsymbol (sym->binding_label, true); gsym->where = sym->declared_at; gsym->sym_name = sym->name; gsym->binding_label = sym->binding_label; Index: symbol.c =================================================================== --- symbol.c (Revision 269624) +++ symbol.c (Arbeitskopie) @@ -4330,7 +4330,7 @@ gsym_compare (void *_s1, void *_s2) /* Get a global symbol, creating it if it doesn't exist. */ gfc_gsymbol * -gfc_get_gsymbol (const char *name) +gfc_get_gsymbol (const char *name, bool bind_c) { gfc_gsymbol *s; @@ -4341,6 +4341,7 @@ gfc_gsymbol * s = XCNEW (gfc_gsymbol); s->type = GSYM_UNKNOWN; s->name = gfc_get_string ("%s", name); + s->bind_c = bind_c; gfc_insert_bbt (&gfc_gsym_root, s, gsym_compare); Index: trans-decl.c =================================================================== --- trans-decl.c (Revision 269624) +++ trans-decl.c (Arbeitskopie) @@ -843,7 +843,7 @@ gfc_get_module_backend_decl (gfc_symbol *sym) { if (!gsym) { - gsym = gfc_get_gsymbol (sym->module); + gsym = gfc_get_gsymbol (sym->module, false); gsym->type = GSYM_MODULE; gsym->ns = gfc_get_namespace (NULL, 0); } @@ -2002,10 +2002,23 @@ gfc_get_extern_function_decl (gfc_symbol * sym, gf return get_proc_pointer_decl (sym); /* See if this is an external procedure from the same file. If so, - return the backend_decl. */ - gsym = gfc_find_gsymbol (gfc_gsym_root, sym->binding_label - ? sym->binding_label : sym->name); + return the backend_decl. If we are looking at a BIND(C) + procedure and the symbol is not BIND(C), or vice versa, we + haven't found the right procedure. */ + if (sym->binding_label) + { + gsym = gfc_find_gsymbol (gfc_gsym_root, sym->binding_label); + if (gsym && !gsym->bind_c) + gsym = NULL; + } + else + { + gsym = gfc_find_gsymbol (gfc_gsym_root, sym->name); + if (gsym && gsym->bind_c) + gsym = NULL; + } + if (gsym && !gsym->defined) gsym = NULL;
! { dg-do run } ! PR 77746 - this used to crash during execution. ! Original test case by Vladimir Fuka. module first private public execute interface execute module procedure random_name end interface contains subroutine random_name() end subroutine end module module test use first implicit none contains subroutine p_execute(i) bind(C, name="random_name") integer :: i call execute() end subroutine end module use test call p_execute(1) end
! { dg-do run } ! PR 79485 - used to crash because the wrong routine was called. module fmod1 contains subroutine foo(i) implicit none integer, intent(inout) :: i i=i+1 end subroutine foo end module fmod1 module fmod2 use iso_c_binding use fmod1, only : foo_first => foo contains subroutine foo(i) bind(c) implicit none integer, intent(inout) :: i i=i+2 call foo_first(i) end subroutine foo end module fmod2 use fmod2 call foo(i) end
! { dg-do compile } ! PR fortran/66695 - this used to ICE. ! Original test case by Vladimir Fuka. module mod implicit none contains integer function F() end function end module module mod_C use mod implicit none contains subroutine s() bind(C, name="f") integer :: x x = F() end subroutine end module
! { dg-do compile } ! Make sure this error is flagged. subroutine foo() ! { dg-error "is already being used as a SUBROUTINE" } end subroutine foo subroutine bar() bind(C,name="foo") ! { dg-error "is already being used as a SUBROUTINE" } end subroutine bar