diff options
author | John Ericson <git@JohnEricson.me> | 2025-08-22 22:24:56 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2025-08-22 22:25:03 -0400 |
commit | f23bac62f46fc296a4d0526ef54824d406c3756c (patch) | |
tree | cc1b97d5ba3616503e4605737cb270678f9b687f | |
parent | 5b85364a6dd0bbfd3e26d3346b075a0819be7cd4 (diff) | |
download | gcc-f23bac62f46fc296a4d0526ef54824d406c3756c.zip gcc-f23bac62f46fc296a4d0526ef54824d406c3756c.tar.gz gcc-f23bac62f46fc296a4d0526ef54824d406c3756c.tar.bz2 |
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 <git@JohnEricson.me>
Reviewed-by: Jason Merrill <jason@redhat.com>
-rw-r--r-- | gcc/gcc.cc | 185 |
1 files changed, 77 insertions, 108 deletions
@@ -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; 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; |