Message ID | Pine.LNX.4.64.1006181014470.28040@digraph.polyomino.org.uk |
---|---|
State | New |
Headers | show |
On 18 June 2010 12:16, Joseph S. Myers <joseph@codesourcery.com> wrote: > + case OPT_Ofast: > + /* -Ofast only adds flags to -O3. */ > + optimize_size = 0; > + optimize = 3; > + ofast = 1; > + break; I believe that the original idea was that commandline options should enable other options by simulating that they appeared in the command line. That is the purpose of the new handle_option and how it is done for Wimplicit. Has the plan changed now? Or are you planning to do this in a follow-up patch? Manuel.
On Fri, 18 Jun 2010, Manuel López-Ibáñez wrote: > On 18 June 2010 12:16, Joseph S. Myers <joseph@codesourcery.com> wrote: > > + case OPT_Ofast: > > + /* -Ofast only adds flags to -O3. */ > > + optimize_size = 0; > > + optimize = 3; > > + ofast = 1; > > + break; > > I believe that the original idea was that commandline options should > enable other options by simulating that they appeared in the command > line. That is the purpose of the new handle_option and how it is done > for Wimplicit. Has the plan changed now? Or are you planning to do > this in a follow-up patch? I don't understand how this comment relates to my patch; it appears to be about something my patch isn't changing or aiming to change. This patch is causing all code in the compilers proper after a certain point that previously worked with the argv array to work with decoded options instead - and the particular part you quote is converting the -O prescan to do just that, without doing anything else about that prescan - the logic handling each option in the prescan is unchanged except that it no longer decodes strings from argv itself. The purpose of this patch is not to implement any general infrastructure for options implying other options (although I have described what I think the semantics should be for this, it may not be necessary to implement that to achieve the desired effects of this patch series). In principle, I do indeed think that the prescan should not be needed - a general enough infrastructure to describe what other options the -O options imply should be able to replace it. But sharing the existing code for -O prescans with the driver is surely going to be substantially simpler than a sufficiently general implication infrastructure. I should point out that I don't really think of -Ofast as implying -O3 in the normal sense of option implications. Rather, I think of -O as more like an option with enumerated arguments (1, 2, 3, s, fast), where no argument is an alias for 1 and arguments that are integers greater than 3 are aliases for 3; logically, you'd take the value of that enumeration from the last -O option present, and only then convert that value into the settings of multiple variables. I *do* expect to implement some generic support for options with enumerated arguments in this patch series - there are so many instances of ad hoc code for such options at present - but it probably won't cover the special case of -O, just the more normal cases such as -march where there is a clear limited finite set of arguments. The anticipated next patches in this series are, roughly (and not necessarily in this exact order): * Split up init_options langhook into part returning lang_mask and part that takes decoded options, together with a hook to say whether to warn for wrong-language options. * Remove unused C-family -lang-objc option. * Convert missing_argument langhook into a message string given in the .opt file. * Move read_cmdline_option and handle_option to common code - taking an array of structures describing the handlers to call, so that the basic infrastructure can be shared with the driver before the handlers themselves are. * Start actually using the opts-common.c infrastructure for parsing options in the driver (this may well need further preliminary patches). I do not have detailed plans after that point, but general themes include introducing more infrastructure for options to be described more fully in the .opt files instead of in code so that hooks shared with the driver end up smaller (a system for one option to be an exact alias of another is definitely a part of this, as I expect is handling for enumerated options), and moving the existing options global variables into a structure to which various options functions take pointers (this last piece is critical to the whole purpose of this patch series, but all the other pieces are involved in ensuring that the structure contents are accurate enough in the driver to be used in multilib selection).
On 18 June 2010 13:13, Joseph S. Myers <joseph@codesourcery.com> wrote: > On Fri, 18 Jun 2010, Manuel López-Ibáñez wrote: > >> On 18 June 2010 12:16, Joseph S. Myers <joseph@codesourcery.com> wrote: >> > + case OPT_Ofast: >> > + /* -Ofast only adds flags to -O3. */ >> > + optimize_size = 0; >> > + optimize = 3; >> > + ofast = 1; >> > + break; >> >> I believe that the original idea was that commandline options should >> enable other options by simulating that they appeared in the command >> line. That is the purpose of the new handle_option and how it is done >> for Wimplicit. Has the plan changed now? Or are you planning to do >> this in a follow-up patch? > I should point out that I don't really think of -Ofast as implying -O3 in > the normal sense of option implications. Rather, I think of -O as more > like an option with enumerated arguments (1, 2, 3, s, fast), where no > argument is an alias for 1 and arguments that are integers greater than 3 > are aliases for 3; logically, you'd take the value of that enumeration > from the last -O option present, and only then convert that value into the > settings of multiple variables. I *do* expect to implement some generic > support for options with enumerated arguments in this patch series - there > are so many instances of ad hoc code for such options at present - but it > probably won't cover the special case of -O, just the more normal cases > such as -march where there is a clear limited finite set of arguments. OK, I misunderstood that cleaning up the options that enable other options was part of your goals. In general, for options implying other options (which seems is not the case of -Ofast and I misunderstood your patch), should we start using handle_option or only when that fixes a reported bug like in the Wimplicit case? Manuel.
On Fri, 18 Jun 2010, Manuel López-Ibáñez wrote: > OK, I misunderstood that cleaning up the options that enable other > options was part of your goals. In general, for options implying other The goal is selecting multilibs based on the features enabled by the command line (and the features enabled by the command lines for each available multilib) rather than based on the text of the options in that command line. Cleanups are done where they seem helpful (not always strictly required) for this goal - so increasing the proportion of option handling done by generic machinery rather than by hooks is helpful insofar as it reduces the amount of hook code that will end up needing to be made to work in two places (but front-end options are of less concern here than back-end options because front-end options should not generally be relevant to multilib selection). Where existing bugs show up that seem too far afield to fix as part of this work, I expect to file PRs for them (e.g. PR 44574). > options (which seems is not the case of -Ofast and I misunderstood > your patch), should we start using handle_option or only when that > fixes a reported bug like in the Wimplicit case? I do not have specific advice here. Fixing bugs (adding testcases in the process) seems appropriate whether or not those bugs have PRs filed in Bugzilla.
On Fri, Jun 18, 2010 at 12:16 PM, Joseph S. Myers <joseph@codesourcery.com> wrote: > This patch continues work towards sharing option-processing code > between the driver and the compilers proper by creating a function in > opts-common.c that deals with converting the argv array into an array > of cl_decoded_option structures. > > The prescan for -O options and the handling of -frecord-gcc-switches > are converted to use this array. In both cases, this simplifies the > code in question and fixes bugs in it: for -O options, bugs relating > to option arguments that look like -O options; for > -frecord-gcc-switches, the issue where it wrongly identifies what is > an option argument (one of many issues mentioned in PR 32998; the > others are not addressed by this patch). The function > read_integral_parameter, used only for -O options, essentially > duplicated integral_argument, used for other options, and is removed > by this patch. Front-end option handlers will never get called with > non-options, so there is no need for the Fortran handler to consider > that possibility, and I removed that code as part of eliminating some > special uses of N_OPTS/cl_options_count in favour of > OPT_SPECIAL_unknown. > > Note that the front-end init_options hooks still take argc and argv, > and the c-family hook uses them for one of the various scans that > don't handle option arguments properly (to scan for -lang-asm). My > inclination is that the special code for -lang-asm should be replaced > with a langhook that determines whether to warn for a wrong-language > option, while init_options is split into one part that determines the > lang_mask used for parsing options (without receiving the options > itself) and another part that receives the decoded options. A hook > determining whether to warn for wrong-language options would also > replace the hardcoding of an LTO check in complain_wrong_lang. When > the option processing code is used in the driver, it would simply > quietly accept options valid for any language. > > Bootstrapped with no regressions on x86_64-unknown-linux-gnu. OK to > commit? Ok. Thanks, Richard. > 2010-06-18 Joseph Myers <joseph@codesourcery.com> > > PR other/32998 > * opth-gen.awk: Generate definitions of OPT_SPECIAL_unknown, > OPT_SPECIAL_program_name and OPT_SPECIAL_input_file. > * opts-common.c (find_opt): Return OPT_SPECIAL_unknown on failure. > (decode_cmdline_option): Update for this return value. Set > orig_option_with_args_text field. Set arg field for unknown > options. Make static. > (decode_cmdline_options_to_array): New. > (prune_options): Update handling of find_opt return value. > * opts.c (read_cmdline_option): Take decoded option. Return void. > (read_cmdline_options): Take decoded options. > (decode_options): Add parameters for decoded options. Use > decode_cmdline_options_to_array. Use decoded options for -O > scan. Use integral_argument for -O parameters. Update call to > read_cmdline_options. > (enable_warning_as_error): Update handling of find_opt return > value. > * opts.h: Update comment on unknown options. > (struct cl_decoded_option): Update comments on opt_index and arg. > Add orig_option_with_args_text. > (decode_cmdline_option): Remove. > (decode_cmdline_options_to_array): Declare. > (decode_options): Update prototype. > * toplev.c (save_argv): Remove. > (save_decoded_options, save_decoded_options_count): New. > (read_integral_parameter): Remove. > (print_switch_values): Use decoded options. > (toplev_main): Don't set save_argv. Update call to > decode_options. > * toplev.h (read_integral_parameter): Remove. > * varasm.c (elf_record_gcc_switches): Don't handle holding back > names. > > c-family: > 2010-06-18 Joseph Myers <joseph@codesourcery.com> > > * c-common.c (parse_optimize_options): Update call to > decode_options. > > fortran: > 2010-06-18 Joseph Myers <joseph@codesourcery.com> > > * options.c (gfc_handle_option): Don't handle N_OPTS. > > testsuite: > 2010-06-18 Joseph Myers <joseph@codesourcery.com> > > * gcc.dg/opts-2.c: New test. > > Index: opts-common.c > =================================================================== > --- opts-common.c (revision 160895) > +++ opts-common.c (working copy) > @@ -25,8 +25,8 @@ along with GCC; see the file COPYING3. > #include "options.h" > > /* Perform a binary search to find which option the command-line INPUT > - matches. Returns its index in the option array, and N_OPTS > - (cl_options_count) on failure. > + matches. Returns its index in the option array, and > + OPT_SPECIAL_unknown on failure. > > This routine is quite subtle. A normal binary search is not good > enough because some options can be suffixed with an argument, and > @@ -73,8 +73,8 @@ find_opt (const char *input, int lang_ma > } > > /* This is the switch that is the best match but for a different > - front end, or cl_options_count if there is no match at all. */ > - match_wrong_lang = cl_options_count; > + front end, or OPT_SPECIAL_unknown if there is no match at all. */ > + match_wrong_lang = OPT_SPECIAL_unknown; > > /* Backtrace the chain of possible matches, returning the longest > one, if any, that fits best. With current GCC switches, this > @@ -94,7 +94,7 @@ find_opt (const char *input, int lang_ma > > /* If we haven't remembered a prior match, remember this > one. Any prior match is necessarily better. */ > - if (match_wrong_lang == cl_options_count) > + if (match_wrong_lang == OPT_SPECIAL_unknown) > match_wrong_lang = mn; > } > > @@ -104,7 +104,7 @@ find_opt (const char *input, int lang_ma > } > while (mn != cl_options_count); > > - /* Return the best wrong match, or cl_options_count if none. */ > + /* Return the best wrong match, or OPT_SPECIAL_unknown if none. */ > return match_wrong_lang; > } > > @@ -129,7 +129,7 @@ integral_argument (const char *arg) > LANG_MASK, into the structure *DECODED. Returns the number of > switches consumed. */ > > -unsigned int > +static unsigned int > decode_cmdline_option (const char **argv, unsigned int lang_mask, > struct cl_decoded_option *decoded) > { > @@ -144,7 +144,7 @@ decode_cmdline_option (const char **argv > opt = argv[0]; > > opt_index = find_opt (opt + 1, lang_mask | CL_COMMON | CL_TARGET); > - if (opt_index == cl_options_count > + if (opt_index == OPT_SPECIAL_unknown > && (opt[1] == 'W' || opt[1] == 'f' || opt[1] == 'm') > && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-') > { > @@ -160,8 +160,11 @@ decode_cmdline_option (const char **argv > opt_index = find_opt (opt + 1, lang_mask | CL_COMMON | CL_TARGET); > } > > - if (opt_index == cl_options_count) > - goto done; > + if (opt_index == OPT_SPECIAL_unknown) > + { > + arg = argv[0]; > + goto done; > + } > > option = &cl_options[opt_index]; > > @@ -169,7 +172,8 @@ decode_cmdline_option (const char **argv > unrecognized. */ > if (!value && (option->flags & CL_REJECT_NEGATIVE)) > { > - opt_index = cl_options_count; > + opt_index = OPT_SPECIAL_unknown; > + arg = argv[0]; > goto done; > } > > @@ -237,9 +241,76 @@ decode_cmdline_option (const char **argv > decoded->arg = arg; > decoded->value = value; > decoded->errors = errors; > + switch (result) > + { > + case 1: > + decoded->orig_option_with_args_text = argv[0]; > + break; > + case 2: > + decoded->orig_option_with_args_text = concat (argv[0], " ", > + argv[1], NULL); > + break; > + default: > + gcc_unreachable (); > + } > return result; > } > > +/* Decode command-line options (ARGC and ARGV being the arguments of > + main) into an array, setting *DECODED_OPTIONS to a pointer to that > + array and *DECODED_OPTIONS_COUNT to the number of entries in the > + array. The first entry in the array is always one for the program > + name (OPT_SPECIAL_program_name). LANG_MASK indicates the language > + applicable for decoding. Do not produce any diagnostics or set > + state outside of these variables. */ > + > +void > +decode_cmdline_options_to_array (unsigned int argc, const char **argv, > + unsigned int lang_mask, > + struct cl_decoded_option **decoded_options, > + unsigned int *decoded_options_count) > +{ > + unsigned int n, i; > + struct cl_decoded_option *opt_array; > + unsigned int num_decoded_options; > + > + opt_array = XNEWVEC (struct cl_decoded_option, argc); > + > + opt_array[0].opt_index = OPT_SPECIAL_program_name; > + opt_array[0].arg = argv[0]; > + opt_array[0].orig_option_with_args_text = argv[0]; > + opt_array[0].value = 1; > + opt_array[0].errors = 0; > + num_decoded_options = 1; > + > + for (i = 1; i < argc; i += n) > + { > + const char *opt = argv[i]; > + > + /* Interpret "-" or a non-switch as a file name. */ > + if (opt[0] != '-' || opt[1] == '\0') > + { > + opt_array[num_decoded_options].opt_index = OPT_SPECIAL_input_file; > + opt_array[num_decoded_options].arg = opt; > + opt_array[num_decoded_options].orig_option_with_args_text = opt; > + opt_array[num_decoded_options].value = 1; > + opt_array[num_decoded_options].errors = 0; > + num_decoded_options++; > + n = 1; > + continue; > + } > + > + n = decode_cmdline_option (argv + i, lang_mask, > + &opt_array[num_decoded_options]); > + num_decoded_options++; > + } > + > + opt_array = XRESIZEVEC (struct cl_decoded_option, opt_array, > + num_decoded_options); > + *decoded_options = opt_array; > + *decoded_options_count = num_decoded_options; > +} > + > /* Return true if NEXT_OPT_IDX cancels OPT_IDX. Return false if the > next one is the same as ORIG_NEXT_OPT_IDX. */ > > @@ -281,7 +352,7 @@ prune_options (int *argcp, char ***argvp > const char *opt = (*argvp) [i]; > > opt_index = find_opt (opt + 1, -1); > - if (opt_index == cl_options_count > + if (opt_index == OPT_SPECIAL_unknown > && (opt[1] == 'W' || opt[1] == 'f' || opt[1] == 'm') > && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-') > { > @@ -300,7 +371,7 @@ prune_options (int *argcp, char ***argvp > free (dup); > } > > - if (opt_index == cl_options_count) > + if (opt_index == OPT_SPECIAL_unknown) > { > cont: > options [i] = 0; > Index: c-family/c-common.c > =================================================================== > --- c-family/c-common.c (revision 160895) > +++ c-family/c-common.c (working copy) > @@ -7624,6 +7624,8 @@ parse_optimize_options (tree args, bool > unsigned i; > int saved_flag_strict_aliasing; > const char **opt_argv; > + struct cl_decoded_option *decoded_options; > + unsigned int decoded_options_count; > tree ap; > > /* Build up argv vector. Just in case the string is stored away, use garbage > @@ -7716,7 +7718,8 @@ parse_optimize_options (tree args, bool > saved_flag_strict_aliasing = flag_strict_aliasing; > > /* Now parse the options. */ > - decode_options (opt_argc, opt_argv); > + decode_options (opt_argc, opt_argv, &decoded_options, > + &decoded_options_count); > > targetm.override_options_after_change(); > > Index: toplev.c > =================================================================== > --- toplev.c (revision 160895) > +++ toplev.c (working copy) > @@ -126,8 +126,9 @@ static bool no_backend; > /* Length of line when printing switch values. */ > #define MAX_LINE 75 > > -/* Copy of argument vector to toplev_main. */ > -static const char **save_argv; > +/* Decoded options, and number of such options. */ > +static struct cl_decoded_option *save_decoded_options; > +static unsigned int save_decoded_options_count; > > /* Name of top-level original source file (what was input to cpp). > This comes from the #-command at the beginning of the actual input. > @@ -488,34 +489,6 @@ set_random_seed (const char *val) > return old; > } > > -/* Decode the string P as an integral parameter. > - If the string is indeed an integer return its numeric value else > - issue an Invalid Option error for the option PNAME and return DEFVAL. > - If PNAME is zero just return DEFVAL, do not call error. */ > - > -int > -read_integral_parameter (const char *p, const char *pname, const int defval) > -{ > - const char *endp = p; > - > - while (*endp) > - { > - if (ISDIGIT (*endp)) > - endp++; > - else > - break; > - } > - > - if (*endp != 0) > - { > - if (pname != 0) > - error ("invalid option argument %qs", pname); > - return defval; > - } > - > - return atoi (p); > -} > - > #if GCC_VERSION < 3004 > > /* The functions floor_log2 and exact_log2 are defined as inline > @@ -1338,7 +1311,6 @@ print_switch_values (print_switch_fn_typ > { > int pos = 0; > size_t j; > - const char **p; > > /* Fill in the -frandom-seed option, if the user didn't pass it, so > that it can be printed below. This helps reproducibility. */ > @@ -1349,30 +1321,23 @@ print_switch_values (print_switch_fn_typ > pos = print_single_switch (print_fn, pos, > SWITCH_TYPE_DESCRIPTIVE, _("options passed: ")); > > - for (p = &save_argv[1]; *p != NULL; p++) > + for (j = 1; j < save_decoded_options_count; j++) > { > - if (**p == '-') > + switch (save_decoded_options[j].opt_index) > { > + case OPT_o: > + case OPT_d: > + case OPT_dumpbase: > + case OPT_dumpdir: > + case OPT_auxbase: > + case OPT_quiet: > + case OPT_version: > /* Ignore these. */ > - if (strcmp (*p, "-o") == 0 > - || strcmp (*p, "-dumpbase") == 0 > - || strcmp (*p, "-dumpdir") == 0 > - || strcmp (*p, "-auxbase") == 0) > - { > - if (p[1] != NULL) > - p++; > - continue; > - } > - > - if (strcmp (*p, "-quiet") == 0 > - || strcmp (*p, "-version") == 0) > - continue; > - > - if ((*p)[1] == 'd') > - continue; > + continue; > } > > - pos = print_single_switch (print_fn, pos, SWITCH_TYPE_PASSED, *p); > + pos = print_single_switch (print_fn, pos, SWITCH_TYPE_PASSED, > + save_decoded_options[j].orig_option_with_args_text); > } > > if (pos > 0) > @@ -2395,14 +2360,13 @@ toplev_main (int argc, char **argv) > { > expandargv (&argc, &argv); > > - save_argv = CONST_CAST2 (const char **, char **, argv); > - > /* Initialization of GCC's environment, and diagnostics. */ > general_init (argv[0]); > > /* Parse the options and do minimal processing; basically just > enough to default flags appropriately. */ > - decode_options (argc, CONST_CAST2 (const char **, char **, argv)); > + decode_options (argc, CONST_CAST2 (const char **, char **, argv), > + &save_decoded_options, &save_decoded_options_count); > > init_local_tick (); > > Index: toplev.h > =================================================================== > --- toplev.h (revision 160895) > +++ toplev.h (working copy) > @@ -31,7 +31,6 @@ along with GCC; see the file COPYING3. > (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part)) > > extern int toplev_main (int, char **); > -extern int read_integral_parameter (const char *, const char *, const int); > extern void strip_off_ending (char *, int); > extern void _fatal_insn_not_found (const_rtx, const char *, int, const char *) > ATTRIBUTE_NORETURN; > Index: testsuite/gcc.dg/opts-2.c > =================================================================== > --- testsuite/gcc.dg/opts-2.c (revision 0) > +++ testsuite/gcc.dg/opts-2.c (revision 0) > @@ -0,0 +1,8 @@ > +/* -O as an operand to another option should not take effect as an > + optimization option. */ > +/* { dg-do compile } */ > +/* { dg-options "-I -O" } */ > + > +#ifdef __OPTIMIZE__ > +#error "__OPTIMIZE__ defined" > +#endif > Index: opts.c > =================================================================== > --- opts.c (revision 160895) > +++ opts.c (working copy) > @@ -515,67 +515,63 @@ handle_option (int opt_index, int value, > return true; > } > > -/* Handle the switch beginning at ARGV for the language indicated by > - LANG_MASK. Returns the number of switches consumed. */ > -static unsigned int > -read_cmdline_option (const char **argv, unsigned int lang_mask) > +/* Handle the switch DECODED for the language indicated by > + LANG_MASK. */ > +static void > +read_cmdline_option (struct cl_decoded_option *decoded, > + unsigned int lang_mask) > { > - struct cl_decoded_option decoded; > - unsigned int result; > - const char *opt; > const struct cl_option *option; > + const char *opt; > > - opt = argv[0]; > - > - result = decode_cmdline_option (argv, lang_mask, &decoded); > - if (decoded.opt_index == cl_options_count) > + if (decoded->opt_index == OPT_SPECIAL_unknown) > { > + opt = decoded->arg; > + > if (opt[1] == 'W' && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-') > /* We don't generate warnings for unknown -Wno-* options > unless we issue diagnostics. */ > - postpone_unknown_option_warning (argv[0]); > + postpone_unknown_option_warning (opt); > else > error ("unrecognized command line option %qs", opt); > - return result; > + return; > } > > - option = &cl_options[decoded.opt_index]; > + option = &cl_options[decoded->opt_index]; > + opt = decoded->orig_option_with_args_text; > > - if (decoded.errors & CL_ERR_DISABLED) > + if (decoded->errors & CL_ERR_DISABLED) > { > error ("command line option %qs" > " is not supported by this configuration", opt); > - goto done; > + return; > } > > - if (decoded.errors & CL_ERR_WRONG_LANG) > + if (decoded->errors & CL_ERR_WRONG_LANG) > { > - complain_wrong_lang (argv[0], option, lang_mask); > - goto done; > + complain_wrong_lang (opt, option, lang_mask); > + return; > } > > - if (decoded.errors & CL_ERR_MISSING_ARG) > + if (decoded->errors & CL_ERR_MISSING_ARG) > { > - if (!lang_hooks.missing_argument (opt, decoded.opt_index)) > + if (!lang_hooks.missing_argument (opt, decoded->opt_index)) > error ("missing argument to %qs", opt); > - goto done; > + return; > } > > - if (decoded.errors & CL_ERR_UINT_ARG) > + if (decoded->errors & CL_ERR_UINT_ARG) > { > error ("argument to %qs should be a non-negative integer", > option->opt_text); > - goto done; > + return; > } > > - gcc_assert (!decoded.errors); > + gcc_assert (!decoded->errors); > > - if (!handle_option (decoded.opt_index, decoded.value, decoded.arg, > + if (!handle_option (decoded->opt_index, decoded->value, decoded->arg, > lang_mask, DK_UNSPECIFIED)) > error ("unrecognized command line option %qs", opt); > - > - done: > - return result; > } > > /* Handle FILENAME from the command line. */ > @@ -667,40 +663,41 @@ flag_instrument_functions_exclude_p (tre > } > > > -/* Decode and handle the vector of command line options. LANG_MASK > +/* Handle the vector of command line options. LANG_MASK > contains has a single bit set representing the current > language. */ > static void > -read_cmdline_options (unsigned int argc, const char **argv, unsigned int lang_mask) > +read_cmdline_options (struct cl_decoded_option *decoded_options, > + unsigned int decoded_options_count, > + unsigned int lang_mask) > { > - unsigned int n, i; > + unsigned int i; > > - for (i = 1; i < argc; i += n) > + for (i = 1; i < decoded_options_count; i++) > { > - const char *opt = argv[i]; > - > - /* Interpret "-" or a non-switch as a file name. */ > - if (opt[0] != '-' || opt[1] == '\0') > + if (decoded_options[i].opt_index == OPT_SPECIAL_input_file) > { > if (main_input_filename == NULL) > { > - main_input_filename = opt; > + main_input_filename = decoded_options[i].arg; > main_input_baselength > = base_of_path (main_input_filename, &main_input_basename); > } > - add_input_filename (opt); > - n = 1; > + add_input_filename (decoded_options[i].arg); > continue; > } > > - n = read_cmdline_option (argv + i, lang_mask); > + read_cmdline_option (decoded_options + i, lang_mask); > } > } > > /* Parse command line options and set default flag values. Do minimal > - options processing. */ > + options processing. The decoded options are placed in *DECODED_OPTIONS > + and *DECODED_OPTIONS_COUNT. */ > void > -decode_options (unsigned int argc, const char **argv) > +decode_options (unsigned int argc, const char **argv, > + struct cl_decoded_option **decoded_options, > + unsigned int *decoded_options_count) > { > static bool first_time_p = true; > static int initial_min_crossjump_insns; > @@ -733,40 +730,30 @@ decode_options (unsigned int argc, const > else > lang_mask = initial_lang_mask; > > + decode_cmdline_options_to_array (argc, argv, lang_mask, > + decoded_options, decoded_options_count); > + > /* Scan to see what optimization level has been specified. That will > determine the default value of many flags. */ > - for (i = 1; i < argc; i++) > + for (i = 1; i < *decoded_options_count; i++) > { > - if (!strcmp (argv[i], "-O")) > - { > - optimize = 1; > - optimize_size = 0; > - ofast = 0; > - } > - else if (argv[i][0] == '-' && argv[i][1] == 'O') > + struct cl_decoded_option *opt = &(*decoded_options)[i]; > + switch (opt->opt_index) > { > - /* Handle -Os, -O2, -O3, -O69, ... */ > - const char *p = &argv[i][2]; > - > - if ((p[0] == 's') && (p[1] == 0)) > - { > - optimize_size = 1; > - > - /* Optimizing for size forces optimize to be 2. */ > - optimize = 2; > - ofast = 0; > - } > - else if (strcmp (p, "fast") == 0) > + case OPT_O: > + if (*opt->arg == '\0') > { > - /* -Ofast only adds flags to -O3. */ > + optimize = 1; > optimize_size = 0; > - optimize = 3; > - ofast = 1; > + ofast = 0; > } > else > { > - const int optimize_val = read_integral_parameter (p, p - 2, -1); > - if (optimize_val != -1) > + const int optimize_val = integral_argument (opt->arg); > + if (optimize_val == -1) > + error ("argument to %qs should be a non-negative integer", > + "-O"); > + else > { > optimize = optimize_val; > if ((unsigned int) optimize > 255) > @@ -775,6 +762,26 @@ decode_options (unsigned int argc, const > ofast = 0; > } > } > + break; > + > + case OPT_Os: > + optimize_size = 1; > + > + /* Optimizing for size forces optimize to be 2. */ > + optimize = 2; > + ofast = 0; > + break; > + > + case OPT_Ofast: > + /* -Ofast only adds flags to -O3. */ > + optimize_size = 0; > + optimize = 3; > + ofast = 1; > + break; > + > + default: > + /* Ignore other options in this prescan. */ > + break; > } > } > > @@ -927,7 +934,7 @@ decode_options (unsigned int argc, const > OPTIMIZATION_OPTIONS (optimize, optimize_size); > #endif > > - read_cmdline_options (argc, argv, lang_mask); > + read_cmdline_options (*decoded_options, *decoded_options_count, lang_mask); > > if (dump_base_name && ! IS_ABSOLUTE_PATH (dump_base_name)) > { > @@ -2419,7 +2426,7 @@ enable_warning_as_error (const char *arg > new_option[0] = 'W'; > strcpy (new_option + 1, arg); > option_index = find_opt (new_option, lang_mask); > - if (option_index == N_OPTS) > + if (option_index == OPT_SPECIAL_unknown) > { > error ("-Werror=%s: No option -%s", arg, new_option); > } > Index: opts.h > =================================================================== > --- opts.h (revision 160895) > +++ opts.h (working copy) > @@ -92,7 +92,7 @@ extern const unsigned int cl_lang_count; > > /* Possible ways in which a command-line option may be erroneous. > These do not include not being known at all; an option index of > - cl_options_count is used for that. */ > + OPT_SPECIAL_unknown is used for that. */ > > #define CL_ERR_DISABLED (1 << 0) /* Disabled in this configuration. */ > #define CL_ERR_MISSING_ARG (1 << 1) /* Argument required but missing. */ > @@ -103,12 +103,20 @@ extern const unsigned int cl_lang_count; > > struct cl_decoded_option > { > - /* The index of this option, or cl_options_count if not known. */ > + /* The index of this option, or an OPT_SPECIAL_* value for > + non-options and unknown options. */ > size_t opt_index; > > - /* The string argument, or NULL if none. */ > + /* The string argument, or NULL if none. For OPT_SPECIAL_* cases, > + the option or non-option command-line argument. */ > const char *arg; > > + /* The original text of option plus arguments, with separate argv > + elements concatenated into one string with spaces separating > + them. This is for such uses as diagnostics and > + -frecord-gcc-switches. */ > + const char *orig_option_with_args_text; > + > /* For a boolean option, 1 for the true case and 0 for the "no-" > case. For an unsigned integer option, the value of the > argument. 1 in all other cases. */ > @@ -128,11 +136,15 @@ extern unsigned num_in_fnames; > > size_t find_opt (const char *input, int lang_mask); > extern int integral_argument (const char *arg); > -extern unsigned int decode_cmdline_option (const char **argv, > - unsigned int lang_mask, > - struct cl_decoded_option *decoded); > +extern void decode_cmdline_options_to_array (unsigned int argc, > + const char **argv, > + unsigned int lang_mask, > + struct cl_decoded_option **decoded_options, > + unsigned int *decoded_options_count); > extern void prune_options (int *argcp, char ***argvp); > -extern void decode_options (unsigned int argc, const char **argv); > +extern void decode_options (unsigned int argc, const char **argv, > + struct cl_decoded_option **decoded_options, > + unsigned int *decoded_options_count); > extern int option_enabled (int opt_idx); > extern bool get_option_state (int, struct cl_option_state *); > extern void set_option (int opt_index, int value, const char *arg, int); > Index: fortran/options.c > =================================================================== > --- fortran/options.c (revision 160895) > +++ fortran/options.c (working copy) > @@ -541,10 +541,6 @@ gfc_handle_option (size_t scode, const c > int result = 1; > enum opt_code code = (enum opt_code) scode; > > - /* Ignore file names. */ > - if (code == N_OPTS) > - return 1; > - > if (gfc_cpp_handle_option (scode, arg, value) == 1) > return 1; > > Index: opth-gen.awk > =================================================================== > --- opth-gen.awk (revision 160895) > +++ opth-gen.awk (working copy) > @@ -358,7 +358,10 @@ for (i = 0; i < n_opts; i++) { > print " " enum "," s "/* -" opts[i] " */" > } > > -print " N_OPTS" > +print " N_OPTS," > +print " OPT_SPECIAL_unknown," > +print " OPT_SPECIAL_program_name," > +print " OPT_SPECIAL_input_file" > print "};" > print "" > print "#endif /* OPTIONS_H */" > Index: varasm.c > =================================================================== > --- varasm.c (revision 160895) > +++ varasm.c (working copy) > @@ -7199,50 +7199,11 @@ output_object_blocks (void) > int > elf_record_gcc_switches (print_switch_type type, const char * name) > { > - static char buffer[1024]; > - > - /* This variable is used as part of a simplistic heuristic to detect > - command line switches which take an argument: > - > - "If a command line option does not start with a dash then > - it is an argument for the previous command line option." > - > - This fails in the case of the command line option which is the name > - of the file to compile, but otherwise it is pretty reasonable. */ > - static bool previous_name_held_back = FALSE; > - > switch (type) > { > case SWITCH_TYPE_PASSED: > - if (* name != '-') > - { > - if (previous_name_held_back) > - { > - unsigned int len = strlen (buffer); > - > - snprintf (buffer + len, sizeof buffer - len, " %s", name); > - ASM_OUTPUT_ASCII (asm_out_file, buffer, strlen (buffer)); > - ASM_OUTPUT_SKIP (asm_out_file, (unsigned HOST_WIDE_INT) 1); > - previous_name_held_back = FALSE; > - } > - else > - { > - strncpy (buffer, name, sizeof buffer); > - ASM_OUTPUT_ASCII (asm_out_file, buffer, strlen (buffer)); > - ASM_OUTPUT_SKIP (asm_out_file, (unsigned HOST_WIDE_INT) 1); > - } > - } > - else > - { > - if (previous_name_held_back) > - { > - ASM_OUTPUT_ASCII (asm_out_file, buffer, strlen (buffer)); > - ASM_OUTPUT_SKIP (asm_out_file, (unsigned HOST_WIDE_INT) 1); > - } > - > - strncpy (buffer, name, sizeof buffer); > - previous_name_held_back = TRUE; > - } > + ASM_OUTPUT_ASCII (asm_out_file, name, strlen (name)); > + ASM_OUTPUT_SKIP (asm_out_file, (unsigned HOST_WIDE_INT) 1); > break; > > case SWITCH_TYPE_DESCRIPTIVE: > @@ -7251,15 +7212,7 @@ elf_record_gcc_switches (print_switch_ty > /* Distinguish between invocations where name is NULL. */ > static bool started = false; > > - if (started) > - { > - if (previous_name_held_back) > - { > - ASM_OUTPUT_ASCII (asm_out_file, buffer, strlen (buffer)); > - ASM_OUTPUT_SKIP (asm_out_file, (unsigned HOST_WIDE_INT) 1); > - } > - } > - else > + if (!started) > { > section * sec; > > > -- > Joseph S. Myers > joseph@codesourcery.com >
Joseph S. Myers wrote: > This patch continues work towards sharing option-processing code > between the driver and the compilers proper by creating a function in > opts-common.c that deals with converting the argv array into an array > of cl_decoded_option structures. > 2010-06-18 Joseph Myers <joseph@codesourcery.com> > > PR other/32998 > * opth-gen.awk: Generate definitions of OPT_SPECIAL_unknown, > OPT_SPECIAL_program_name and OPT_SPECIAL_input_file. ... OK.
Index: opts-common.c =================================================================== --- opts-common.c (revision 160895) +++ opts-common.c (working copy) @@ -25,8 +25,8 @@ along with GCC; see the file COPYING3. #include "options.h" /* Perform a binary search to find which option the command-line INPUT - matches. Returns its index in the option array, and N_OPTS - (cl_options_count) on failure. + matches. Returns its index in the option array, and + OPT_SPECIAL_unknown on failure. This routine is quite subtle. A normal binary search is not good enough because some options can be suffixed with an argument, and @@ -73,8 +73,8 @@ find_opt (const char *input, int lang_ma } /* This is the switch that is the best match but for a different - front end, or cl_options_count if there is no match at all. */ - match_wrong_lang = cl_options_count; + front end, or OPT_SPECIAL_unknown if there is no match at all. */ + match_wrong_lang = OPT_SPECIAL_unknown; /* Backtrace the chain of possible matches, returning the longest one, if any, that fits best. With current GCC switches, this @@ -94,7 +94,7 @@ find_opt (const char *input, int lang_ma /* If we haven't remembered a prior match, remember this one. Any prior match is necessarily better. */ - if (match_wrong_lang == cl_options_count) + if (match_wrong_lang == OPT_SPECIAL_unknown) match_wrong_lang = mn; } @@ -104,7 +104,7 @@ find_opt (const char *input, int lang_ma } while (mn != cl_options_count); - /* Return the best wrong match, or cl_options_count if none. */ + /* Return the best wrong match, or OPT_SPECIAL_unknown if none. */ return match_wrong_lang; } @@ -129,7 +129,7 @@ integral_argument (const char *arg) LANG_MASK, into the structure *DECODED. Returns the number of switches consumed. */ -unsigned int +static unsigned int decode_cmdline_option (const char **argv, unsigned int lang_mask, struct cl_decoded_option *decoded) { @@ -144,7 +144,7 @@ decode_cmdline_option (const char **argv opt = argv[0]; opt_index = find_opt (opt + 1, lang_mask | CL_COMMON | CL_TARGET); - if (opt_index == cl_options_count + if (opt_index == OPT_SPECIAL_unknown && (opt[1] == 'W' || opt[1] == 'f' || opt[1] == 'm') && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-') { @@ -160,8 +160,11 @@ decode_cmdline_option (const char **argv opt_index = find_opt (opt + 1, lang_mask | CL_COMMON | CL_TARGET); } - if (opt_index == cl_options_count) - goto done; + if (opt_index == OPT_SPECIAL_unknown) + { + arg = argv[0]; + goto done; + } option = &cl_options[opt_index]; @@ -169,7 +172,8 @@ decode_cmdline_option (const char **argv unrecognized. */ if (!value && (option->flags & CL_REJECT_NEGATIVE)) { - opt_index = cl_options_count; + opt_index = OPT_SPECIAL_unknown; + arg = argv[0]; goto done; } @@ -237,9 +241,76 @@ decode_cmdline_option (const char **argv decoded->arg = arg; decoded->value = value; decoded->errors = errors; + switch (result) + { + case 1: + decoded->orig_option_with_args_text = argv[0]; + break; + case 2: + decoded->orig_option_with_args_text = concat (argv[0], " ", + argv[1], NULL); + break; + default: + gcc_unreachable (); + } return result; } +/* Decode command-line options (ARGC and ARGV being the arguments of + main) into an array, setting *DECODED_OPTIONS to a pointer to that + array and *DECODED_OPTIONS_COUNT to the number of entries in the + array. The first entry in the array is always one for the program + name (OPT_SPECIAL_program_name). LANG_MASK indicates the language + applicable for decoding. Do not produce any diagnostics or set + state outside of these variables. */ + +void +decode_cmdline_options_to_array (unsigned int argc, const char **argv, + unsigned int lang_mask, + struct cl_decoded_option **decoded_options, + unsigned int *decoded_options_count) +{ + unsigned int n, i; + struct cl_decoded_option *opt_array; + unsigned int num_decoded_options; + + opt_array = XNEWVEC (struct cl_decoded_option, argc); + + opt_array[0].opt_index = OPT_SPECIAL_program_name; + opt_array[0].arg = argv[0]; + opt_array[0].orig_option_with_args_text = argv[0]; + opt_array[0].value = 1; + opt_array[0].errors = 0; + num_decoded_options = 1; + + for (i = 1; i < argc; i += n) + { + const char *opt = argv[i]; + + /* Interpret "-" or a non-switch as a file name. */ + if (opt[0] != '-' || opt[1] == '\0') + { + opt_array[num_decoded_options].opt_index = OPT_SPECIAL_input_file; + opt_array[num_decoded_options].arg = opt; + opt_array[num_decoded_options].orig_option_with_args_text = opt; + opt_array[num_decoded_options].value = 1; + opt_array[num_decoded_options].errors = 0; + num_decoded_options++; + n = 1; + continue; + } + + n = decode_cmdline_option (argv + i, lang_mask, + &opt_array[num_decoded_options]); + num_decoded_options++; + } + + opt_array = XRESIZEVEC (struct cl_decoded_option, opt_array, + num_decoded_options); + *decoded_options = opt_array; + *decoded_options_count = num_decoded_options; +} + /* Return true if NEXT_OPT_IDX cancels OPT_IDX. Return false if the next one is the same as ORIG_NEXT_OPT_IDX. */ @@ -281,7 +352,7 @@ prune_options (int *argcp, char ***argvp const char *opt = (*argvp) [i]; opt_index = find_opt (opt + 1, -1); - if (opt_index == cl_options_count + if (opt_index == OPT_SPECIAL_unknown && (opt[1] == 'W' || opt[1] == 'f' || opt[1] == 'm') && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-') { @@ -300,7 +371,7 @@ prune_options (int *argcp, char ***argvp free (dup); } - if (opt_index == cl_options_count) + if (opt_index == OPT_SPECIAL_unknown) { cont: options [i] = 0; Index: c-family/c-common.c =================================================================== --- c-family/c-common.c (revision 160895) +++ c-family/c-common.c (working copy) @@ -7624,6 +7624,8 @@ parse_optimize_options (tree args, bool unsigned i; int saved_flag_strict_aliasing; const char **opt_argv; + struct cl_decoded_option *decoded_options; + unsigned int decoded_options_count; tree ap; /* Build up argv vector. Just in case the string is stored away, use garbage @@ -7716,7 +7718,8 @@ parse_optimize_options (tree args, bool saved_flag_strict_aliasing = flag_strict_aliasing; /* Now parse the options. */ - decode_options (opt_argc, opt_argv); + decode_options (opt_argc, opt_argv, &decoded_options, + &decoded_options_count); targetm.override_options_after_change(); Index: toplev.c =================================================================== --- toplev.c (revision 160895) +++ toplev.c (working copy) @@ -126,8 +126,9 @@ static bool no_backend; /* Length of line when printing switch values. */ #define MAX_LINE 75 -/* Copy of argument vector to toplev_main. */ -static const char **save_argv; +/* Decoded options, and number of such options. */ +static struct cl_decoded_option *save_decoded_options; +static unsigned int save_decoded_options_count; /* Name of top-level original source file (what was input to cpp). This comes from the #-command at the beginning of the actual input. @@ -488,34 +489,6 @@ set_random_seed (const char *val) return old; } -/* Decode the string P as an integral parameter. - If the string is indeed an integer return its numeric value else - issue an Invalid Option error for the option PNAME and return DEFVAL. - If PNAME is zero just return DEFVAL, do not call error. */ - -int -read_integral_parameter (const char *p, const char *pname, const int defval) -{ - const char *endp = p; - - while (*endp) - { - if (ISDIGIT (*endp)) - endp++; - else - break; - } - - if (*endp != 0) - { - if (pname != 0) - error ("invalid option argument %qs", pname); - return defval; - } - - return atoi (p); -} - #if GCC_VERSION < 3004 /* The functions floor_log2 and exact_log2 are defined as inline @@ -1338,7 +1311,6 @@ print_switch_values (print_switch_fn_typ { int pos = 0; size_t j; - const char **p; /* Fill in the -frandom-seed option, if the user didn't pass it, so that it can be printed below. This helps reproducibility. */ @@ -1349,30 +1321,23 @@ print_switch_values (print_switch_fn_typ pos = print_single_switch (print_fn, pos, SWITCH_TYPE_DESCRIPTIVE, _("options passed: ")); - for (p = &save_argv[1]; *p != NULL; p++) + for (j = 1; j < save_decoded_options_count; j++) { - if (**p == '-') + switch (save_decoded_options[j].opt_index) { + case OPT_o: + case OPT_d: + case OPT_dumpbase: + case OPT_dumpdir: + case OPT_auxbase: + case OPT_quiet: + case OPT_version: /* Ignore these. */ - if (strcmp (*p, "-o") == 0 - || strcmp (*p, "-dumpbase") == 0 - || strcmp (*p, "-dumpdir") == 0 - || strcmp (*p, "-auxbase") == 0) - { - if (p[1] != NULL) - p++; - continue; - } - - if (strcmp (*p, "-quiet") == 0 - || strcmp (*p, "-version") == 0) - continue; - - if ((*p)[1] == 'd') - continue; + continue; } - pos = print_single_switch (print_fn, pos, SWITCH_TYPE_PASSED, *p); + pos = print_single_switch (print_fn, pos, SWITCH_TYPE_PASSED, + save_decoded_options[j].orig_option_with_args_text); } if (pos > 0) @@ -2395,14 +2360,13 @@ toplev_main (int argc, char **argv) { expandargv (&argc, &argv); - save_argv = CONST_CAST2 (const char **, char **, argv); - /* Initialization of GCC's environment, and diagnostics. */ general_init (argv[0]); /* Parse the options and do minimal processing; basically just enough to default flags appropriately. */ - decode_options (argc, CONST_CAST2 (const char **, char **, argv)); + decode_options (argc, CONST_CAST2 (const char **, char **, argv), + &save_decoded_options, &save_decoded_options_count); init_local_tick (); Index: toplev.h =================================================================== --- toplev.h (revision 160895) +++ toplev.h (working copy) @@ -31,7 +31,6 @@ along with GCC; see the file COPYING3. (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part)) extern int toplev_main (int, char **); -extern int read_integral_parameter (const char *, const char *, const int); extern void strip_off_ending (char *, int); extern void _fatal_insn_not_found (const_rtx, const char *, int, const char *) ATTRIBUTE_NORETURN; Index: testsuite/gcc.dg/opts-2.c =================================================================== --- testsuite/gcc.dg/opts-2.c (revision 0) +++ testsuite/gcc.dg/opts-2.c (revision 0) @@ -0,0 +1,8 @@ +/* -O as an operand to another option should not take effect as an + optimization option. */ +/* { dg-do compile } */ +/* { dg-options "-I -O" } */ + +#ifdef __OPTIMIZE__ +#error "__OPTIMIZE__ defined" +#endif Index: opts.c =================================================================== --- opts.c (revision 160895) +++ opts.c (working copy) @@ -515,67 +515,63 @@ handle_option (int opt_index, int value, return true; } -/* Handle the switch beginning at ARGV for the language indicated by - LANG_MASK. Returns the number of switches consumed. */ -static unsigned int -read_cmdline_option (const char **argv, unsigned int lang_mask) +/* Handle the switch DECODED for the language indicated by + LANG_MASK. */ +static void +read_cmdline_option (struct cl_decoded_option *decoded, + unsigned int lang_mask) { - struct cl_decoded_option decoded; - unsigned int result; - const char *opt; const struct cl_option *option; + const char *opt; - opt = argv[0]; - - result = decode_cmdline_option (argv, lang_mask, &decoded); - if (decoded.opt_index == cl_options_count) + if (decoded->opt_index == OPT_SPECIAL_unknown) { + opt = decoded->arg; + if (opt[1] == 'W' && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-') /* We don't generate warnings for unknown -Wno-* options unless we issue diagnostics. */ - postpone_unknown_option_warning (argv[0]); + postpone_unknown_option_warning (opt); else error ("unrecognized command line option %qs", opt); - return result; + return; } - option = &cl_options[decoded.opt_index]; + option = &cl_options[decoded->opt_index]; + opt = decoded->orig_option_with_args_text; - if (decoded.errors & CL_ERR_DISABLED) + if (decoded->errors & CL_ERR_DISABLED) { error ("command line option %qs" " is not supported by this configuration", opt); - goto done; + return; } - if (decoded.errors & CL_ERR_WRONG_LANG) + if (decoded->errors & CL_ERR_WRONG_LANG) { - complain_wrong_lang (argv[0], option, lang_mask); - goto done; + complain_wrong_lang (opt, option, lang_mask); + return; } - if (decoded.errors & CL_ERR_MISSING_ARG) + if (decoded->errors & CL_ERR_MISSING_ARG) { - if (!lang_hooks.missing_argument (opt, decoded.opt_index)) + if (!lang_hooks.missing_argument (opt, decoded->opt_index)) error ("missing argument to %qs", opt); - goto done; + return; } - if (decoded.errors & CL_ERR_UINT_ARG) + if (decoded->errors & CL_ERR_UINT_ARG) { error ("argument to %qs should be a non-negative integer", option->opt_text); - goto done; + return; } - gcc_assert (!decoded.errors); + gcc_assert (!decoded->errors); - if (!handle_option (decoded.opt_index, decoded.value, decoded.arg, + if (!handle_option (decoded->opt_index, decoded->value, decoded->arg, lang_mask, DK_UNSPECIFIED)) error ("unrecognized command line option %qs", opt); - - done: - return result; } /* Handle FILENAME from the command line. */ @@ -667,40 +663,41 @@ flag_instrument_functions_exclude_p (tre } -/* Decode and handle the vector of command line options. LANG_MASK +/* Handle the vector of command line options. LANG_MASK contains has a single bit set representing the current language. */ static void -read_cmdline_options (unsigned int argc, const char **argv, unsigned int lang_mask) +read_cmdline_options (struct cl_decoded_option *decoded_options, + unsigned int decoded_options_count, + unsigned int lang_mask) { - unsigned int n, i; + unsigned int i; - for (i = 1; i < argc; i += n) + for (i = 1; i < decoded_options_count; i++) { - const char *opt = argv[i]; - - /* Interpret "-" or a non-switch as a file name. */ - if (opt[0] != '-' || opt[1] == '\0') + if (decoded_options[i].opt_index == OPT_SPECIAL_input_file) { if (main_input_filename == NULL) { - main_input_filename = opt; + main_input_filename = decoded_options[i].arg; main_input_baselength = base_of_path (main_input_filename, &main_input_basename); } - add_input_filename (opt); - n = 1; + add_input_filename (decoded_options[i].arg); continue; } - n = read_cmdline_option (argv + i, lang_mask); + read_cmdline_option (decoded_options + i, lang_mask); } } /* Parse command line options and set default flag values. Do minimal - options processing. */ + options processing. The decoded options are placed in *DECODED_OPTIONS + and *DECODED_OPTIONS_COUNT. */ void -decode_options (unsigned int argc, const char **argv) +decode_options (unsigned int argc, const char **argv, + struct cl_decoded_option **decoded_options, + unsigned int *decoded_options_count) { static bool first_time_p = true; static int initial_min_crossjump_insns; @@ -733,40 +730,30 @@ decode_options (unsigned int argc, const else lang_mask = initial_lang_mask; + decode_cmdline_options_to_array (argc, argv, lang_mask, + decoded_options, decoded_options_count); + /* Scan to see what optimization level has been specified. That will determine the default value of many flags. */ - for (i = 1; i < argc; i++) + for (i = 1; i < *decoded_options_count; i++) { - if (!strcmp (argv[i], "-O")) - { - optimize = 1; - optimize_size = 0; - ofast = 0; - } - else if (argv[i][0] == '-' && argv[i][1] == 'O') + struct cl_decoded_option *opt = &(*decoded_options)[i]; + switch (opt->opt_index) { - /* Handle -Os, -O2, -O3, -O69, ... */ - const char *p = &argv[i][2]; - - if ((p[0] == 's') && (p[1] == 0)) - { - optimize_size = 1; - - /* Optimizing for size forces optimize to be 2. */ - optimize = 2; - ofast = 0; - } - else if (strcmp (p, "fast") == 0) + case OPT_O: + if (*opt->arg == '\0') { - /* -Ofast only adds flags to -O3. */ + optimize = 1; optimize_size = 0; - optimize = 3; - ofast = 1; + ofast = 0; } else { - const int optimize_val = read_integral_parameter (p, p - 2, -1); - if (optimize_val != -1) + const int optimize_val = integral_argument (opt->arg); + if (optimize_val == -1) + error ("argument to %qs should be a non-negative integer", + "-O"); + else { optimize = optimize_val; if ((unsigned int) optimize > 255) @@ -775,6 +762,26 @@ decode_options (unsigned int argc, const ofast = 0; } } + break; + + case OPT_Os: + optimize_size = 1; + + /* Optimizing for size forces optimize to be 2. */ + optimize = 2; + ofast = 0; + break; + + case OPT_Ofast: + /* -Ofast only adds flags to -O3. */ + optimize_size = 0; + optimize = 3; + ofast = 1; + break; + + default: + /* Ignore other options in this prescan. */ + break; } } @@ -927,7 +934,7 @@ decode_options (unsigned int argc, const OPTIMIZATION_OPTIONS (optimize, optimize_size); #endif - read_cmdline_options (argc, argv, lang_mask); + read_cmdline_options (*decoded_options, *decoded_options_count, lang_mask); if (dump_base_name && ! IS_ABSOLUTE_PATH (dump_base_name)) { @@ -2419,7 +2426,7 @@ enable_warning_as_error (const char *arg new_option[0] = 'W'; strcpy (new_option + 1, arg); option_index = find_opt (new_option, lang_mask); - if (option_index == N_OPTS) + if (option_index == OPT_SPECIAL_unknown) { error ("-Werror=%s: No option -%s", arg, new_option); } Index: opts.h =================================================================== --- opts.h (revision 160895) +++ opts.h (working copy) @@ -92,7 +92,7 @@ extern const unsigned int cl_lang_count; /* Possible ways in which a command-line option may be erroneous. These do not include not being known at all; an option index of - cl_options_count is used for that. */ + OPT_SPECIAL_unknown is used for that. */ #define CL_ERR_DISABLED (1 << 0) /* Disabled in this configuration. */ #define CL_ERR_MISSING_ARG (1 << 1) /* Argument required but missing. */ @@ -103,12 +103,20 @@ extern const unsigned int cl_lang_count; struct cl_decoded_option { - /* The index of this option, or cl_options_count if not known. */ + /* The index of this option, or an OPT_SPECIAL_* value for + non-options and unknown options. */ size_t opt_index; - /* The string argument, or NULL if none. */ + /* The string argument, or NULL if none. For OPT_SPECIAL_* cases, + the option or non-option command-line argument. */ const char *arg; + /* The original text of option plus arguments, with separate argv + elements concatenated into one string with spaces separating + them. This is for such uses as diagnostics and + -frecord-gcc-switches. */ + const char *orig_option_with_args_text; + /* For a boolean option, 1 for the true case and 0 for the "no-" case. For an unsigned integer option, the value of the argument. 1 in all other cases. */ @@ -128,11 +136,15 @@ extern unsigned num_in_fnames; size_t find_opt (const char *input, int lang_mask); extern int integral_argument (const char *arg); -extern unsigned int decode_cmdline_option (const char **argv, - unsigned int lang_mask, - struct cl_decoded_option *decoded); +extern void decode_cmdline_options_to_array (unsigned int argc, + const char **argv, + unsigned int lang_mask, + struct cl_decoded_option **decoded_options, + unsigned int *decoded_options_count); extern void prune_options (int *argcp, char ***argvp); -extern void decode_options (unsigned int argc, const char **argv); +extern void decode_options (unsigned int argc, const char **argv, + struct cl_decoded_option **decoded_options, + unsigned int *decoded_options_count); extern int option_enabled (int opt_idx); extern bool get_option_state (int, struct cl_option_state *); extern void set_option (int opt_index, int value, const char *arg, int); Index: fortran/options.c =================================================================== --- fortran/options.c (revision 160895) +++ fortran/options.c (working copy) @@ -541,10 +541,6 @@ gfc_handle_option (size_t scode, const c int result = 1; enum opt_code code = (enum opt_code) scode; - /* Ignore file names. */ - if (code == N_OPTS) - return 1; - if (gfc_cpp_handle_option (scode, arg, value) == 1) return 1; Index: opth-gen.awk =================================================================== --- opth-gen.awk (revision 160895) +++ opth-gen.awk (working copy) @@ -358,7 +358,10 @@ for (i = 0; i < n_opts; i++) { print " " enum "," s "/* -" opts[i] " */" } -print " N_OPTS" +print " N_OPTS," +print " OPT_SPECIAL_unknown," +print " OPT_SPECIAL_program_name," +print " OPT_SPECIAL_input_file" print "};" print "" print "#endif /* OPTIONS_H */" Index: varasm.c =================================================================== --- varasm.c (revision 160895) +++ varasm.c (working copy) @@ -7199,50 +7199,11 @@ output_object_blocks (void) int elf_record_gcc_switches (print_switch_type type, const char * name) { - static char buffer[1024]; - - /* This variable is used as part of a simplistic heuristic to detect - command line switches which take an argument: - - "If a command line option does not start with a dash then - it is an argument for the previous command line option." - - This fails in the case of the command line option which is the name - of the file to compile, but otherwise it is pretty reasonable. */ - static bool previous_name_held_back = FALSE; - switch (type) { case SWITCH_TYPE_PASSED: - if (* name != '-') - { - if (previous_name_held_back) - { - unsigned int len = strlen (buffer); - - snprintf (buffer + len, sizeof buffer - len, " %s", name); - ASM_OUTPUT_ASCII (asm_out_file, buffer, strlen (buffer)); - ASM_OUTPUT_SKIP (asm_out_file, (unsigned HOST_WIDE_INT) 1); - previous_name_held_back = FALSE; - } - else - { - strncpy (buffer, name, sizeof buffer); - ASM_OUTPUT_ASCII (asm_out_file, buffer, strlen (buffer)); - ASM_OUTPUT_SKIP (asm_out_file, (unsigned HOST_WIDE_INT) 1); - } - } - else - { - if (previous_name_held_back) - { - ASM_OUTPUT_ASCII (asm_out_file, buffer, strlen (buffer)); - ASM_OUTPUT_SKIP (asm_out_file, (unsigned HOST_WIDE_INT) 1); - } - - strncpy (buffer, name, sizeof buffer); - previous_name_held_back = TRUE; - } + ASM_OUTPUT_ASCII (asm_out_file, name, strlen (name)); + ASM_OUTPUT_SKIP (asm_out_file, (unsigned HOST_WIDE_INT) 1); break; case SWITCH_TYPE_DESCRIPTIVE: @@ -7251,15 +7212,7 @@ elf_record_gcc_switches (print_switch_ty /* Distinguish between invocations where name is NULL. */ static bool started = false; - if (started) - { - if (previous_name_held_back) - { - ASM_OUTPUT_ASCII (asm_out_file, buffer, strlen (buffer)); - ASM_OUTPUT_SKIP (asm_out_file, (unsigned HOST_WIDE_INT) 1); - } - } - else + if (!started) { section * sec;