From 2dcfc8722b6146e479039a2f8994050c772b25e6 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Thu, 2 May 2019 10:16:12 +0200 Subject: [PATCH] Postpone print of --help=* option. 2019-05-02 Martin Liska * gcc.c (process_command): Add dummy file only if n_infiles == 0. * opts-global.c (decode_options): Pass lang_mask. * opts.c (print_help): New function. (finish_options): Print --help if help_option_argument is set. (common_handle_option): Factor out content of OPT__help_ into print_help. * opts.h (finish_options): Add new argument. From-SVN: r270788 --- gcc/ChangeLog | 12 +++ gcc/gcc.c | 5 +- gcc/opts-global.c | 2 +- gcc/opts.c | 267 ++++++++++++++++++++++++---------------------- gcc/opts.h | 3 +- 5 files changed, 158 insertions(+), 131 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1883e4df91f..a6ce52335d5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2019-05-02 Martin Liska + + * gcc.c (process_command): Add dummy file only + if n_infiles == 0. + * opts-global.c (decode_options): Pass lang_mask. + * opts.c (print_help): New function. + (finish_options): Print --help if help_option_argument + is set. + (common_handle_option): Factor out content of OPT__help_ + into print_help. + * opts.h (finish_options): Add new argument. + 2019-05-02 Martin Liska PR target/88809 diff --git a/gcc/gcc.c b/gcc/gcc.c index 4f57765b012..a1003a5cdf9 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -4751,10 +4751,9 @@ process_command (unsigned int decoded_options_count, } /* Ensure we only invoke each subprocess once. */ - if (print_subprocess_help || print_help_list || print_version) + if (n_infiles == 0 + && (print_subprocess_help || print_help_list || print_version)) { - n_infiles = 0; - /* Create a dummy input file, so that we can pass the help option on to the various sub-processes. */ add_infile ("help-dummy", "c"); diff --git a/gcc/opts-global.c b/gcc/opts-global.c index a5e9ef0237a..f110fe1026f 100644 --- a/gcc/opts-global.c +++ b/gcc/opts-global.c @@ -314,7 +314,7 @@ decode_options (struct gcc_options *opts, struct gcc_options *opts_set, loc, lang_mask, &handlers, dc); - finish_options (opts, opts_set, loc); + finish_options (opts, opts_set, loc, lang_mask); } /* Hold command-line options associated with stack limitation. */ diff --git a/gcc/opts.c b/gcc/opts.c index 926904c609e..286bb8f5402 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -855,12 +855,18 @@ control_options_for_live_patching (struct gcc_options *opts, } } +/* --help option argument if set. */ +const char *help_option_argument = NULL; + +static void print_help (struct gcc_options *opts, unsigned int lang_mask); + + /* After all options at LOC have been read into OPTS and OPTS_SET, finalize settings of those options and diagnose incompatible combinations. */ void finish_options (struct gcc_options *opts, struct gcc_options *opts_set, - location_t loc) + location_t loc, unsigned int lang_mask) { enum unwind_info_type ui_except; @@ -1224,6 +1230,10 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, opts->x_flag_live_patching, loc); } + + /* Print --help=* if used. */ + if (help_option_argument != NULL) + print_help (opts, lang_mask); } #define LEFT_COLUMN 27 @@ -2054,6 +2064,135 @@ check_alignment_argument (location_t loc, const char *flag, const char *name) parse_and_check_align_values (flag, name, align_result, true, loc); } +/* Print help when OPT__help_ is set. */ + +static void +print_help (struct gcc_options *opts, unsigned int lang_mask) +{ + const char *a = help_option_argument; + unsigned int include_flags = 0; + /* Note - by default we include undocumented options when listing + specific classes. If you only want to see documented options + then add ",^undocumented" to the --help= option. E.g.: + + --help=target,^undocumented */ + unsigned int exclude_flags = 0; + + if (lang_mask == CL_DRIVER) + return; + + /* Walk along the argument string, parsing each word in turn. + The format is: + arg = [^]{word}[,{arg}] + word = {optimizers|target|warnings|undocumented| + params|common|} */ + while (*a != 0) + { + static const struct + { + const char *string; + unsigned int flag; + } + specifics[] = + { + { "optimizers", CL_OPTIMIZATION }, + { "target", CL_TARGET }, + { "warnings", CL_WARNING }, + { "undocumented", CL_UNDOCUMENTED }, + { "params", CL_PARAMS }, + { "joined", CL_JOINED }, + { "separate", CL_SEPARATE }, + { "common", CL_COMMON }, + { NULL, 0 } + }; + unsigned int *pflags; + const char *comma; + unsigned int lang_flag, specific_flag; + unsigned int len; + unsigned int i; + + if (*a == '^') + { + ++a; + if (*a == '\0') + { + error ("missing argument to %qs", "--help=^"); + break; + } + pflags = &exclude_flags; + } + else + pflags = &include_flags; + + comma = strchr (a, ','); + if (comma == NULL) + len = strlen (a); + else + len = comma - a; + if (len == 0) + { + a = comma + 1; + continue; + } + + /* Check to see if the string matches an option class name. */ + for (i = 0, specific_flag = 0; specifics[i].string != NULL; i++) + if (strncasecmp (a, specifics[i].string, len) == 0) + { + specific_flag = specifics[i].flag; + break; + } + + /* Check to see if the string matches a language name. + Note - we rely upon the alpha-sorted nature of the entries in + the lang_names array, specifically that shorter names appear + before their longer variants. (i.e. C before C++). That way + when we are attempting to match --help=c for example we will + match with C first and not C++. */ + for (i = 0, lang_flag = 0; i < cl_lang_count; i++) + if (strncasecmp (a, lang_names[i], len) == 0) + { + lang_flag = 1U << i; + break; + } + + if (specific_flag != 0) + { + if (lang_flag == 0) + *pflags |= specific_flag; + else + { + /* The option's argument matches both the start of a + language name and the start of an option class name. + We have a special case for when the user has + specified "--help=c", but otherwise we have to issue + a warning. */ + if (strncasecmp (a, "c", len) == 0) + *pflags |= lang_flag; + else + warning (0, + "--help argument %q.*s is ambiguous, " + "please be more specific", + len, a); + } + } + else if (lang_flag != 0) + *pflags |= lang_flag; + else + warning (0, + "unrecognized argument to --help= option: %q.*s", + len, a); + + if (comma == NULL) + break; + a = comma + 1; + } + + if (include_flags) + print_specific_help (include_flags, exclude_flags, 0, opts, + lang_mask); +} + /* Handle target- and language-independent options. Return zero to generate an "unknown option" message. Only options that need extra handling need to be listed here; if you simply want @@ -2121,131 +2260,7 @@ common_handle_option (struct gcc_options *opts, case OPT__help_: { - const char *a = arg; - unsigned int include_flags = 0; - /* Note - by default we include undocumented options when listing - specific classes. If you only want to see documented options - then add ",^undocumented" to the --help= option. E.g.: - - --help=target,^undocumented */ - unsigned int exclude_flags = 0; - - if (lang_mask == CL_DRIVER) - break; - - /* Walk along the argument string, parsing each word in turn. - The format is: - arg = [^]{word}[,{arg}] - word = {optimizers|target|warnings|undocumented| - params|common|} */ - while (*a != 0) - { - static const struct - { - const char *string; - unsigned int flag; - } - specifics[] = - { - { "optimizers", CL_OPTIMIZATION }, - { "target", CL_TARGET }, - { "warnings", CL_WARNING }, - { "undocumented", CL_UNDOCUMENTED }, - { "params", CL_PARAMS }, - { "joined", CL_JOINED }, - { "separate", CL_SEPARATE }, - { "common", CL_COMMON }, - { NULL, 0 } - }; - unsigned int *pflags; - const char *comma; - unsigned int lang_flag, specific_flag; - unsigned int len; - unsigned int i; - - if (*a == '^') - { - ++a; - if (*a == '\0') - { - error_at (loc, "missing argument to %qs", "--help=^"); - break; - } - pflags = &exclude_flags; - } - else - pflags = &include_flags; - - comma = strchr (a, ','); - if (comma == NULL) - len = strlen (a); - else - len = comma - a; - if (len == 0) - { - a = comma + 1; - continue; - } - - /* Check to see if the string matches an option class name. */ - for (i = 0, specific_flag = 0; specifics[i].string != NULL; i++) - if (strncasecmp (a, specifics[i].string, len) == 0) - { - specific_flag = specifics[i].flag; - break; - } - - /* Check to see if the string matches a language name. - Note - we rely upon the alpha-sorted nature of the entries in - the lang_names array, specifically that shorter names appear - before their longer variants. (i.e. C before C++). That way - when we are attempting to match --help=c for example we will - match with C first and not C++. */ - for (i = 0, lang_flag = 0; i < cl_lang_count; i++) - if (strncasecmp (a, lang_names[i], len) == 0) - { - lang_flag = 1U << i; - break; - } - - if (specific_flag != 0) - { - if (lang_flag == 0) - *pflags |= specific_flag; - else - { - /* The option's argument matches both the start of a - language name and the start of an option class name. - We have a special case for when the user has - specified "--help=c", but otherwise we have to issue - a warning. */ - if (strncasecmp (a, "c", len) == 0) - *pflags |= lang_flag; - else - warning_at (loc, 0, - "--help argument %q.*s is ambiguous, " - "please be more specific", - len, a); - } - } - else if (lang_flag != 0) - *pflags |= lang_flag; - else - warning_at (loc, 0, - "unrecognized argument to --help= option: %q.*s", - len, a); - - if (comma == NULL) - break; - a = comma + 1; - } - - if (include_flags) - { - target_option_override_hook (); - print_specific_help (include_flags, exclude_flags, 0, opts, - lang_mask); - } + help_option_argument = arg; opts->x_exit_after_options = true; break; } diff --git a/gcc/opts.h b/gcc/opts.h index f14d9bcb896..6e99eaddbaf 100644 --- a/gcc/opts.h +++ b/gcc/opts.h @@ -418,7 +418,8 @@ extern bool target_handle_option (struct gcc_options *opts, void (*target_option_override_hook) (void)); extern void finish_options (struct gcc_options *opts, struct gcc_options *opts_set, - location_t loc); + location_t loc, + unsigned int lang_mask); extern void default_options_optimization (struct gcc_options *opts, struct gcc_options *opts_set, struct cl_decoded_option *decoded_options, -- 2.30.2