Mercurial > hg > CbC > CbC_gcc
diff gcc/opts-common.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
line wrap: on
line diff
--- a/gcc/opts-common.c Sun Aug 21 07:07:55 2011 +0900 +++ b/gcc/opts-common.c Fri Oct 27 22:46:09 2017 +0900 @@ -1,5 +1,5 @@ /* Command line option handling. - Copyright (C) 2006, 2007, 2008, 2010 Free Software Foundation, Inc. + Copyright (C) 2006-2017 Free Software Foundation, Inc. This file is part of GCC. @@ -22,11 +22,30 @@ #include "intl.h" #include "coretypes.h" #include "opts.h" -#include "flags.h" +#include "options.h" #include "diagnostic.h" +#include "spellcheck.h" static void prune_options (struct cl_decoded_option **, unsigned int *); +/* An option that is undocumented, that takes a joined argument, and + that doesn't fit any of the classes of uses (language/common, + driver, target) is assumed to be a prefix used to catch + e.g. negated options, and stop them from being further shortened to + a prefix that could use the negated option as an argument. For + example, we want -gno-statement-frontiers to be taken as a negation + of -gstatement-frontiers, but without catching the gno- prefix and + signaling it's to be used for option remapping, it would end up + backtracked to g with no-statemnet-frontiers as the debug level. */ + +static bool +remapping_prefix_p (const struct cl_option *opt) +{ + return opt->flags & CL_UNDOCUMENTED + && opt->flags & CL_JOINED + && !(opt->flags & (CL_DRIVER | CL_TARGET | CL_COMMON | CL_LANG_ALL)); +} + /* Perform a binary search to find which option the command-line INPUT matches. Returns its index in the option array, and OPT_SPECIAL_unknown on failure. @@ -52,7 +71,7 @@ front end, the longest match for a different front end is returned (or N_OPTS if none) and the caller emits an error message. */ size_t -find_opt (const char *input, int lang_mask) +find_opt (const char *input, unsigned int lang_mask) { size_t mn, mn_orig, mx, md, opt_len; size_t match_wrong_lang; @@ -97,6 +116,9 @@ if (opt->flags & lang_mask) return mn; + if (remapping_prefix_p (opt)) + return OPT_SPECIAL_unknown; + /* If we haven't remembered a prior match, remember this one. Any prior match is necessarily better. */ if (match_wrong_lang == OPT_SPECIAL_unknown) @@ -147,7 +169,7 @@ return match_wrong_lang; } -/* If ARG is a non-negative integer made up solely of digits, return its +/* If ARG is a non-negative decimal or hexadecimal integer, return its value, otherwise return -1. */ int @@ -161,6 +183,17 @@ if (*p == '\0') return atoi (arg); + /* It wasn't a decimal number - try hexadecimal. */ + if (arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X')) + { + p = arg + 2; + while (*p && ISXDIGIT (*p)) + p++; + + if (p != arg + 2 && *p == '\0') + return strtol (arg, NULL, 16); + } + return -1; } @@ -212,6 +245,22 @@ return false; } +/* Look up ARG in the enum used by option OPT_INDEX for language + LANG_MASK, returning true and storing the value in *VALUE if found, + and returning false without modifying *VALUE if not found. */ + +bool +opt_enum_arg_to_value (size_t opt_index, const char *arg, int *value, + unsigned int lang_mask) +{ + const struct cl_option *option = &cl_options[opt_index]; + + gcc_assert (option->var_type == CLVC_ENUM); + + return enum_arg_to_value (cl_enums[option->var_enum].values, arg, + value, lang_mask); +} + /* Look of VALUE in ENUM_ARGS for language LANG_MASK and store the corresponding string in *ARGP, returning true if the found string was marked as canonical, false otherwise. If VALUE is not found @@ -257,10 +306,11 @@ const char *opt_text = option->opt_text; if (value == 0 - && !(option->flags & CL_REJECT_NEGATIVE) - && (opt_text[1] == 'W' || opt_text[1] == 'f' || opt_text[1] == 'm')) + && !option->cl_reject_negative + && (opt_text[1] == 'W' || opt_text[1] == 'f' + || opt_text[1] == 'g' || opt_text[1] == 'm')) { - char *t = XNEWVEC (char, option->opt_len + 5); + char *t = XOBNEWVEC (&opts_obstack, char, option->opt_len + 5); t[0] = '-'; t[1] = opt_text[1]; t[2] = 'n'; @@ -276,7 +326,7 @@ if (arg) { if ((option->flags & CL_SEPARATE) - && !(option->flags & CL_SEPARATE_ALIAS)) + && !option->cl_separate_alias) { decoded->canonical_option[0] = opt_text; decoded->canonical_option[1] = arg; @@ -285,7 +335,7 @@ else { gcc_assert (option->flags & CL_JOINED); - decoded->canonical_option[0] = concat (opt_text, arg, NULL); + decoded->canonical_option[0] = opts_concat (opt_text, arg, NULL); decoded->canonical_option[1] = NULL; decoded->canonical_option_num_elements = 1; } @@ -321,6 +371,7 @@ { { "-Wno-", NULL, "-W", false, true }, { "-fno-", NULL, "-f", false, true }, + { "-gno-", NULL, "-g", false, true }, { "-mno-", NULL, "-m", false, true }, { "--debug=", NULL, "-g", false, false }, { "--machine-", NULL, "-m", true, false }, @@ -338,6 +389,55 @@ { "--no-", NULL, "-f", false, true } }; +/* Helper function for gcc.c's driver::suggest_option, for populating the + vec of suggestions for misspelled options. + + option_map above provides various prefixes for spelling command-line + options, which decode_cmdline_option uses to map spellings of options + to specific options. We want to do the reverse: to find all the ways + that a user could validly spell an option. + + Given valid OPT_TEXT (with a leading dash) for OPTION, add it and all + of its valid variant spellings to CANDIDATES, each without a leading + dash. + + For example, given "-Wabi-tag", the following are added to CANDIDATES: + "Wabi-tag" + "Wno-abi-tag" + "-warn-abi-tag" + "-warn-no-abi-tag". + + The added strings must be freed using free. */ + +void +add_misspelling_candidates (auto_vec<char *> *candidates, + const struct cl_option *option, + const char *opt_text) +{ + gcc_assert (candidates); + gcc_assert (option); + gcc_assert (opt_text); + if (remapping_prefix_p (option)) + return; + candidates->safe_push (xstrdup (opt_text + 1)); + for (unsigned i = 0; i < ARRAY_SIZE (option_map); i++) + { + const char *opt0 = option_map[i].opt0; + const char *new_prefix = option_map[i].new_prefix; + size_t new_prefix_len = strlen (new_prefix); + + if (option->cl_reject_negative && option_map[i].negated) + continue; + + if (strncmp (opt_text, new_prefix, new_prefix_len) == 0) + { + char *alternative = concat (opt0 + 1, opt_text + new_prefix_len, + NULL); + candidates->safe_push (alternative); + } + } +} + /* Decode the switch beginning at ARGV for the language indicated by LANG_MASK (including CL_COMMON and CL_TARGET if applicable), into the structure *DECODED. Returns the number of switches @@ -412,7 +512,7 @@ /* Reject negative form of switches that don't take negatives as unrecognized. */ - if (!value && (option->flags & CL_REJECT_NEGATIVE)) + if (!value && option->cl_reject_negative) { opt_index = OPT_SPECIAL_unknown; errors |= CL_ERR_NEGATIVE; @@ -424,18 +524,17 @@ warn_message = option->warn_message; /* Check to see if the option is disabled for this configuration. */ - if (option->flags & CL_DISABLED) + if (option->cl_disabled) errors |= CL_ERR_DISABLED; /* Determine whether there may be a separate argument based on whether this option is being processed for the driver, and, if so, how many such arguments. */ separate_arg_flag = ((option->flags & CL_SEPARATE) - && !((option->flags & CL_NO_DRIVER_ARG) + && !(option->cl_no_driver_arg && (lang_mask & CL_DRIVER))); separate_args = (separate_arg_flag - ? ((option->flags & CL_SEPARATE_NARGS_MASK) - >> CL_SEPARATE_NARGS_SHIFT) + 1 + ? option->cl_separate_nargs + 1 : 0); joined_arg_flag = (option->flags & CL_JOINED) != 0; @@ -447,7 +546,7 @@ argument to be persistent until the program exits. */ arg = argv[extra_args] + cl_options[opt_index].opt_len + 1 + adjust_len; - if (*arg == '\0' && !(option->flags & CL_MISSING_OK)) + if (*arg == '\0' && !option->cl_missing_ok) { if (separate_arg_flag) { @@ -483,7 +582,7 @@ /* Is this option an alias (or an ignored option, marked as an alias of OPT_SPECIAL_ignore)? */ if (option->alias_target != N_OPTS - && (!(option->flags & CL_SEPARATE_ALIAS) || have_separate_arg)) + && (!option->cl_separate_alias || have_separate_arg)) { size_t new_opt_index = option->alias_target; @@ -501,12 +600,13 @@ /* The new option must not be an alias itself. */ gcc_assert (new_option->alias_target == N_OPTS - || (new_option->flags & CL_SEPARATE_ALIAS)); + || new_option->cl_separate_alias); if (option->neg_alias_arg) { gcc_assert (option->alias_arg != NULL); gcc_assert (arg == NULL); + gcc_assert (!option->cl_negative_alias); if (value) arg = option->alias_arg; else @@ -517,31 +617,34 @@ { gcc_assert (value == 1); gcc_assert (arg == NULL); + gcc_assert (!option->cl_negative_alias); arg = option->alias_arg; } + if (option->cl_negative_alias) + value = !value; + opt_index = new_opt_index; option = new_option; if (value == 0) - gcc_assert (!(option->flags & CL_REJECT_NEGATIVE)); + gcc_assert (!option->cl_reject_negative); /* Recompute what arguments are allowed. */ separate_arg_flag = ((option->flags & CL_SEPARATE) - && !((option->flags & CL_NO_DRIVER_ARG) + && !(option->cl_no_driver_arg && (lang_mask & CL_DRIVER))); joined_arg_flag = (option->flags & CL_JOINED) != 0; - if (separate_args > 1 || (option->flags & CL_SEPARATE_NARGS_MASK)) + if (separate_args > 1 || option->cl_separate_nargs) gcc_assert (separate_args - == ((option->flags & CL_SEPARATE_NARGS_MASK) - >> CL_SEPARATE_NARGS_SHIFT) + 1); + == (unsigned int) option->cl_separate_nargs + 1); if (!(errors & CL_ERR_MISSING_ARG)) { if (separate_arg_flag || joined_arg_flag) { - if ((option->flags & CL_MISSING_OK) && arg == NULL) + if (option->cl_missing_ok && arg == NULL) arg = ""; gcc_assert (arg != NULL); } @@ -555,7 +658,7 @@ gcc_assert (warn_message == NULL); warn_message = option->warn_message; } - if (option->flags & CL_DISABLED) + if (option->cl_disabled) errors |= CL_ERR_DISABLED; } } @@ -564,12 +667,30 @@ if (!option_ok_for_language (option, lang_mask)) errors |= CL_ERR_WRONG_LANG; + /* Convert the argument to lowercase if appropriate. */ + if (arg && option->cl_tolower) + { + size_t j; + size_t len = strlen (arg); + char *arg_lower = XOBNEWVEC (&opts_obstack, char, len + 1); + + for (j = 0; j < len; j++) + arg_lower[j] = TOLOWER ((unsigned char) arg[j]); + arg_lower[len] = 0; + arg = arg_lower; + } + /* If the switch takes an integer, convert it. */ - if (arg && (option->flags & CL_UINTEGER)) + if (arg && option->cl_uinteger) { value = integral_argument (arg); if (value == -1) errors |= CL_ERR_UINT_ARG; + + /* Reject value out of a range. */ + if (option->range_max != -1 + && (value < option->range_min || value > option->range_max)) + errors |= CL_ERR_INT_RANGE_ARG; } /* If the switch takes an enumerated argument, convert it. */ @@ -636,7 +757,8 @@ decoded->canonical_option_num_elements = result; } } - decoded->orig_option_with_args_text = p = XNEWVEC (char, total_len); + decoded->orig_option_with_args_text + = p = XOBNEWVEC (&opts_obstack, char, total_len); for (i = 0; i < result; i++) { size_t len = strlen (argv[i]); @@ -659,6 +781,40 @@ return result; } +/* Obstack for option strings. */ + +struct obstack opts_obstack; + +/* Like libiberty concat, but allocate using opts_obstack. */ + +char * +opts_concat (const char *first, ...) +{ + char *newstr, *end; + size_t length = 0; + const char *arg; + va_list ap; + + /* First compute the size of the result and get sufficient memory. */ + va_start (ap, first); + for (arg = first; arg; arg = va_arg (ap, const char *)) + length += strlen (arg); + newstr = XOBNEWVEC (&opts_obstack, char, length + 1); + va_end (ap); + + /* Now copy the individual pieces to the result string. */ + va_start (ap, first); + for (arg = first, end = newstr; arg; arg = va_arg (ap, const char *)) + { + length = strlen (arg); + memcpy (end, arg, length); + end += length; + } + *end = '\0'; + va_end (ap); + return newstr; +} + /* 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 @@ -677,7 +833,6 @@ unsigned int n, i; struct cl_decoded_option *opt_array; unsigned int num_decoded_options; - bool argv_copied = false; opt_array = XNEWVEC (struct cl_decoded_option, argc); @@ -712,8 +867,6 @@ num_decoded_options++; } - if (argv_copied) - free (argv); *decoded_options = opt_array; *decoded_options_count = num_decoded_options; prune_options (decoded_options, decoded_options_count); @@ -750,6 +903,7 @@ = XNEWVEC (struct cl_decoded_option, old_decoded_options_count); unsigned int i; const struct cl_option *option; + unsigned int fdiagnostics_color_idx = 0; /* Remove arguments which are negated by others after them. */ new_decoded_options_count = 0; @@ -769,6 +923,11 @@ case OPT_SPECIAL_input_file: goto keep; + /* Do not save OPT_fdiagnostics_color_, just remember the last one. */ + case OPT_fdiagnostics_color_: + fdiagnostics_color_idx = i; + continue; + default: gcc_assert (opt_idx < cl_options_count); option = &cl_options[opt_idx]; @@ -804,6 +963,17 @@ } } + if (fdiagnostics_color_idx >= 1) + { + /* We put the last -fdiagnostics-color= at the first position + after argv[0] so it can take effect immediately. */ + memmove (new_decoded_options + 2, new_decoded_options + 1, + sizeof (struct cl_decoded_option) + * (new_decoded_options_count - 1)); + new_decoded_options[1] = old_decoded_options[fdiagnostics_color_idx]; + new_decoded_options_count++; + } + free (old_decoded_options); new_decoded_options = XRESIZEVEC (struct cl_decoded_option, new_decoded_options, @@ -819,9 +989,10 @@ option for options from the source file, UNKNOWN_LOCATION otherwise. GENERATED_P is true for an option generated as part of processing another option or otherwise generated internally, false - for one explicitly passed by the user. Returns false if the switch - was invalid. DC is the diagnostic context for options affecting - diagnostics state, or NULL. */ + for one explicitly passed by the user. control_warning_option + generated options are considered explicitly passed by the user. + Returns false if the switch was invalid. DC is the diagnostic + context for options affecting diagnostics state, or NULL. */ static bool handle_option (struct gcc_options *opts, @@ -847,11 +1018,9 @@ { if (!handlers->handlers[i].handler (opts, opts_set, decoded, lang_mask, kind, loc, - handlers, dc)) + handlers, dc, + handlers->target_option_override_hook)) return false; - else - handlers->post_handling_callback (decoded, - handlers->handlers[i].mask); } return true; @@ -868,13 +1037,13 @@ size_t opt_index, const char *arg, int value, unsigned int lang_mask, int kind, location_t loc, const struct cl_option_handlers *handlers, - diagnostic_context *dc) + bool generated_p, diagnostic_context *dc) { struct cl_decoded_option decoded; generate_option (opt_index, arg, value, lang_mask, &decoded); return handle_option (opts, opts_set, &decoded, lang_mask, kind, loc, - handlers, true, dc); + handlers, generated_p, dc); } /* Fill in *DECODED with an option described by OPT_INDEX, ARG and @@ -904,8 +1073,8 @@ case 2: decoded->orig_option_with_args_text - = concat (decoded->canonical_option[0], " ", - decoded->canonical_option[1], NULL); + = opts_concat (decoded->canonical_option[0], " ", + decoded->canonical_option[1], NULL); break; default: @@ -932,6 +1101,112 @@ decoded->errors = 0; } +/* Helper function for listing valid choices and hint for misspelled + value. CANDIDATES is a vector containing all valid strings, + STR is set to a heap allocated string that contains all those + strings concatenated, separated by spaces, and the return value + is the closest string from those to ARG, or NULL if nothing is + close enough. Callers should XDELETEVEC (STR) after using it + to avoid memory leaks. */ + +const char * +candidates_list_and_hint (const char *arg, char *&str, + const auto_vec <const char *> &candidates) +{ + size_t len = 0; + int i; + const char *candidate; + char *p; + + FOR_EACH_VEC_ELT (candidates, i, candidate) + len += strlen (candidate) + 1; + + str = p = XNEWVEC (char, len); + FOR_EACH_VEC_ELT (candidates, i, candidate) + { + len = strlen (candidate); + memcpy (p, candidate, len); + p[len] = ' '; + p += len + 1; + } + p[-1] = '\0'; + return find_closest_string (arg, &candidates); +} + +/* Perform diagnostics for read_cmdline_option and control_warning_option + functions. Returns true if an error has been diagnosed. + LOC and LANG_MASK arguments like in read_cmdline_option. + OPTION is the option to report diagnostics for, OPT the name + of the option as text, ARG the argument of the option (for joined + options), ERRORS is bitmask of CL_ERR_* values. */ + +static bool +cmdline_handle_error (location_t loc, const struct cl_option *option, + const char *opt, const char *arg, int errors, + unsigned int lang_mask) +{ + if (errors & CL_ERR_DISABLED) + { + error_at (loc, "command line option %qs" + " is not supported by this configuration", opt); + return true; + } + + if (errors & CL_ERR_MISSING_ARG) + { + if (option->missing_argument_error) + error_at (loc, option->missing_argument_error, opt); + else + error_at (loc, "missing argument to %qs", opt); + return true; + } + + if (errors & CL_ERR_UINT_ARG) + { + error_at (loc, "argument to %qs should be a non-negative integer", + option->opt_text); + return true; + } + + if (errors & CL_ERR_INT_RANGE_ARG) + { + error_at (loc, "argument to %qs is not between %d and %d", + option->opt_text, option->range_min, option->range_max); + return true; + } + + if (errors & CL_ERR_ENUM_ARG) + { + const struct cl_enum *e = &cl_enums[option->var_enum]; + unsigned int i; + char *s; + + if (e->unknown_error) + error_at (loc, e->unknown_error, arg); + else + error_at (loc, "unrecognized argument in option %qs", opt); + + auto_vec <const char *> candidates; + for (i = 0; e->values[i].arg != NULL; i++) + { + if (!enum_arg_ok_for_language (&e->values[i], lang_mask)) + continue; + candidates.safe_push (e->values[i].arg); + } + const char *hint = candidates_list_and_hint (arg, s, candidates); + if (hint) + inform (loc, "valid arguments to %qs are: %s; did you mean %qs?", + option->opt_text, s, hint); + else + inform (loc, "valid arguments to %qs are: %s", option->opt_text, s); + XDELETEVEC (s); + + return true; + } + + return false; +} + /* Handle the switch DECODED (location LOC) for the language indicated by LANG_MASK, using the handlers in *HANDLERS and setting fields in OPTS and OPTS_SET and using diagnostic context DC (if not NULL) for @@ -964,58 +1239,10 @@ option = &cl_options[decoded->opt_index]; - if (decoded->errors & CL_ERR_DISABLED) - { - error_at (loc, "command line option %qs" - " is not supported by this configuration", opt); - return; - } - - if (decoded->errors & CL_ERR_MISSING_ARG) - { - if (option->missing_argument_error) - error_at (loc, option->missing_argument_error, opt); - else - error_at (loc, "missing argument to %qs", opt); - return; - } - - if (decoded->errors & CL_ERR_UINT_ARG) - { - error_at (loc, "argument to %qs should be a non-negative integer", - option->opt_text); - return; - } - - if (decoded->errors & CL_ERR_ENUM_ARG) - { - const struct cl_enum *e = &cl_enums[option->var_enum]; - unsigned int i; - size_t len; - char *s, *p; - - if (e->unknown_error) - error_at (loc, e->unknown_error, decoded->arg); - else - error_at (loc, "unrecognized argument in option %qs", opt); - - len = 0; - for (i = 0; e->values[i].arg != NULL; i++) - len += strlen (e->values[i].arg) + 1; - - s = XALLOCAVEC (char, len); - p = s; - for (i = 0; e->values[i].arg != NULL; i++) - { - size_t arglen = strlen (e->values[i].arg); - memcpy (p, e->values[i].arg, arglen); - p[arglen] = ' '; - p += arglen + 1; - } - p[-1] = 0; - inform (loc, "valid arguments to %qs are: %s", option->opt_text, s); - return; - } + if (decoded->errors + && cmdline_handle_error (loc, option, opt, decoded->arg, + decoded->errors, lang_mask)) + return; if (decoded->errors & CL_ERR_WRONG_LANG) { @@ -1047,6 +1274,9 @@ if (!flag_var) return; + if ((diagnostic_t) kind != DK_UNSPECIFIED && dc != NULL) + diagnostic_classify_diagnostic (dc, opt_index, (diagnostic_t) kind, loc); + if (opts_set != NULL) set_flag_var = option_flag_var (opt_index, opts_set); @@ -1059,9 +1289,14 @@ break; case CLVC_EQUAL: - *(int *) flag_var = (value - ? option->var_value - : !option->var_value); + if (option->cl_host_wide_int) + *(HOST_WIDE_INT *) flag_var = (value + ? option->var_value + : !option->var_value); + else + *(int *) flag_var = (value + ? option->var_value + : !option->var_value); if (set_flag_var) *(int *) set_flag_var = 1; break; @@ -1069,11 +1304,26 @@ case CLVC_BIT_CLEAR: case CLVC_BIT_SET: if ((value != 0) == (option->var_type == CLVC_BIT_SET)) - *(int *) flag_var |= option->var_value; + { + if (option->cl_host_wide_int) + *(HOST_WIDE_INT *) flag_var |= option->var_value; + else + *(int *) flag_var |= option->var_value; + } else - *(int *) flag_var &= ~option->var_value; + { + if (option->cl_host_wide_int) + *(HOST_WIDE_INT *) flag_var &= ~option->var_value; + else + *(int *) flag_var &= ~option->var_value; + } if (set_flag_var) - *(int *) set_flag_var |= option->var_value; + { + if (option->cl_host_wide_int) + *(HOST_WIDE_INT *) set_flag_var |= option->var_value; + else + *(int *) set_flag_var |= option->var_value; + } break; case CLVC_STRING: @@ -1094,24 +1344,18 @@ case CLVC_DEFER: { - VEC(cl_deferred_option,heap) *vec - = (VEC(cl_deferred_option,heap) *) *(void **) flag_var; - cl_deferred_option *p; - - p = VEC_safe_push (cl_deferred_option, heap, vec, NULL); - p->opt_index = opt_index; - p->arg = arg; - p->value = value; - *(void **) flag_var = vec; + vec<cl_deferred_option> *v + = (vec<cl_deferred_option> *) *(void **) flag_var; + cl_deferred_option p = {opt_index, arg, value}; + if (!v) + v = XCNEW (vec<cl_deferred_option>); + v->safe_push (p); + *(void **) flag_var = v; if (set_flag_var) - *(void **) set_flag_var = vec; + *(void **) set_flag_var = v; } break; } - - if ((diagnostic_t) kind != DK_UNSPECIFIED - && dc != NULL) - diagnostic_classify_diagnostic (dc, opt_index, (diagnostic_t) kind, loc); } /* Return the address of the flag variable for option OPT_INDEX in @@ -1144,13 +1388,22 @@ return *(int *) flag_var != 0; case CLVC_EQUAL: - return *(int *) flag_var == option->var_value; + if (option->cl_host_wide_int) + return *(HOST_WIDE_INT *) flag_var == option->var_value; + else + return *(int *) flag_var == option->var_value; case CLVC_BIT_CLEAR: - return (*(int *) flag_var & option->var_value) == 0; + if (option->cl_host_wide_int) + return (*(HOST_WIDE_INT *) flag_var & option->var_value) == 0; + else + return (*(int *) flag_var & option->var_value) == 0; case CLVC_BIT_SET: - return (*(int *) flag_var & option->var_value) != 0; + if (option->cl_host_wide_int) + return (*(HOST_WIDE_INT *) flag_var & option->var_value) != 0; + else + return (*(int *) flag_var & option->var_value) != 0; case CLVC_STRING: case CLVC_ENUM: @@ -1177,7 +1430,9 @@ case CLVC_BOOLEAN: case CLVC_EQUAL: state->data = flag_var; - state->size = sizeof (int); + state->size = (cl_options[option].cl_host_wide_int + ? sizeof (HOST_WIDE_INT) + : sizeof (int)); break; case CLVC_BIT_CLEAR: @@ -1208,30 +1463,86 @@ /* Set a warning option OPT_INDEX (language mask LANG_MASK, option handlers HANDLERS) to have diagnostic kind KIND for option structures OPTS and OPTS_SET and diagnostic context DC (possibly - NULL), at location LOC (UNKNOWN_LOCATION for -Werror=). If IMPLY, + NULL), at location LOC (UNKNOWN_LOCATION for -Werror=). ARG is the + argument of the option for joined options, or NULL otherwise. If IMPLY, the warning option in question is implied at this point. This is used by -Werror= and #pragma GCC diagnostic. */ void -control_warning_option (unsigned int opt_index, int kind, bool imply, - location_t loc, unsigned int lang_mask, +control_warning_option (unsigned int opt_index, int kind, const char *arg, + bool imply, location_t loc, unsigned int lang_mask, const struct cl_option_handlers *handlers, struct gcc_options *opts, struct gcc_options *opts_set, diagnostic_context *dc) { if (cl_options[opt_index].alias_target != N_OPTS) - opt_index = cl_options[opt_index].alias_target; + { + gcc_assert (!cl_options[opt_index].cl_separate_alias + && !cl_options[opt_index].cl_negative_alias); + if (cl_options[opt_index].alias_arg) + arg = cl_options[opt_index].alias_arg; + opt_index = cl_options[opt_index].alias_target; + } if (opt_index == OPT_SPECIAL_ignore) return; if (dc) diagnostic_classify_diagnostic (dc, opt_index, (diagnostic_t) kind, loc); if (imply) { + const struct cl_option *option = &cl_options[opt_index]; + /* -Werror=foo implies -Wfoo. */ - if (cl_options[opt_index].var_type == CLVC_BOOLEAN) - handle_generated_option (opts, opts_set, - opt_index, NULL, 1, lang_mask, - kind, loc, handlers, dc); + if (option->var_type == CLVC_BOOLEAN || option->var_type == CLVC_ENUM) + { + int value = 1; + + if (arg && *arg == '\0' && !option->cl_missing_ok) + arg = NULL; + + if ((option->flags & CL_JOINED) && arg == NULL) + { + cmdline_handle_error (loc, option, option->opt_text, arg, + CL_ERR_MISSING_ARG, lang_mask); + return; + } + + /* If the switch takes an integer, convert it. */ + if (arg && option->cl_uinteger) + { + value = integral_argument (arg); + if (value == -1) + { + cmdline_handle_error (loc, option, option->opt_text, arg, + CL_ERR_UINT_ARG, lang_mask); + return; + } + } + + /* If the switch takes an enumerated argument, convert it. */ + if (arg && option->var_type == CLVC_ENUM) + { + const struct cl_enum *e = &cl_enums[option->var_enum]; + + if (enum_arg_to_value (e->values, arg, &value, lang_mask)) + { + const char *carg = NULL; + + if (enum_value_to_arg (e->values, &carg, value, lang_mask)) + arg = carg; + gcc_assert (carg != NULL); + } + else + { + cmdline_handle_error (loc, option, option->opt_text, arg, + CL_ERR_ENUM_ARG, lang_mask); + return; + } + } + + handle_generated_option (opts, opts_set, + opt_index, arg, value, lang_mask, + kind, loc, handlers, false, dc); + } } }