Skip to content

Commit

Permalink
Postpone print of --help=* option.
Browse files Browse the repository at this point in the history
2019-05-02  Martin Liska  <mliska@suse.cz>

	* 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
  • Loading branch information
marxin authored and Martin Liska committed May 2, 2019
1 parent 786e0e5 commit 2dcfc87
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 131 deletions.
12 changes: 12 additions & 0 deletions gcc/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
2019-05-02 Martin Liska <mliska@suse.cz>

* 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 <mliska@suse.cz>

PR target/88809
Expand Down
5 changes: 2 additions & 3 deletions gcc/gcc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
2 changes: 1 addition & 1 deletion gcc/opts-global.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
267 changes: 141 additions & 126 deletions gcc/opts.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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|<language>} */
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
Expand Down Expand Up @@ -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|<language>} */
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;
}
Expand Down
3 changes: 2 additions & 1 deletion gcc/opts.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 2dcfc87

Please sign in to comment.