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.
---
gcc/gcc.cc | 140 +++++++++++++++++++++++++----------------------------
1 file changed, 66 insertions(+), 74 deletions(-)
diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index 930060c2078..3a7dc869261 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -2945,29 +2945,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 +2989,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* {
+ 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 *);
@@ -3033,43 +3041,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 : find_within_paths {
- const char *name;
- const char *suffix;
- int name_len;
- int suffix_len;
- int mode;
-
-private:
- void *callback (char *path) override;
-};
-
-void *file_at_path::callback (char *path)
-{
- 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;
-}
/* Search for NAME using the prefix list PREFIXES. MODE is passed to
access to check permissions. If DO_MULTI is true, search multilib
@@ -3080,8 +3051,6 @@ static char *
find_a_file (const struct path_prefix *pprefix, const char *name, int mode,
bool do_multi)
{
- struct file_at_path info;
-
/* Find the filename in question (special case for absolute paths). */
if (IS_ABSOLUTE_PATH (name))
@@ -3092,14 +3061,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* {
+ size_t len = strlen (path);
+
+ memcpy (path + len, name, name_len);
+ len += name_len;
- return (char*) info.for_each_path (pprefix, do_multi,
- info.name_len + info.suffix_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
--
2.49.0