On 8/13/25 11:45 AM, John Ericson wrote:
The old C-style was cumbersome make making one responsible for manually
create and pass a closure (separate function and *_info class for
closed-over variables).

I would have liked to redo this with C++ lambdas, so we could:

- derive environment types implicitly
- have fewer stray static functions
- make the return-type polymorphism type safe.

But I was advised on IRC that introducing template specializations in
the driver would a open compile time performance can of worms. It was
instead suggested I do it the old OOP way: this patch.

The old OOP way I don't really like, as it doesn't really reduce
boilerplate, but at least the environment accessing is well-typed now
(no `data` to `info` casts), and the `info->` boilerplate is also gone.
But I am happy to do as suggested. Also I have an idea for a follow-up
patch (after this one) that does allow the use of lambdas without
templating the original function, and so should be a "best of both
worlds" approach.

Thanks to Jason Merill for the idea of using an out-of-line definition
to avoid a large reindentating. That does make this much nicer.

gcc/ChangeLog:

        * gcc.cc (for_each_path): Made method on class below.
        (class find_within_paths): Class below has virtual method for
        callback, instead of function and and data arguments.
        (struct add_to_obstack_info): Renamed without trailing _info.
        (struct add_to_obstack): Now inherits from find_within_paths.
        (add_to_obstack): Became the callback on the above class which
        inherited its name.
        (build_search_list): Updated to use add_to_obstack.
        (struct file_at_path_info): Renamed without trailing _info.
        (struct file_at_path): Now inherits from find_within_paths.
        (file_at_path): Became the callback on the above class which
        inherited its name.
        (find_a_file): Updated to use new file_at_path.
        (struct spec_path_info): Renamed without trailing _info.
        (struct spec_path): Now inherits from find_within_paths.
        (spec_path): Became the callback on the above class which
        inherited its name.
        (do_spec_1): Updated to use new spec_path.

Signed-off-by: John Ericson <g...@johnericson.me>
---
  gcc/gcc.cc | 126 +++++++++++++++++++++++++++++------------------------
  1 file changed, 68 insertions(+), 58 deletions(-)

diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index bfa588ee5f0..930060c2078 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -2774,12 +2774,23 @@ clear_failure_queue (void)
Returns the value returned by CALLBACK. */ -static void *
-for_each_path (const struct path_prefix *paths,
+class find_within_paths
+{
+protected:
+  virtual void *
+  callback (char *);

We don't need to split this declaration across lines. Also, building xgcc fails for me with this patch because this function is not defined:

/usr/bin/ld: gcc.o: in function `find_within_paths::find_within_paths()':
/home/jason/gt/gcc/gcc.cc:2777:(.text._ZN17find_within_pathsC2Ev[_ZN17find_within_pathsC5Ev]+0x9):
 undefined reference to `vtable for find_within_paths'

Doesn't it fail for you? Hmm, perhaps because you're building with optimization and the reference gets optimized away.

It seems enough to add = 0 to define it as pure virtual.

@@ -2936,26 +2947,26 @@ for_each_path (const struct path_prefix *paths,
/* Callback for build_search_list. Adds path to obstack being built. */ -struct add_to_obstack_info {
+struct add_to_obstack : find_within_paths {
    struct obstack *ob;
    bool check_dir;
    bool first_time;
+
+private:
+  void *callback (char *path) override;
  };
-static void *
-add_to_obstack (char *path, void *data)
+void *add_to_obstack::callback (char *path)

...but here in the definition, the qualified-name should be at the beginning of the line.

@@ -3026,34 +3037,35 @@ access_check (const char *name, int mode)
     path.  If the resulting file exists in the right mode, return the
     full pathname to the file.  */
-struct file_at_path_info {
+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;
  };
-static void *
-file_at_path (char *path, void *data)
+void *file_at_path::callback (char *path)

Likewise.

@@ -6008,25 +6019,26 @@ do_self_spec (const char *spec)
/* Callback for processing %D and %I specs. */ -struct spec_path_info {
+struct spec_path : find_within_paths {
    const char *option;
    const char *append;
    size_t append_len;
    bool omit_relative;
    bool separate_options;
    bool realpaths;
+
+private:
+  void *callback (char *path) override;
  };
-static void *
-spec_path (char *path, void *data)
+void *spec_path::callback (char *path)

Likewise.

Jason

Reply via email to