summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/opts.c243
-rw-r--r--gcc/opts.h2
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,