diff options
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/opts.c | 243 | ||||
-rw-r--r-- | gcc/opts.h | 2 |
3 files changed, 132 insertions, 121 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 28cb00c7451..e84acc123ac 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2016-01-26 Jakub Jelinek <jakub@redhat.com> + + PR lto/69254 + * opts.h (parse_sanitizer_options): New prototype. + * opts.c (sanitizer_opts): New array. + (parse_sanitizer_options): New function. + (common_handle_option): Use parse_sanitizer_options. + 2016-01-26 H.J. Lu <hongjiu.lu@intel.com> PR target/68986 diff --git a/gcc/opts.c b/gcc/opts.c index b4e8144489c..0a18c26d6e1 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -1433,6 +1433,104 @@ enable_fdo_optimizations (struct gcc_options *opts, opts->x_flag_tree_loop_distribute_patterns = value; } +/* -f{,no-}sanitize{,-recover}= suboptions. */ +static const struct sanitizer_opts_s +{ + const char *const name; + unsigned int flag; + size_t len; +} sanitizer_opts[] = +{ +#define SANITIZER_OPT(name, flags) { #name, flags, sizeof #name - 1 } + SANITIZER_OPT (address, SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS), + SANITIZER_OPT (kernel-address, SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS), + SANITIZER_OPT (thread, SANITIZE_THREAD), + SANITIZER_OPT (leak, SANITIZE_LEAK), + SANITIZER_OPT (shift, SANITIZE_SHIFT), + SANITIZER_OPT (integer-divide-by-zero, SANITIZE_DIVIDE), + SANITIZER_OPT (undefined, SANITIZE_UNDEFINED), + SANITIZER_OPT (unreachable, SANITIZE_UNREACHABLE), + SANITIZER_OPT (vla-bound, SANITIZE_VLA), + SANITIZER_OPT (return, SANITIZE_RETURN), + SANITIZER_OPT (null, SANITIZE_NULL), + SANITIZER_OPT (signed-integer-overflow, SANITIZE_SI_OVERFLOW), + SANITIZER_OPT (bool, SANITIZE_BOOL), + SANITIZER_OPT (enum, SANITIZE_ENUM), + SANITIZER_OPT (float-divide-by-zero, SANITIZE_FLOAT_DIVIDE), + SANITIZER_OPT (float-cast-overflow, SANITIZE_FLOAT_CAST), + SANITIZER_OPT (bounds, SANITIZE_BOUNDS), + SANITIZER_OPT (bounds-strict, SANITIZE_BOUNDS | SANITIZE_BOUNDS_STRICT), + SANITIZER_OPT (alignment, SANITIZE_ALIGNMENT), + SANITIZER_OPT (nonnull-attribute, SANITIZE_NONNULL_ATTRIBUTE), + SANITIZER_OPT (returns-nonnull-attribute, SANITIZE_RETURNS_NONNULL_ATTRIBUTE), + SANITIZER_OPT (object-size, SANITIZE_OBJECT_SIZE), + SANITIZER_OPT (vptr, SANITIZE_VPTR), + SANITIZER_OPT (all, ~0), +#undef SANITIZER_OPT + { NULL, 0, 0 } +}; + +/* Parse comma separated sanitizer suboptions from P for option SCODE, + adjust previous FLAGS and return new ones. If COMPLAIN is false, + don't issue diagnostics. */ + +unsigned int +parse_sanitizer_options (const char *p, location_t loc, int scode, + unsigned int flags, int value, bool complain) +{ + enum opt_code code = (enum opt_code) scode; + while (*p != 0) + { + size_t len, i; + bool found = false; + const char *comma = strchr (p, ','); + + if (comma == NULL) + len = strlen (p); + else + len = comma - p; + if (len == 0) + { + p = comma + 1; + continue; + } + + /* Check to see if the string matches an option class name. */ + for (i = 0; sanitizer_opts[i].name != NULL; ++i) + if (len == sanitizer_opts[i].len + && memcmp (p, sanitizer_opts[i].name, len) == 0) + { + /* Handle both -fsanitize and -fno-sanitize cases. */ + if (value && sanitizer_opts[i].flag == ~0U) + { + if (code == OPT_fsanitize_) + { + if (complain) + error_at (loc, "-fsanitize=all option is not valid"); + } + else + flags |= ~(SANITIZE_USER_ADDRESS | SANITIZE_THREAD + | SANITIZE_LEAK); + } + else if (value) + flags |= sanitizer_opts[i].flag; + else + flags &= ~sanitizer_opts[i].flag; + found = true; + break; + } + + if (! found && complain) + error_at (loc, "unrecognized argument to -fsanitize%s= option: %q.*s", + code == OPT_fsanitize_ ? "" : "-recover", (int) len, p); + + if (comma == NULL) + break; + p = comma + 1; + } + return flags; +} + /* 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 @@ -1626,129 +1724,32 @@ common_handle_option (struct gcc_options *opts, break; case OPT_fsanitize_: - case OPT_fsanitize_recover_: - { - const char *p = arg; - unsigned int *flag - = code == OPT_fsanitize_ ? &opts->x_flag_sanitize - : &opts->x_flag_sanitize_recover; - while (*p != 0) - { - static const struct - { - const char *const name; - unsigned int flag; - size_t len; - } spec[] = - { - { "address", SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS, - sizeof "address" - 1 }, - { "kernel-address", SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS, - sizeof "kernel-address" - 1 }, - { "thread", SANITIZE_THREAD, sizeof "thread" - 1 }, - { "leak", SANITIZE_LEAK, sizeof "leak" - 1 }, - { "shift", SANITIZE_SHIFT, sizeof "shift" - 1 }, - { "integer-divide-by-zero", SANITIZE_DIVIDE, - sizeof "integer-divide-by-zero" - 1 }, - { "undefined", SANITIZE_UNDEFINED, sizeof "undefined" - 1 }, - { "unreachable", SANITIZE_UNREACHABLE, - sizeof "unreachable" - 1 }, - { "vla-bound", SANITIZE_VLA, sizeof "vla-bound" - 1 }, - { "return", SANITIZE_RETURN, sizeof "return" - 1 }, - { "null", SANITIZE_NULL, sizeof "null" - 1 }, - { "signed-integer-overflow", SANITIZE_SI_OVERFLOW, - sizeof "signed-integer-overflow" -1 }, - { "bool", SANITIZE_BOOL, sizeof "bool" - 1 }, - { "enum", SANITIZE_ENUM, sizeof "enum" - 1 }, - { "float-divide-by-zero", SANITIZE_FLOAT_DIVIDE, - sizeof "float-divide-by-zero" - 1 }, - { "float-cast-overflow", SANITIZE_FLOAT_CAST, - sizeof "float-cast-overflow" - 1 }, - { "bounds", SANITIZE_BOUNDS, sizeof "bounds" - 1 }, - { "bounds-strict", SANITIZE_BOUNDS | SANITIZE_BOUNDS_STRICT, - sizeof "bounds-strict" - 1 }, - { "alignment", SANITIZE_ALIGNMENT, sizeof "alignment" - 1 }, - { "nonnull-attribute", SANITIZE_NONNULL_ATTRIBUTE, - sizeof "nonnull-attribute" - 1 }, - { "returns-nonnull-attribute", - SANITIZE_RETURNS_NONNULL_ATTRIBUTE, - sizeof "returns-nonnull-attribute" - 1 }, - { "object-size", SANITIZE_OBJECT_SIZE, - sizeof "object-size" - 1 }, - { "vptr", SANITIZE_VPTR, sizeof "vptr" - 1 }, - { "all", ~0, sizeof "all" - 1 }, - { NULL, 0, 0 } - }; - const char *comma; - size_t len, i; - bool found = false; - - comma = strchr (p, ','); - if (comma == NULL) - len = strlen (p); - else - len = comma - p; - if (len == 0) - { - p = comma + 1; - continue; - } - - /* Check to see if the string matches an option class name. */ - for (i = 0; spec[i].name != NULL; ++i) - if (len == spec[i].len - && memcmp (p, spec[i].name, len) == 0) - { - /* Handle both -fsanitize and -fno-sanitize cases. */ - if (value && spec[i].flag == ~0U) - { - if (code == OPT_fsanitize_) - error_at (loc, "-fsanitize=all option is not valid"); - else - *flag |= ~(SANITIZE_USER_ADDRESS | SANITIZE_THREAD - | SANITIZE_LEAK); - } - else if (value) - *flag |= spec[i].flag; - else - *flag &= ~spec[i].flag; - found = true; - break; - } + opts->x_flag_sanitize + = parse_sanitizer_options (arg, loc, code, + opts->x_flag_sanitize, value, true); - if (! found) - error_at (loc, - "unrecognized argument to -fsanitize%s= option: %q.*s", - code == OPT_fsanitize_ ? "" : "-recover", (int) len, p); - - if (comma == NULL) - break; - p = comma + 1; - } - - if (code != OPT_fsanitize_) - break; - - /* Kernel ASan implies normal ASan but does not yet support - all features. */ - if (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS) - { - maybe_set_param_value (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD, 0, - opts->x_param_values, - opts_set->x_param_values); - maybe_set_param_value (PARAM_ASAN_GLOBALS, 0, - opts->x_param_values, - opts_set->x_param_values); - maybe_set_param_value (PARAM_ASAN_STACK, 0, - opts->x_param_values, - opts_set->x_param_values); - maybe_set_param_value (PARAM_ASAN_USE_AFTER_RETURN, 0, - opts->x_param_values, - opts_set->x_param_values); - } + /* Kernel ASan implies normal ASan but does not yet support + all features. */ + if (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS) + { + maybe_set_param_value (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD, + 0, opts->x_param_values, + opts_set->x_param_values); + maybe_set_param_value (PARAM_ASAN_GLOBALS, 0, opts->x_param_values, + opts_set->x_param_values); + maybe_set_param_value (PARAM_ASAN_STACK, 0, opts->x_param_values, + opts_set->x_param_values); + maybe_set_param_value (PARAM_ASAN_USE_AFTER_RETURN, 0, + opts->x_param_values, + opts_set->x_param_values); + } + break; - break; - } + case OPT_fsanitize_recover_: + opts->x_flag_sanitize_recover + = parse_sanitizer_options (arg, loc, code, + opts->x_flag_sanitize_recover, value, true); + break; case OPT_fasan_shadow_offset_: /* Deferred. */ diff --git a/gcc/opts.h b/gcc/opts.h index 7e48dbe8fe2..6e6dbead946 100644 --- a/gcc/opts.h +++ b/gcc/opts.h @@ -372,6 +372,8 @@ extern void control_warning_option (unsigned int opt_index, int kind, extern char *write_langs (unsigned int mask); extern void print_ignored_options (void); extern void handle_common_deferred_options (void); +unsigned int parse_sanitizer_options (const char *, location_t, int, + unsigned int, int, bool); extern bool common_handle_option (struct gcc_options *opts, struct gcc_options *opts_set, const struct cl_decoded_option *decoded, |