re PR lto/69254 (ICE in streamer_get_builtin_tree when using -fsanitize=shift on the compile side only)
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. From-SVN: r232826
This commit is contained in:
parent
81cd202e24
commit
b1b46af04f
|
@ -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
|
||||
|
|
245
gcc/opts.c
245
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_:
|
||||
opts->x_flag_sanitize
|
||||
= parse_sanitizer_options (arg, loc, code,
|
||||
opts->x_flag_sanitize, value, true);
|
||||
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
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. */
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue