aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJohn Ericson <git@JohnEricson.me>2025-08-22 22:24:56 -0400
committerJason Merrill <jason@redhat.com>2025-08-22 22:25:03 -0400
commitf23bac62f46fc296a4d0526ef54824d406c3756c (patch)
treecc1b97d5ba3616503e4605737cb270678f9b687f /gcc
parent5b85364a6dd0bbfd3e26d3346b075a0819be7cd4 (diff)
downloadgcc-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>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gcc.cc185
1 files changed, 77 insertions, 108 deletions
diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index bfa588e..722d42c 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;
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;