https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109684
--- Comment #7 from Tomáš Trnka <trnka at scm dot com> --- (In reply to Paul Thomas from comment #5) > Created attachment 55144 [details] > Fix for this PR > > Thanks for reporting this. The patch "fingered" in comment #4 is certainly > responsible for this regression. In particular, it is the first chunk in > resolve.cc that is the culprit. > > The attached patch feels to be a bit of sticking plaster on top of sticking > plaster and so I will go back to hunt down the root cause of these > namespace-less symbols. Thanks for the patch. It seems to mostly do the trick for our huge proprietary F2008 codebase, but some files ultimately fail to compile with the following error (not sure if related or a different bug): in gfc_format_decoder, at fortran/error.cc:1078 0xb01b5a gfc_format_decoder ../../gcc/fortran/error.cc:1078 0x1594c0c pp_format(pretty_printer*, text_info*) ../../gcc/pretty-print.cc:1475 0x10f0c5e diagnostic_report_diagnostic(diagnostic_context*, diagnostic_info*) ../../gcc/diagnostic.cc:1592 0x1789c5d gfc_report_diagnostic ../../gcc/fortran/error.cc:890 0x1789c5d gfc_warning ../../gcc/fortran/error.cc:923 0x1789da7 gfc_warning(int, char const*, ...) ../../gcc/fortran/error.cc:954 0x1852c41 resolve_procedure_expression ../../gcc/fortran/resolve.cc:1957 0x1852c41 resolve_variable ../../gcc/fortran/resolve.cc:6030 0x1852c41 gfc_resolve_expr(gfc_expr*) ../../gcc/fortran/resolve.cc:7266 0x1806880 gfc_resolve_expr(gfc_expr*) ../../gcc/fortran/resolve.cc:7231 0x1806880 resolve_structure_cons ../../gcc/fortran/resolve.cc:1341 0x1858969 resolve_values ../../gcc/fortran/resolve.cc:12771 0x1869492 do_traverse_symtree ../../gcc/fortran/symbol.cc:4190 0x185b02f gfc_traverse_ns(gfc_namespace*, void (*)(gfc_symbol*)) ../../gcc/fortran/symbol.cc:4215 0x185b02f resolve_types ../../gcc/fortran/resolve.cc:17899 0x184cf93 gfc_resolve(gfc_namespace*) ../../gcc/fortran/resolve.cc:17996 0x184fb47 resolve_symbol ../../gcc/fortran/resolve.cc:16567 0x1869492 do_traverse_symtree ../../gcc/fortran/symbol.cc:4190 0x185aee0 gfc_traverse_ns(gfc_namespace*, void (*)(gfc_symbol*)) ../../gcc/fortran/symbol.cc:4215 0x185aee0 resolve_types ../../gcc/fortran/resolve.cc:17880 This seems to be the following assert: gcc_assert (loc->nextc - loc->lb->line >= 0); The backtrace I get from gdb is a little different (there's no resolve_structure_cons in it, for example; I guess that it might be due to LTO): #0 gfc_warning (opt=0, gmsgid=0x1e55748 "Non-RECURSIVE procedure %qs at %L is possibly calling itself recursively. Declare it RECURSIVE or use %<-frecursive%>") at ../../gcc/fortran/error.cc:950 #1 0x0000000001852c42 in resolve_procedure_expression (expr=0x2aefc80) at ../../gcc/fortran/resolve.cc:1957 #2 resolve_variable (e=0x2aefc80) at ../../gcc/fortran/resolve.cc:6030 #3 gfc_resolve_expr (e=0x2aefc80) at ../../gcc/fortran/resolve.cc:7266 #4 0x0000000001806881 in gfc_resolve_expr (e=0x2aefc80) at ../../gcc/fortran/resolve.cc:7231 #5 resolve_structure_cons (expr=<optimized out>, init=1) at ../../gcc/fortran/resolve.cc:1341 #6 0x000000000185896a in resolve_values (sym=0x2ad30c0) at ../../gcc/fortran/resolve.cc:12771 #7 0x0000000001869493 in do_traverse_symtree (st=<optimized out>, st_func=0x0, sym_func=0x1858900 <resolve_values(gfc_symbol*)>) at ../../gcc/fortran/symbol.cc:4190 #8 0x000000000185b030 in gfc_traverse_ns (sym_func=0x1858900 <resolve_values(gfc_symbol*)>, ns=0x3ae65e0) at ../../gcc/fortran/symbol.cc:4215 #9 resolve_types (ns=0x3ae65e0) at ../../gcc/fortran/resolve.cc:17899 #10 0x000000000184cf94 in gfc_resolve (ns=0x3ae65e0) at ../../gcc/fortran/resolve.cc:17996 #11 0x000000000184d022 in gfc_resolve (ns=<optimized out>) at ../../gcc/fortran/resolve.cc:17983 #12 0x000000000184fb48 in resolve_symbol (sym=<optimized out>) at ../../gcc/fortran/resolve.cc:16567 #13 0x0000000001869493 in do_traverse_symtree (st=<optimized out>, st_func=0x0, sym_func=0x184d030 <resolve_symbol(gfc_symbol*)>) at ../../gcc/fortran/symbol.cc:4190 #14 0x000000000185aee1 in gfc_traverse_ns (sym_func=0x184d030 <resolve_symbol(gfc_symbol*)>, ns=0x3697bb0) at ../../gcc/fortran/symbol.cc:4215 #15 resolve_types (ns=0x3697bb0) at ../../gcc/fortran/resolve.cc:17880 #16 0x000000000184cf94 in gfc_resolve (ns=0x3697bb0) at ../../gcc/fortran/resolve.cc:17996 #17 0x000000000184d022 in gfc_resolve (ns=<optimized out>) at ../../gcc/fortran/resolve.cc:17983 #18 0x000000000184fb48 in resolve_symbol (sym=<optimized out>) at ../../gcc/fortran/resolve.cc:16567 #19 0x0000000001869493 in do_traverse_symtree (st=<optimized out>, st_func=0x0, sym_func=0x184d030 <resolve_symbol(gfc_symbol*)>) at ../../gcc/fortran/symbol.cc:4190 #20 0x000000000185aee1 in gfc_traverse_ns (sym_func=0x184d030 <resolve_symbol(gfc_symbol*)>, ns=0x3238a50) at ../../gcc/fortran/symbol.cc:4215 #21 resolve_types (ns=0x3238a50) at ../../gcc/fortran/resolve.cc:17880 #22 0x000000000184cf94 in gfc_resolve (ns=0x3238a50) at ../../gcc/fortran/resolve.cc:17996 #23 0x000000000184d022 in gfc_resolve (ns=<optimized out>) at ../../gcc/fortran/resolve.cc:17983 #24 0x000000000184fb48 in resolve_symbol (sym=<optimized out>) at ../../gcc/fortran/resolve.cc:16567 #25 0x0000000001869493 in do_traverse_symtree (st=<optimized out>, st_func=0x0, sym_func=0x184d030 <resolve_symbol(gfc_symbol*)>) at ../../gcc/fortran/symbol.cc:4190 #26 0x000000000185aee1 in gfc_traverse_ns (sym_func=0x184d030 <resolve_symbol(gfc_symbol*)>, ns=0x2503410) at ../../gcc/fortran/symbol.cc:4215 #27 resolve_types (ns=0x2503410) at ../../gcc/fortran/resolve.cc:17880 #28 0x000000000185aff8 in resolve_types (ns=0x24fd1f0) at ../../gcc/fortran/resolve.cc:17892 #29 0x000000000184cf94 in gfc_resolve (ns=0x24fd1f0) at ../../gcc/fortran/resolve.cc:17996 #30 0x0000000001823689 in gfc_resolve (ns=<optimized out>) at ../../gcc/fortran/resolve.cc:17983 #31 gfc_parse_file () at ../../gcc/fortran/parse.cc:6861 #32 0x000000000187b705 in gfc_be_parse_file () at ../../gcc/fortran/f95-lang.cc:229 #33 0x00000000015b4582 in compile_file () at ../../gcc/toplev.cc:447 #34 0x0000000001592fc6 in do_compile (no_backend=false) at ../../gcc/toplev.cc:2128 #35 toplev::main (this=this@entry=0x7fffffffb82e, argc=<optimized out>, argv=<optimized out>) at ../../gcc/toplev.cc:2282 #36 0x000000000159238f in main (argc=<optimized out>, argv=<optimized out>) at ../../gcc/main.cc:39 (gdb) up #1 0x0000000001852c42 in resolve_procedure_expression (expr=0x2aefc80) at ../../gcc/fortran/resolve.cc:1957 The affected routine is a defined assignment in the ftlDynArray class, used in this case to hold ordinary integers: https://github.com/SCM-NV/ftl/blob/master/src/ftlDynArray.F90_template That defined assignment is impure elemental, if that matters. (gdb) p *sym $7 = {name = 0x7fffea3fd9a0 "assignother", module = 0x7fffea3ec8d0 "ftldynarrayintmodule", declared_at = {nextc = 0x24d0648, lb = 0x24d0600}, ts = {type = BT_UNKNOWN, kind = 0, u = {derived = 0x0, cl = 0x0, pad = 0}, interface = 0x0, is_c_interop = 0, is_iso_c = 0, f90_type = BT_UNKNOWN, deferred = false, interop_kind = 0x0}, attr = {allocatable = 0, dimension = 0, codimension = 0, external = 0, intrinsic = 0, optional = 0, pointer = 0, target = 0, value = 0, volatile_ = 0, temporary = 0, dummy = 0, result = 0, assign = 0, threadprivate = 0, not_always_present = 0, implied_index = 0, subref_array_pointer = 0, proc_pointer = 0, asynchronous = 0, contiguous = 0, fe_temp = 0, automatic = 0, class_pointer = 0, save = SAVE_NONE, data = 0, is_protected = 0, use_assoc = 1, used_in_submodule = 0, use_only = 0, use_rename = 0, imported = 0, host_assoc = 0, in_namelist = 0, in_common = 0, in_equivalence = 0, function = 0, subroutine = 1, procedure = 0, generic = 0, generic_copy = 0, implicit_type = 0, untyped = 0, is_bind_c = 0, extension = 0, is_class = 0, class_ok = 0, vtab = 0, vtype = 0, is_c_interop = 0, is_iso_c = 0, sequence = 0, elemental = 1, pure = 0, recursive = 0, unmaskable = 0, masked = 0, contained = 0, mod_proc = 0, abstract = 0, module_procedure = 0, public_used = 0, implicit_pure = 0, array_outer_dependency = 1, noreturn = 0, entry = 0, entry_master = 0, mixed_entry_master = 0, always_explicit = 1, artificial = 0, referenced = 0, is_main_program = 0, access = ACCESS_UNKNOWN, intent = INTENT_UNKNOWN, flavor = FL_PROCEDURE, if_source = IFSRC_DECL, proc = PROC_MODULE, cray_pointer = 0, cray_pointee = 0, alloc_comp = 0, pointer_comp = 0, proc_pointer_comp = 0, private_comp = 0, zero_comp = 0, coarray_comp = 0, lock_comp = 0, event_comp = 0, defined_assign_comp = 0, unlimited_polymorphic = 0, has_dtio_procs = 0, caf_token = 0, select_type_temporary = 0, select_rank_temporary = 0, associate_var = 0, pdt_kind = 0, pdt_len = 0, pdt_type = 0, pdt_template = 0, pdt_array = 0, pdt_string = 0, omp_udr_artificial_var = 0, omp_declare_target = 0, omp_declare_target_link = 0, omp_device_type = OMP_DEVICE_TYPE_UNSET, oacc_declare_create = 0, oacc_declare_copyin = 0, oacc_declare_deviceptr = 0, oacc_declare_device_resident = 0, oacc_declare_link = 0, oacc_routine_lop = OACC_ROUTINE_LOP_NONE, oacc_routine_nohost = 0, ext_attr = 0, volatile_ns = 0x0, asynchronous_ns = 0x0}, generic = 0x0, component_access = ACCESS_UNKNOWN, formal = 0x381f040, formal_ns = 0x3ae65e0, f2k_derived = 0x0, param_list = 0x0, value = 0x0, as = 0x0, result = 0x0, components = 0x0, cp_pointer = 0x0, entry_id = 0, hash_value = 0, common_next = 0x0, common_head = 0x0, dummy_order = 0, namelist = 0x0, namelist_tail = 0x0, tlink = 0x0, old_symbol = 0x0, mark = 0, comp_mark = 0, data_mark = 0, dev_mark = 0, gen_mark = 0, reduc_mark = 0, gfc_new = 0, equiv_built = 0, forall_index = 0, fn_result_spec = 0, resolve_symbol_called = 1, abr_modproc_decl = 0, error = 0, maybe_array = 0, pass_as_value = 0, refs = 1, ns = 0x3697bb0, backend_decl = 0x0, from_intmod = INTMOD_NONE, intmod_sym_id = 0, binding_label = 0x0, common_block = 0x0, assoc = 0x0, dt_next = 0x0} expr->where is full of zeros (so is *expr, mostly): (gdb) p *expr $9 = {expr_type = EXPR_VARIABLE, ts = {type = BT_PROCEDURE, kind = 0, u = {derived = 0x0, cl = 0x0, pad = 0}, interface = 0x0, is_c_interop = 0, is_iso_c = 0, f90_type = BT_UNKNOWN, deferred = false, interop_kind = 0x0}, rank = 0, shape = 0x0, symtree = 0x3fc73b0, ref = 0x0, where = { nextc = 0x0, lb = 0x0}, base_expr = 0x0, is_snan = 0, error = 0, user_operator = 0, mold = 0, must_finalize = 0, no_bounds_check = 0, external_blas = 0, do_not_resolve_again = 0, do_not_warn = 0, from_constructor = 0, representation = {length = 0, string = 0x0}, boz = {len = 0, rdx = 0, str = 0x0}, value = {logical = 0, iokind = M_READ, integer = {{_mp_alloc = 0, _mp_size = 0, _mp_d = 0x0}}, real = {{_mpfr_prec = 0, _mpfr_sign = 0, _mpfr_exp = 0, _mpfr_d = 0x0}}, complex = {{re = {{_mpfr_prec = 0, _mpfr_sign = 0, _mpfr_exp = 0, _mpfr_d = 0x0}}, im = {{ _mpfr_prec = 0, _mpfr_sign = 0, _mpfr_exp = 0, _mpfr_d = 0x0}}}}, op = {op = GFC_INTRINSIC_BEGIN, uop = 0x0, op1 = 0x0, op2 = 0x0}, function = {actual = 0x0, name = 0x0, isym = 0x0, esym = 0x0}, compcall = {actual = 0x0, name = 0x0, base_object = 0x0, tbp = 0x0, ignore_pass = 0, assign = 0}, character = {length = 0, string = 0x0}, constructor = 0x0}, param_list = 0x0} This all happens when compiling one of our modules with lots of dependencies, so I can't easily turn it into a standalone testcase. I could possibly just send you the source together with all the .mod dependencies, but isolating it further will take me a while (if needed). Another defined assignment routine triggering the same warning/assert is even weirder, since I can't imagine how this could end up calling itself recursively: impure elemental subroutine AssignOther(self, other) class(InputType), intent(inout) :: self type(InputType), intent(in) :: other ! TODO: Implement actual assignment. (Default assignment will not do the right job, so we disable it for now.) call StopIt('Developer error: InputType is not assignable.') DontWarnUnused(self) DontWarnUnused(other) end subroutine (StopIt is an external subroutine which just does some cleanup and stops the program. This type does have a finalizer, but it certainly shouldn't trigger the assignment again.) type :: InputType (snip) final :: Finalizer generic , public :: assignment(=) => AssignOther procedure, private :: AssignOther end type subroutine DeletePrivate(self) class(InputType), intent(inout) :: self self%quiet = .false. self%stringLeafs = .false. self%stopOnError = .true. self%hasError = .true. call self%errorMessage%Delete() call self%prog%Delete() call self%inputDef%Destroy() if (associated(self%pRoot)) call self%json%Destroy(self%pRoot) end subroutine ! subroutine Finalizer(self) type(InputType), intent(inout) :: self call self%Delete() end subroutine In the end I ended up having to compile everything -frecursive because this issue pops up in many different modules and hunting them all down is really tedious (having to extract the gfortran commandline out from our buildsystem, get the corresponding f951 command line, run f951 under gdb to break on gfc_warning, check *sym). Compiling with this patch also makes PR103931 rear its ugly head in one module, which does not happen when the offending commit in comment #4 is reverted instead. But that PR is weird enough as it is, likely some minor changes in the module file layout are all that's needed to trigger it. > I fear that you will have to make your procedures impure for the time being > or, if you don't need the added finalization features, revert to a previous > version of gfortran. Well, our codebase uses F2008 features extensively, and defined assignments plus finalization are by far the two most prominent sources of bugs in both ifort and gfortran, so we already have layers upon layers of workarounds for those in place. Any change to that mix is prone to break something else. Your work on this in gfortran will likely allow us to get rid of quite some of those workarounds, so it is greatly appreciated! Indeed, running with gfortran 12 is certainly an option, but 13 with the revert seems to do the job as well. We want to make our code compile with GCC 13 before that version is picked up by major distros and makes the life of our developers miserable. (I'm sure the whole world would be much better off if we could just include our codebase in the regression test suites of both ifort and gfortran :-))