On 8/21/25 1:01 AM, John Ericson wrote:
A follow-up from "driver: Rework for_each_path using C++"
These types are, for all intents and purposes, single-use closure
environment types. It is much more ergonomic to juse use lambdas for
this.
On IRC there was concern about static dispatch and compile times with
lambdas, but I have kept the class hierarchy and virtual methods from
the previous commit that keeps `find_within_paths::for_each_path`
untemplated, and I believe that add addresses the issue.
Note that `struct spec_path` was *not* converted because it is used
multiple times. We could stil 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.
gcc/ChangeLog:
* gcc.cc (struct add_to_obstack): Gone, lambda capture list
replaces it.
(struct file_at_path): Gone, lambda capture list replaces it.
(add_to_obstack::callback): Moved to lambda in
build_search_list.
(file_at_path::callback): Moved to lambda in fine_a_file.
(for_each_path): New tiny templated wrapper for lambda
(build_search_list): Use for_each_path with lambda.
(find_a_file): Use for_each_path with lambda.
Signed-off-by: John Ericson <g...@johnericson.me>
---
gcc/gcc.cc | 142 +++++++++++++++++++++++++----------------------------
1 file changed, 66 insertions(+), 76 deletions(-)
diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index d43a347d120..94d9f760da6 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -2944,30 +2944,28 @@ find_within_paths::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 : find_within_paths {
- struct obstack *ob;
- bool check_dir;
- bool first_time;
-
-private:
- void *callback (char *path) override;
-};
-
-void *
-add_to_obstack::callback (char *path)
+/* This is an adapter for using a lambda. It is separate from
+ find_within_paths::for_each_path in order that the main body of the
+ function (that function) *not* be template-specialised, and just this
+ tiny wrapper is instead. */
+template<typename fun>
+static void *
+for_each_path (const struct path_prefix *paths,
+ bool do_multi,
+ size_t extra_space,
+ fun && callback)
{
- 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;
+ struct adapter : find_within_paths {
+ fun cb;
+ adapter(fun && cb) : cb{cb} {}
+ private:
+ void *callback (char *path) override
+ {
+ return cb(path);
+ }
+ };
+ adapter a{std::move(callback)};
+ return a.for_each_path(paths, do_multi, extra_space);
}
/* Add or change the value of an environment variable, outputting the
@@ -2990,16 +2988,25 @@ 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.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, '=');
- info.for_each_path (paths, do_multi, 0);
+ /* Callback adds path to obstack being built. */
+ for_each_path (paths, do_multi, 0, [ob, &first_time, check_dir](char *path)
-> void* {
Line too long; the simplest fix would be to simplify the capture list to
[&]. Also, the { should be on the next line, per
https://gcc.gnu.org/codingconventions.html#Lambda_Form
@@ -3093,14 +3060,37 @@ 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);
+
+
+ /* 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 (char*) for_each_path (pprefix, do_multi,
+ name_len + suffix_len,
+ [name, suffix, suffix_len, name_len, mode](char
*path) -> void* {
Likewise. Or optionally [=] in this case.
Jason