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 *); + +public: + void * + for_each_path (const struct path_prefix *paths, + bool do_multi, + size_t extra_space); +}; + +void * +find_within_paths::for_each_path (const struct path_prefix *paths, bool do_multi, - size_t extra_space, - void *(*callback) (char *, void *), - void *callback_info) + size_t extra_space) { struct prefix_list *pl; const char *multi_dir = NULL; @@ -2839,7 +2850,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 +2861,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 +2871,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 +2899,7 @@ for_each_path (const struct path_prefix *paths, else path[len] = '\0'; - ret = callback (path, callback_info); + ret = callback (path); if (ret) break; } @@ -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) { - struct add_to_obstack_info *info = (struct add_to_obstack_info *) data; - - if (info->check_dir && !is_directory (path)) + if (check_dir && !is_directory (path)) return NULL; - if (!info->first_time) - obstack_1grow (info->ob, PATH_SEPARATOR); + if (!first_time) + obstack_1grow (ob, PATH_SEPARATOR); - obstack_grow (info->ob, path, strlen (path)); + obstack_grow (ob, path, strlen (path)); - info->first_time = false; + first_time = false; return NULL; } @@ -2979,7 +2990,7 @@ 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; + struct add_to_obstack info; info.ob = &collect_obstack; info.check_dir = check_dir; @@ -2988,7 +2999,7 @@ build_search_list (const struct path_prefix *paths, const char *prefix, obstack_grow (&collect_obstack, prefix, strlen (prefix)); obstack_1grow (&collect_obstack, '='); - for_each_path (paths, do_multi, 0, add_to_obstack, &info); + info.for_each_path (paths, do_multi, 0); obstack_1grow (&collect_obstack, '\0'); return XOBFINISH (&collect_obstack, char *); @@ -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) { - 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; + memcpy (path + len, name, name_len); + len += name_len; /* Some systems have a suffix for executable files. So try appending that first. */ - if (info->suffix_len) + if (suffix_len) { - memcpy (path + len, info->suffix, info->suffix_len + 1); - if (access_check (path, info->mode) == 0) + memcpy (path + len, suffix, suffix_len + 1); + if (access_check (path, mode) == 0) return path; } path[len] = '\0'; - if (access_check (path, info->mode) == 0) + if (access_check (path, mode) == 0) return path; return NULL; @@ -3068,7 +3080,7 @@ static char * find_a_file (const struct path_prefix *pprefix, const char *name, int mode, bool do_multi) { - struct file_at_path_info info; + struct file_at_path info; /* Find the filename in question (special case for absolute paths). */ @@ -3086,9 +3098,8 @@ find_a_file (const struct path_prefix *pprefix, const char *name, int mode, info.suffix_len = strlen (info.suffix); info.mode = mode; - return (char*) for_each_path (pprefix, do_multi, - info.name_len + info.suffix_len, - file_at_path, &info); + return (char*) info.for_each_path (pprefix, do_multi, + info.name_len + info.suffix_len); } /* Specialization of find_a_file for programs that also takes into account @@ -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) { - 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 +6046,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 +6074,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 +6262,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 +6279,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); + info.for_each_path (&startfile_prefixes, true, 0); } break; case 'P': { - struct spec_path_info info; + struct spec_path info; info.option = RUNPATH_OPTION; info.append_len = 0; @@ -6282,7 +6294,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); + info.for_each_path (&startfile_prefixes, true, 0); } break; @@ -6561,7 +6573,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 +6621,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); + info.for_each_path (&include_prefixes, false, info.append_len); info.append = "include-fixed"; if (*sysroot_hdrs_suffix_spec) @@ -6623,14 +6634,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); + info.for_each_path (&include_prefixes, false, + info.append_len); info.append = "include-fixed"; } info.append_len = strlen (info.append); - for_each_path (&include_prefixes, false, info.append_len, - spec_path, &info); + info.for_each_path (&include_prefixes, false, info.append_len); } break; -- 2.49.0