Hello world,

the attached patch regtests cleanly and fixes a recent regression
introduced by myself and discovered by Jürgen Reuter.

OK for trunk?

Best regards

        Thomas

Fix PR 125379, ICE with BIND(C) and PRIVATE

This fixes a recent regression introduced by my patch for PR 125902. The
problem was that, for private entities, the symbols cannot be found by
gfc_find_symbol a gsymbol's namespace.  This patch uses the approach of
iterating over all the symbols to look for the right name if direct
lookup fails.

gcc/fortran/ChangeLog:

        * gfortran.h (gfc_find_symbol_by_name): Add prototype.
        * resolve.cc (gfc_verify_binding_labels): Call gfc_find_symbol_by_name
        if direct lookup fails.
        * symbol.cc (compare_target_sym_name): New function.
        (gfc_find_symbol_by_name): New function.

gcc/testsuite/ChangeLog:

        * gfortran.dg/binding_label_tests_38.f90: New test.
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 37a8582e36d..fa8b9653527 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -3808,6 +3808,8 @@ int gfc_find_symbol (const char *, gfc_namespace *, int, gfc_symbol **);
 bool gfc_find_sym_tree (const char *, gfc_namespace *, int, gfc_symtree **);
 int gfc_get_symbol (const char *, gfc_namespace *, gfc_symbol **,
 		    locus * = NULL);
+bool gfc_find_symbol_by_name (const char *, gfc_namespace *,
+				    gfc_symbol **);
 bool gfc_verify_c_interop (gfc_typespec *);
 bool gfc_verify_c_interop_param (gfc_symbol *);
 bool verify_bind_c_sym (gfc_symbol *, gfc_typespec *, int, gfc_common_head *);
diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index 6d2ebed813f..a997ea757ca 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -15084,6 +15084,13 @@ gfc_verify_binding_labels (gfc_symbol *sym)
 	{
 	  gfc_symbol *global_sym;
 	  gfc_find_symbol (gsym->sym_name, gsym->ns, 0, &global_sym);
+
+	  /* For when the symtree does not match the symbol name, which can happen
+	     in modules with PRIVATE.  */
+
+	  if (global_sym == NULL)
+	    gfc_find_symbol_by_name (gsym->sym_name, gsym->ns, &global_sym);
+
 	  gcc_assert (global_sym);
 
 	  /* If subroutines and functions are conflated, there is little point
diff --git a/gcc/fortran/symbol.cc b/gcc/fortran/symbol.cc
index e1b49b0ba0d..a49033e3ea7 100644
--- a/gcc/fortran/symbol.cc
+++ b/gcc/fortran/symbol.cc
@@ -5711,3 +5711,33 @@ gfc_get_spec_ns (gfc_symbol *sym)
 
   return sym->ns;
 }
+
+/* This section deals with looking up a symbol when the symtree name and symbol
+   name do not agree, so gfc_find_symbol() cannot be used.  */
+
+static gfc_symbol* found_sym;		/* Where to store the symbol.  */
+static const char* sym_target_name;	/* What name to look for.  */
+
+/* Helper function.  */
+
+static void
+compare_target_sym_name (gfc_symbol *sym)
+{
+  if (strcmp(sym->name, sym_target_name) == 0)
+    found_sym = sym;
+}
+
+/* Search for a symbol when the symtree name may be different from the
+   symbol name.  Return true if found.  */
+
+bool
+gfc_find_symbol_by_name (const char *name, gfc_namespace *ns,
+			       gfc_symbol **result)
+{
+  found_sym = NULL;
+  sym_target_name = name;
+
+  do_traverse_symtree (ns->sym_root, NULL, compare_target_sym_name);
+  *result = found_sym;
+  return result != 0;
+}
diff --git a/gcc/testsuite/gfortran.dg/binding_label_tests_38.f90 b/gcc/testsuite/gfortran.dg/binding_label_tests_38.f90
new file mode 100644
index 00000000000..b212fa503c2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/binding_label_tests_38.f90
@@ -0,0 +1,56 @@
+! { dg-do compile }
+! PR fortran/125379 - this gave an ICE due to C binding private
+! globals.
+! Test case by Juergen Reuter.
+
+module blha_olp_interfaces
+  use, intrinsic :: iso_c_binding !NODEP!                                                                                                                                                                     
+  use, intrinsic :: iso_fortran_env
+  implicit none
+  private
+  public :: olp_polvec
+  type :: blha_driver_t
+    procedure(olp_polvec), nopass, pointer :: blha_olp_polvec => null ()
+  end type blha_driver_t
+
+  interface
+    subroutine olp_polvec (eps) bind(C)
+      import
+      real(kind = c_double), dimension(0:7), intent(out) :: eps
+    end subroutine
+  end interface
+end module blha_olp_interfaces
+
+
+module pcm_base
+  use blha_olp_interfaces
+  implicit none
+  private
+end module pcm_base
+
+
+module api
+  use pcm_base
+  implicit none
+  private
+  public :: whizard_api_t
+
+  type :: whizard_api_t
+     private
+     character(:), allocatable :: logfile
+  end type whizard_api_t
+
+end module api
+
+function whizard_get_char (whizard_handle) result (stat) bind (C)
+  use iso_c_binding, only: c_ptr  !NODEP!                                                                                                                                                                     
+  use iso_c_binding, only: c_f_pointer  !NODEP!                                                                                                                                                               
+  use api, only: whizard_api_t
+  implicit none
+  integer :: stat
+  type(c_ptr), intent(in) :: whizard_handle
+  type(whizard_api_t), pointer :: whizard
+
+  call c_f_pointer (whizard_handle, whizard)
+
+end function whizard_get_char

Reply via email to