On Wed, 3 Sep 2025, Tobias Burnus wrote: > > Hi Andre, hi all, > > Andre Vehreschild wrote: > > I am experiencing a strange issue with gfortran. Compiling a simple program: > > $ cat end.f90 > end > $ gfortran end.f90 -o end > f951: Fatal Error: Cannot open pre-included file '\xe0\xd4\xf2,' > compilation terminated. > > From your description, it sounds as if your Stage 1 compiler > of Fedora 41 is miscompiling gfortran/f951. > > I have not understood whether a normal bootstrap, i.e. where > gfortran is only build during Stage 2 also fails or only a > non-bootstrap / --enable-stage1-languages=fortran,... built one. > > * * * > > Yes, the program is doing nothing, but can not be compiled. The pre-included > file name changes randomly. Looks like something is either overwritten or > not initialized properly. I bisected this issue down to > commit f23bac62f46fc296a4d0526ef54824d406c3756c > Author: John Ericson <[email protected]> > Date: Fri Aug 22 22:24:56 2025 -0400 > > driver: Rework for_each_path using C++ > > but I do not see, why this should affect gfortran's ability to build a simple > program. > > Well, from your valgrind output, the issue is in for_each_path > and 'pre-included' is also run for empty programs - as the name implies > And there is also a > -fpre-include=/usr/include/finclude/math-vector-fortran.h > in your f951 call, which is used to ensure that GLIBC's vector math > functions are used. > > * * * > > I don't feel like checking whether there is a bug in > commit r16-3354-gf23bac62f46fc2 itself or only an issue in the F41 system > compiler.
There seems to be a bug in r16-3354 that may be causing what the crash that you're seeing: > From f23bac62f46fc296a4d0526ef54824d406c3756c Mon Sep 17 00:00:00 2001 > From: John Ericson <[email protected]> > Date: Fri, 22 Aug 2025 22:24:56 -0400 > Subject: driver: Rework for_each_path using C++ > > The old C-style was cumbersome make making one responsible for manually > creating and passing in two parts a closure (separate function and > *_info class for closed-over variables). > > With C++ lambdas, we can just: > > - derive environment types implicitly > - have fewer stray static functions > > Also thanks to templates we can > - make the return type polymorphic, to avoid casting pointee types. > > Note that `struct spec_path` was *not* converted because it is used > multiple times. We could still convert to a lambda, but we would want to > put the for_each_path call with that lambda inside a separate function > anyways, to support the multiple callers. Unlike the other two > refactors, it is not clear that this one would make anything shorter. > Instead, I define the `operator()` explicitly. Keeping the explicit > struct gives us some nice "named arguments", versus the wrapper function > alternative, too. > > gcc/ChangeLog: > > * gcc.cc (for_each_path): templated, to make passing lambdas > possible/easy/safe, and to have a polymorphic return type. > (struct add_to_obstack_info): Deleted, lambda captures replace > it. > (add_to_obstack): Moved to lambda in build_search_list. > (build_search_list): Has above lambda now. > (struct file_at_path_info): Deleted, lambda captures replace > it. > (file_at_path): Moved to lambda in find_a_file. > (find_a_file): Has above lambda now. > (struct spec_path_info): Reamed to just struct spec_path. > (struct spec_path): New name. > (spec_path): Rnamed to spec_path::operator() > (spec_path::operator()): New name > (do_spec_1): Updated for_each_path call sites. > > Signed-off-by: John Ericson <[email protected]> > Reviewed-by: Jason Merrill <[email protected]> > --- > gcc/gcc.cc | 185 > +++++++++++++++++++++++++------------------------------------ > 1 file changed, 77 insertions(+), 108 deletions(-) > > diff --git a/gcc/gcc.cc b/gcc/gcc.cc > index bfa588ee5f04..722d42c69683 100644 > --- a/gcc/gcc.cc > +++ b/gcc/gcc.cc > @@ -2774,12 +2774,12 @@ clear_failure_queue (void) > > Returns the value returned by CALLBACK. */ > > -static void * > +template<typename fun> > +auto * > for_each_path (const struct path_prefix *paths, > bool do_multi, > size_t extra_space, > - void *(*callback) (char *, void *), > - void *callback_info) > + fun && callback) > { > struct prefix_list *pl; > const char *multi_dir = NULL; > @@ -2788,7 +2788,7 @@ for_each_path (const struct path_prefix *paths, > const char *multi_suffix; > const char *just_multi_suffix; > char *path = NULL; > - void *ret = NULL; > + decltype (callback (nullptr)) ret; 'ret' is no longer initialized here, so presumably some code paths now use it uninitialized. > bool skip_multi_dir = false; > bool skip_multi_os_dir = false; > > @@ -2839,7 +2839,7 @@ for_each_path (const struct path_prefix *paths, > if (!skip_multi_dir) > { > memcpy (path + len, multi_suffix, suffix_len + 1); > - ret = callback (path, callback_info); > + ret = callback (path); > if (ret) > break; > } > @@ -2850,7 +2850,7 @@ for_each_path (const struct path_prefix *paths, > && pl->require_machine_suffix == 2) > { > memcpy (path + len, just_multi_suffix, just_suffix_len + 1); > - ret = callback (path, callback_info); > + ret = callback (path); > if (ret) > break; > } > @@ -2860,7 +2860,7 @@ for_each_path (const struct path_prefix *paths, > && !pl->require_machine_suffix && multiarch_dir) > { > memcpy (path + len, multiarch_suffix, multiarch_len + 1); > - ret = callback (path, callback_info); > + ret = callback (path); > if (ret) > break; > } > @@ -2888,7 +2888,7 @@ for_each_path (const struct path_prefix *paths, > else > path[len] = '\0'; > > - ret = callback (path, callback_info); > + ret = callback (path); > if (ret) > break; > } > @@ -2934,31 +2934,6 @@ for_each_path (const struct path_prefix *paths, > return ret; > } > > -/* Callback for build_search_list. Adds path to obstack being built. */ > - > -struct add_to_obstack_info { > - struct obstack *ob; > - bool check_dir; > - bool first_time; > -}; > - > -static void * > -add_to_obstack (char *path, void *data) > -{ > - struct add_to_obstack_info *info = (struct add_to_obstack_info *) data; > - > - if (info->check_dir && !is_directory (path)) > - return NULL; > - > - if (!info->first_time) > - obstack_1grow (info->ob, PATH_SEPARATOR); > - > - obstack_grow (info->ob, path, strlen (path)); > - > - info->first_time = false; > - return NULL; > -} > - > /* Add or change the value of an environment variable, outputting the > change to standard error if in verbose mode. */ > static void > @@ -2979,16 +2954,26 @@ static char * > build_search_list (const struct path_prefix *paths, const char *prefix, > bool check_dir, bool do_multi) > { > - struct add_to_obstack_info info; > - > - info.ob = &collect_obstack; > - info.check_dir = check_dir; > - info.first_time = true; > + struct obstack *const ob = &collect_obstack; > + bool first_time = true; > > obstack_grow (&collect_obstack, prefix, strlen (prefix)); > obstack_1grow (&collect_obstack, '='); > > - for_each_path (paths, do_multi, 0, add_to_obstack, &info); > + /* Callback adds path to obstack being built. */ > + for_each_path (paths, do_multi, 0, [&](char *path) -> void* > + { > + if (check_dir && !is_directory (path)) > + return NULL; > + > + if (!first_time) > + obstack_1grow (ob, PATH_SEPARATOR); > + > + obstack_grow (ob, path, strlen (path)); > + > + first_time = false; > + return NULL; > + }); > > obstack_1grow (&collect_obstack, '\0'); > return XOBFINISH (&collect_obstack, char *); > @@ -3022,42 +3007,6 @@ access_check (const char *name, int mode) > return access (name, mode); > } > > -/* Callback for find_a_file. Appends the file name to the directory > - path. If the resulting file exists in the right mode, return the > - full pathname to the file. */ > - > -struct file_at_path_info { > - const char *name; > - const char *suffix; > - int name_len; > - int suffix_len; > - int mode; > -}; > - > -static void * > -file_at_path (char *path, void *data) > -{ > - struct file_at_path_info *info = (struct file_at_path_info *) data; > - size_t len = strlen (path); > - > - memcpy (path + len, info->name, info->name_len); > - len += info->name_len; > - > - /* Some systems have a suffix for executable files. > - So try appending that first. */ > - if (info->suffix_len) > - { > - memcpy (path + len, info->suffix, info->suffix_len + 1); > - if (access_check (path, info->mode) == 0) > - return path; > - } > - > - path[len] = '\0'; > - if (access_check (path, info->mode) == 0) > - return path; > - > - return NULL; > -} > > /* Search for NAME using the prefix list PREFIXES. MODE is passed to > access to check permissions. If DO_MULTI is true, search multilib > @@ -3068,8 +3017,6 @@ static char * > find_a_file (const struct path_prefix *pprefix, const char *name, int mode, > bool do_multi) > { > - struct file_at_path_info info; > - > /* Find the filename in question (special case for absolute paths). */ > > if (IS_ABSOLUTE_PATH (name)) > @@ -3080,15 +3027,38 @@ find_a_file (const struct path_prefix *pprefix, const > char *name, int mode, > return NULL; > } > > - info.name = name; > - info.suffix = (mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : ""; > - info.name_len = strlen (info.name); > - info.suffix_len = strlen (info.suffix); > - info.mode = mode; > + const char *suffix = (mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : ""; > + const int name_len = strlen (name); > + const int suffix_len = strlen (suffix); > > - return (char*) for_each_path (pprefix, do_multi, > - info.name_len + info.suffix_len, > - file_at_path, &info); > + > + /* Callback appends the file name to the directory path. If the > + resulting file exists in the right mode, return the full pathname > + to the file. */ > + return for_each_path (pprefix, do_multi, > + name_len + suffix_len, > + [=](char *path) -> char* > + { > + size_t len = strlen (path); > + > + memcpy (path + len, name, name_len); > + len += name_len; > + > + /* Some systems have a suffix for executable files. > + So try appending that first. */ > + if (suffix_len) > + { > + memcpy (path + len, suffix, suffix_len + 1); > + if (access_check (path, mode) == 0) > + return path; > + } > + > + path[len] = '\0'; > + if (access_check (path, mode) == 0) > + return path; > + > + return NULL; > + }); > } > > /* Specialization of find_a_file for programs that also takes into account > @@ -6008,25 +5978,26 @@ do_self_spec (const char *spec) > > /* Callback for processing %D and %I specs. */ > > -struct spec_path_info { > +struct spec_path { > const char *option; > const char *append; > size_t append_len; > bool omit_relative; > bool separate_options; > bool realpaths; > + > + void *operator() (char *path); > }; > > -static void * > -spec_path (char *path, void *data) > +void * > +spec_path::operator() (char *path) > { > - struct spec_path_info *info = (struct spec_path_info *) data; > size_t len = 0; > char save = 0; > > /* The path must exist; we want to resolve it to the realpath so that this > can be embedded as a runpath. */ > - if (info->realpaths) > + if (realpaths) > path = lrealpath (path); > > /* However, if we failed to resolve it - perhaps because there was a bogus > @@ -6034,23 +6005,23 @@ spec_path (char *path, void *data) > if (!path) > return NULL; > > - if (info->omit_relative && !IS_ABSOLUTE_PATH (path)) > + if (omit_relative && !IS_ABSOLUTE_PATH (path)) > return NULL; > > - if (info->append_len != 0) > + if (append_len != 0) > { > len = strlen (path); > - memcpy (path + len, info->append, info->append_len + 1); > + memcpy (path + len, append, append_len + 1); > } > > if (!is_directory (path)) > return NULL; > > - do_spec_1 (info->option, 1, NULL); > - if (info->separate_options) > + do_spec_1 (option, 1, NULL); > + if (separate_options) > do_spec_1 (" ", 0, NULL); > > - if (info->append_len == 0) > + if (append_len == 0) > { > len = strlen (path); > save = path[len - 1]; > @@ -6062,7 +6033,7 @@ spec_path (char *path, void *data) > do_spec_1 (" ", 0, NULL); > > /* Must not damage the original path. */ > - if (info->append_len == 0) > + if (append_len == 0) > path[len - 1] = save; > > return NULL; > @@ -6250,7 +6221,7 @@ do_spec_1 (const char *spec, int inswitch, const char > *soft_matched_part) > that we search for startfiles. */ > case 'D': > { > - struct spec_path_info info; > + struct spec_path info; > > info.option = "-L"; > info.append_len = 0; > @@ -6267,13 +6238,13 @@ do_spec_1 (const char *spec, int inswitch, const char > *soft_matched_part) > info.separate_options = false; > info.realpaths = false; > > - for_each_path (&startfile_prefixes, true, 0, spec_path, &info); > + for_each_path (&startfile_prefixes, true, 0, info); > } > break; > > case 'P': > { > - struct spec_path_info info; > + struct spec_path info; > > info.option = RUNPATH_OPTION; > info.append_len = 0; > @@ -6282,7 +6253,7 @@ do_spec_1 (const char *spec, int inswitch, const char > *soft_matched_part) > /* We want to embed the actual paths that have the libraries. */ > info.realpaths = true; > > - for_each_path (&startfile_prefixes, true, 0, spec_path, &info); > + for_each_path (&startfile_prefixes, true, 0, info); > } > break; > > @@ -6561,7 +6532,7 @@ do_spec_1 (const char *spec, int inswitch, const char > *soft_matched_part) > > case 'I': > { > - struct spec_path_info info; > + struct spec_path info; > > if (multilib_dir) > { > @@ -6609,8 +6580,7 @@ do_spec_1 (const char *spec, int inswitch, const char > *soft_matched_part) > info.separate_options = true; > info.realpaths = false; > > - for_each_path (&include_prefixes, false, info.append_len, > - spec_path, &info); > + for_each_path (&include_prefixes, false, info.append_len, info); > > info.append = "include-fixed"; > if (*sysroot_hdrs_suffix_spec) > @@ -6623,14 +6593,13 @@ do_spec_1 (const char *spec, int inswitch, const char > *soft_matched_part) > info.append = concat (info.append, dir_separator_str, > multiarch_dir, NULL); > info.append_len = strlen (info.append); > - for_each_path (&include_prefixes, false, info.append_len, > - spec_path, &info); > + for_each_path (&include_prefixes, false, > + info.append_len, info); > > info.append = "include-fixed"; > } > info.append_len = strlen (info.append); > - for_each_path (&include_prefixes, false, info.append_len, > - spec_path, &info); > + for_each_path (&include_prefixes, false, info.append_len, info); > } > break; > > -- > cgit
