Reimplement -fsanitize-recover family of flags.

Introduce the following -fsanitize-recover flags:
  - -fsanitize-recover=<list>: Enable recovery for selected checks or
      group of checks. It is forbidden to explicitly list unrecoverable
      sanitizers here (that is, "address", "unreachable", "return").
  - -fno-sanitize-recover=<list>: Disable recovery for selected checks or
     group of checks.
  - -f(no-)?sanitize-recover is now a synonym for
    -f(no-)?sanitize-recover=undefined,integer and will soon be deprecated.

These flags are parsed left to right, and mask of "recoverable"
sanitizer is updated accordingly, much like what we do for -fsanitize= flags.
-fsanitize= and -fsanitize-recover= flag families are independent.

CodeGen change: If there is a single UBSan handler function, responsible
for implementing multiple checks, which have different recoverable setting,
then we emit two handler calls instead of one:
the first one for the set of "unrecoverable" checks, another one - for
set of "recoverable" checks. If all checks implemented by a handler have the
same recoverability setting, then the generated code will be the same.

llvm-svn: 225719
This commit is contained in:
Alexey Samsonov
2015-01-12 22:39:12 +00:00
parent d88ab87064
commit 8845952b54
14 changed files with 227 additions and 86 deletions

View File

@@ -325,6 +325,21 @@ GenerateOptimizationRemarkRegex(DiagnosticsEngine &Diags, ArgList &Args,
return Pattern;
}
static void parseSanitizerKinds(StringRef FlagName,
const std::vector<std::string> &Sanitizers,
DiagnosticsEngine &Diags, SanitizerSet &S) {
for (const auto &Sanitizer : Sanitizers) {
SanitizerKind K = llvm::StringSwitch<SanitizerKind>(Sanitizer)
#define SANITIZER(NAME, ID) .Case(NAME, SanitizerKind::ID)
#include "clang/Basic/Sanitizers.def"
.Default(SanitizerKind::Unknown);
if (K == SanitizerKind::Unknown)
Diags.Report(diag::err_drv_invalid_value) << FlagName << Sanitizer;
else
S.set(K, true);
}
}
static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
DiagnosticsEngine &Diags,
const TargetOptions &TargetOpts) {
@@ -465,7 +480,6 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name);
Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier);
Opts.SanitizeRecover = !Args.hasArg(OPT_fno_sanitize_recover);
Opts.DisableGCov = Args.hasArg(OPT_test_coverage);
Opts.EmitGcovArcs = Args.hasArg(OPT_femit_coverage_data);
@@ -596,6 +610,12 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.RewriteMapFiles = Args.getAllArgValues(OPT_frewrite_map_file);
// Parse -fsanitize-recover= arguments.
// FIXME: Report unrecoverable sanitizers incorrectly specified here.
parseSanitizerKinds("-fsanitize-recover=",
Args.getAllArgValues(OPT_fsanitize_recover_EQ), Diags,
Opts.SanitizeRecover);
return Success;
}
@@ -1635,18 +1655,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
}
// Parse -fsanitize= arguments.
std::vector<std::string> Sanitizers = Args.getAllArgValues(OPT_fsanitize_EQ);
for (const auto &Sanitizer : Sanitizers) {
SanitizerKind K = llvm::StringSwitch<SanitizerKind>(Sanitizer)
#define SANITIZER(NAME, ID) .Case(NAME, SanitizerKind::ID)
#include "clang/Basic/Sanitizers.def"
.Default(SanitizerKind::Unknown);
if (K == SanitizerKind::Unknown)
Diags.Report(diag::err_drv_invalid_value)
<< "-fsanitize=" << Sanitizer;
else
Opts.Sanitize.set(K, true);
}
parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
Diags, Opts.Sanitize);
// -fsanitize-address-field-padding=N has to be a LangOpt, parse it here.
Opts.SanitizeAddressFieldPadding =
getLastArgIntValue(Args, OPT_fsanitize_address_field_padding, 0, Diags);