[gcc r17-3322] fortran: [PR126872] BIND(C) entities must keep default ELF visibility
Jerry DeLisle via Gcc-cvs <[email protected]>
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:75136eabafd2028a04d47720ea87548df47e2578 commit r17-3322-g75136eabafd2028a04d47720ea87548df47e2578 Author: Jerry DeLisle <[email protected]> Date: Fri Aug 14 12:20:35 2026 -0700 fortran: [PR126872] BIND(C) entities must keep default ELF visibility Assisted-by: Claude Opus 5 A binding label gives an entity external linkage, so PRIVATE hides only the Fortran name and must not lower the symbol's ELF visibility. Three sites gave hidden visibility to PRIVATE module entities without exempting binding labels, so a BIND(C) procedure or variable in a module with a PRIVATE default was not exported from a shared library. The procedure case is a regression from r17-913 (PR fortran/125430), backported to the 16 branch as r16-9113 and so present in 16.2.0 but not 16.1.0; the variable case dates from r6-2637, the introduction of submodules (PR fortran/52846). Module entities without a binding label keep the hidden visibility that lets submodules reach them via host association. gcc/fortran/ChangeLog: PR fortran/126872 * trans-decl.cc (gfc_finish_var_decl): Drop the unreachable hidden-visibility case in the BIND(C) block. Do not give hidden visibility to a PRIVATE module variable with a binding label. (build_function_decl): Do not give hidden visibility to a PRIVATE module procedure with a binding label. gcc/testsuite/ChangeLog: PR fortran/126872 * gfortran.dg/bind_c_private_1.f90: New test. Diff: --- gcc/fortran/trans-decl.cc | 17 +++++++-------- gcc/testsuite/gfortran.dg/bind_c_private_1.f90 | 30 ++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc index 47b28c1d0032..e277f2b2ccc6 100644 --- a/gcc/fortran/trans-decl.cc +++ b/gcc/fortran/trans-decl.cc @@ -709,14 +709,11 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym) into common space, then C cannot initialize global Fortran variables that it interoperates with and the draft says that either Fortran or C should be able to initialize it (but not - both, of course.) (J3/04-007, section 15.3). */ + both, of course.) (J3/04-007, section 15.3). A binding label has + external linkage, so PRIVATE hides only the Fortran name and must + not restrict the symbol's visibility. */ 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. */ @@ -742,7 +739,8 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym) TREE_PUBLIC (decl) = 1; TREE_STATIC (decl) = 1; - if (sym->attr.access == ACCESS_PRIVATE && !sym->attr.public_used) + if (sym->attr.access == ACCESS_PRIVATE && !sym->attr.public_used + && !sym->binding_label) { DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; DECL_VISIBILITY_SPECIFIED (decl) = true; @@ -2600,9 +2598,10 @@ build_function_decl (gfc_symbol * sym, bool global) /* Mirror the variable treatment (see gfc_finish_var_decl): PRIVATE module procedures get global linkage but hidden visibility so the symbol is reachable from submodules in the same link without being - exported to external DSOs. */ + exported to external DSOs. A binding label has external linkage, + so PRIVATE hides only the Fortran name. */ if (in_module_contains && sym->attr.access == ACCESS_PRIVATE - && !sym->attr.public_used) + && !sym->attr.public_used && !sym->binding_label) { DECL_VISIBILITY (fndecl) = VISIBILITY_HIDDEN; DECL_VISIBILITY_SPECIFIED (fndecl) = true; diff --git a/gcc/testsuite/gfortran.dg/bind_c_private_1.f90 b/gcc/testsuite/gfortran.dg/bind_c_private_1.f90 new file mode 100644 index 000000000000..9caacbb21c7d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/bind_c_private_1.f90 @@ -0,0 +1,30 @@ +! { dg-do compile } +! { dg-require-visibility "" } +! +! PR fortran/126872 +! +! A binding label gives external linkage, so PRIVATE must hide only the +! Fortran name and must not give the symbol hidden ELF visibility. +! Module entities without a binding label keep the hidden visibility +! introduced by PR fortran/125430. + +module m + use iso_c_binding + implicit none + private + integer(c_int), bind(C, name="bc_var") :: bc_var + integer :: plain_var +contains + subroutine bc_named() bind(C, name="bc_named") + end subroutine bc_named + subroutine bc_unnamed() bind(C) + end subroutine bc_unnamed + subroutine plain_sub() + end subroutine plain_sub +end module m + +! { dg-final { scan-assembler-not "\\.hidden\[ \t\]+bc_var" } } +! { dg-final { scan-assembler-not "\\.hidden\[ \t\]+bc_named" } } +! { dg-final { scan-assembler-not "\\.hidden\[ \t\]+bc_unnamed" } } +! { dg-final { scan-assembler "\\.hidden\[ \t\]+__m_MOD_plain_var" } } +! { dg-final { scan-assembler "\\.hidden\[ \t\]+__m_MOD_plain_sub" } }