summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Samsonov <samsonov@google.com>2013-08-08 10:11:02 +0000
committerAlexey Samsonov <samsonov@google.com>2013-08-08 10:11:02 +0000
commit442c60a92b6e3980e0f69a195a264ec2ffa2dd6d (patch)
tree67e43a17a706be8fb9387978addabd0a5adde350
parentb26404a7505dab7ec3a16f6e3b85f95cfd59ba93 (diff)
Move SanitizerArgs implementation from .h to .cpp
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@187972 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Driver/CMakeLists.txt1
-rw-r--r--lib/Driver/SanitizerArgs.cpp293
-rw-r--r--lib/Driver/SanitizerArgs.h152
-rw-r--r--lib/Driver/Tools.cpp124
4 files changed, 308 insertions, 262 deletions
diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt
index f380e50388..69d18adce1 100644
--- a/lib/Driver/CMakeLists.txt
+++ b/lib/Driver/CMakeLists.txt
@@ -6,6 +6,7 @@ add_clang_library(clangDriver
DriverOptions.cpp
Job.cpp
Phases.cpp
+ SanitizerArgs.cpp
Tool.cpp
ToolChain.cpp
ToolChains.cpp
diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp
new file mode 100644
index 0000000000..5d2ea89224
--- /dev/null
+++ b/lib/Driver/SanitizerArgs.cpp
@@ -0,0 +1,293 @@
+//===--- SanitizerArgs.cpp - Arguments for sanitizer tools ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "SanitizerArgs.h"
+
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/ToolChain.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+
+using namespace clang::driver;
+using namespace llvm::opt;
+
+SanitizerArgs::SanitizerArgs()
+ : Kind(0), BlacklistFile(""), MsanTrackOrigins(false),
+ AsanZeroBaseShadow(false), UbsanTrapOnError(false) {}
+
+SanitizerArgs::SanitizerArgs(const ToolChain &TC,
+ const llvm::opt::ArgList &Args)
+ : Kind(0), BlacklistFile(""), MsanTrackOrigins(false),
+ AsanZeroBaseShadow(false) {
+ unsigned AllKinds = 0; // All kinds of sanitizers that were turned on
+ // at least once (possibly, disabled further).
+ const Driver &D = TC.getDriver();
+ for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) {
+ unsigned Add, Remove;
+ if (!parse(D, Args, *I, Add, Remove, true))
+ continue;
+ (*I)->claim();
+ Kind |= Add;
+ Kind &= ~Remove;
+ AllKinds |= Add;
+ }
+
+ UbsanTrapOnError =
+ Args.hasArg(options::OPT_fcatch_undefined_behavior) ||
+ Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
+ options::OPT_fno_sanitize_undefined_trap_on_error, false);
+
+ if (Args.hasArg(options::OPT_fcatch_undefined_behavior) &&
+ !Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
+ options::OPT_fno_sanitize_undefined_trap_on_error, true)) {
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fcatch-undefined-behavior"
+ << "-fno-sanitize-undefined-trap-on-error";
+ }
+
+ // Warn about undefined sanitizer options that require runtime support.
+ if (UbsanTrapOnError && notAllowedWithTrap()) {
+ if (Args.hasArg(options::OPT_fcatch_undefined_behavior))
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << lastArgumentForKind(D, Args, NotAllowedWithTrap)
+ << "-fcatch-undefined-behavior";
+ else if (Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
+ options::OPT_fno_sanitize_undefined_trap_on_error,
+ false))
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << lastArgumentForKind(D, Args, NotAllowedWithTrap)
+ << "-fsanitize-undefined-trap-on-error";
+ }
+
+ // Only one runtime library can be used at once.
+ bool NeedsAsan = needsAsanRt();
+ bool NeedsTsan = needsTsanRt();
+ bool NeedsMsan = needsMsanRt();
+ bool NeedsLsan = needsLeakDetection();
+ if (NeedsAsan && NeedsTsan)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << lastArgumentForKind(D, Args, NeedsAsanRt)
+ << lastArgumentForKind(D, Args, NeedsTsanRt);
+ if (NeedsAsan && NeedsMsan)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << lastArgumentForKind(D, Args, NeedsAsanRt)
+ << lastArgumentForKind(D, Args, NeedsMsanRt);
+ if (NeedsTsan && NeedsMsan)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << lastArgumentForKind(D, Args, NeedsTsanRt)
+ << lastArgumentForKind(D, Args, NeedsMsanRt);
+ if (NeedsLsan && NeedsTsan)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << lastArgumentForKind(D, Args, NeedsLeakDetection)
+ << lastArgumentForKind(D, Args, NeedsTsanRt);
+ if (NeedsLsan && NeedsMsan)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << lastArgumentForKind(D, Args, NeedsLeakDetection)
+ << lastArgumentForKind(D, Args, NeedsMsanRt);
+ // FIXME: Currenly -fsanitize=leak is silently ignored in the presence of
+ // -fsanitize=address. Perhaps it should print an error, or perhaps
+ // -f(-no)sanitize=leak should change whether leak detection is enabled by
+ // default in ASan?
+
+ // If -fsanitize contains extra features of ASan, it should also
+ // explicitly contain -fsanitize=address (probably, turned off later in the
+ // command line).
+ if ((Kind & AddressFull) != 0 && (AllKinds & Address) == 0)
+ D.Diag(diag::warn_drv_unused_sanitizer)
+ << lastArgumentForKind(D, Args, AddressFull)
+ << "-fsanitize=address";
+
+ // Parse -f(no-)sanitize-blacklist options.
+ if (Arg *BLArg = Args.getLastArg(options::OPT_fsanitize_blacklist,
+ options::OPT_fno_sanitize_blacklist)) {
+ if (BLArg->getOption().matches(options::OPT_fsanitize_blacklist)) {
+ std::string BLPath = BLArg->getValue();
+ if (llvm::sys::fs::exists(BLPath))
+ BlacklistFile = BLPath;
+ else
+ D.Diag(diag::err_drv_no_such_file) << BLPath;
+ }
+ } else {
+ // If no -fsanitize-blacklist option is specified, try to look up for
+ // blacklist in the resource directory.
+ std::string BLPath;
+ if (getDefaultBlacklistForKind(D, Kind, BLPath) &&
+ llvm::sys::fs::exists(BLPath))
+ BlacklistFile = BLPath;
+ }
+
+ // Parse -f(no-)sanitize-memory-track-origins options.
+ if (NeedsMsan)
+ MsanTrackOrigins =
+ Args.hasFlag(options::OPT_fsanitize_memory_track_origins,
+ options::OPT_fno_sanitize_memory_track_origins,
+ /* Default */false);
+
+ // Parse -f(no-)sanitize-address-zero-base-shadow options.
+ if (NeedsAsan) {
+ bool IsAndroid = (TC.getTriple().getEnvironment() == llvm::Triple::Android);
+ bool ZeroBaseShadowDefault = IsAndroid;
+ AsanZeroBaseShadow =
+ Args.hasFlag(options::OPT_fsanitize_address_zero_base_shadow,
+ options::OPT_fno_sanitize_address_zero_base_shadow,
+ ZeroBaseShadowDefault);
+ // Zero-base shadow is a requirement on Android.
+ if (IsAndroid && !AsanZeroBaseShadow) {
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fno-sanitize-address-zero-base-shadow"
+ << lastArgumentForKind(D, Args, Address);
+ }
+ }
+}
+
+void SanitizerArgs::addArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const {
+ if (!Kind)
+ return;
+ SmallString<256> SanitizeOpt("-fsanitize=");
+#define SANITIZER(NAME, ID) \
+ if (Kind & ID) \
+ SanitizeOpt += NAME ",";
+#include "clang/Basic/Sanitizers.def"
+ SanitizeOpt.pop_back();
+ CmdArgs.push_back(Args.MakeArgString(SanitizeOpt));
+ if (!BlacklistFile.empty()) {
+ SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
+ BlacklistOpt += BlacklistFile;
+ CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
+ }
+
+ if (MsanTrackOrigins)
+ CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins"));
+
+ if (AsanZeroBaseShadow)
+ CmdArgs.push_back(
+ Args.MakeArgString("-fsanitize-address-zero-base-shadow"));
+
+ // Workaround for PR16386.
+ if (needsMsanRt())
+ CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new"));
+}
+
+unsigned SanitizerArgs::parse(const char *Value) {
+ unsigned ParsedKind = llvm::StringSwitch<SanitizeKind>(Value)
+#define SANITIZER(NAME, ID) .Case(NAME, ID)
+#define SANITIZER_GROUP(NAME, ID, ALIAS) .Case(NAME, ID)
+#include "clang/Basic/Sanitizers.def"
+ .Default(SanitizeKind());
+ // Assume -fsanitize=address implies -fsanitize=init-order.
+ // FIXME: This should be either specified in Sanitizers.def, or go away when
+ // we get rid of "-fsanitize=init-order" flag at all.
+ if (ParsedKind & Address)
+ ParsedKind |= InitOrder;
+ return ParsedKind;
+}
+
+unsigned SanitizerArgs::parse(const Driver &D, const llvm::opt::Arg *A,
+ bool DiagnoseErrors) {
+ unsigned Kind = 0;
+ for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) {
+ if (unsigned K = parse(A->getValue(I)))
+ Kind |= K;
+ else if (DiagnoseErrors)
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << A->getValue(I);
+ }
+ return Kind;
+}
+
+bool SanitizerArgs::parse(const Driver &D, const llvm::opt::ArgList &Args,
+ const llvm::opt::Arg *A, unsigned &Add,
+ unsigned &Remove, bool DiagnoseErrors) {
+ Add = 0;
+ Remove = 0;
+ const char *DeprecatedReplacement = 0;
+ if (A->getOption().matches(options::OPT_faddress_sanitizer)) {
+ Add = Address;
+ DeprecatedReplacement = "-fsanitize=address";
+ } else if (A->getOption().matches(options::OPT_fno_address_sanitizer)) {
+ Remove = Address;
+ DeprecatedReplacement = "-fno-sanitize=address";
+ } else if (A->getOption().matches(options::OPT_fthread_sanitizer)) {
+ Add = Thread;
+ DeprecatedReplacement = "-fsanitize=thread";
+ } else if (A->getOption().matches(options::OPT_fno_thread_sanitizer)) {
+ Remove = Thread;
+ DeprecatedReplacement = "-fno-sanitize=thread";
+ } else if (A->getOption().matches(options::OPT_fcatch_undefined_behavior)) {
+ Add = UndefinedTrap;
+ DeprecatedReplacement =
+ "-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error";
+ } else if (A->getOption().matches(options::OPT_fbounds_checking) ||
+ A->getOption().matches(options::OPT_fbounds_checking_EQ)) {
+ Add = Bounds;
+ DeprecatedReplacement = "-fsanitize=bounds";
+ } else if (A->getOption().matches(options::OPT_fsanitize_EQ)) {
+ Add = parse(D, A, DiagnoseErrors);
+ } else if (A->getOption().matches(options::OPT_fno_sanitize_EQ)) {
+ Remove = parse(D, A, DiagnoseErrors);
+ } else {
+ // Flag is not relevant to sanitizers.
+ return false;
+ }
+ // If this is a deprecated synonym, produce a warning directing users
+ // towards the new spelling.
+ if (DeprecatedReplacement && DiagnoseErrors)
+ D.Diag(diag::warn_drv_deprecated_arg)
+ << A->getAsString(Args) << DeprecatedReplacement;
+ return true;
+}
+
+std::string SanitizerArgs::lastArgumentForKind(const Driver &D,
+ const llvm::opt::ArgList &Args,
+ unsigned Kind) {
+ for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
+ E = Args.rend();
+ I != E; ++I) {
+ unsigned Add, Remove;
+ if (parse(D, Args, *I, Add, Remove, false) &&
+ (Add & Kind))
+ return describeSanitizeArg(Args, *I, Kind);
+ Kind &= ~Remove;
+ }
+ llvm_unreachable("arg list didn't provide expected value");
+}
+
+std::string SanitizerArgs::describeSanitizeArg(const llvm::opt::ArgList &Args,
+ const llvm::opt::Arg *A,
+ unsigned Mask) {
+ if (!A->getOption().matches(options::OPT_fsanitize_EQ))
+ return A->getAsString(Args);
+
+ for (unsigned I = 0, N = A->getNumValues(); I != N; ++I)
+ if (parse(A->getValue(I)) & Mask)
+ return std::string("-fsanitize=") + A->getValue(I);
+
+ llvm_unreachable("arg didn't provide expected value");
+}
+
+bool SanitizerArgs::getDefaultBlacklistForKind(const Driver &D, unsigned Kind,
+ std::string &BLPath) {
+ const char *BlacklistFile = 0;
+ if (Kind & NeedsAsanRt)
+ BlacklistFile = "asan_blacklist.txt";
+ else if (Kind & NeedsMsanRt)
+ BlacklistFile = "msan_blacklist.txt";
+ else if (Kind & NeedsTsanRt)
+ BlacklistFile = "tsan_blacklist.txt";
+ if (BlacklistFile) {
+ SmallString<64> Path(D.ResourceDir);
+ llvm::sys::path::append(Path, BlacklistFile);
+ BLPath = Path.str();
+ return true;
+ }
+ return false;
+}
diff --git a/lib/Driver/SanitizerArgs.h b/lib/Driver/SanitizerArgs.h
index 58dece9b56..e622d0010d 100644
--- a/lib/Driver/SanitizerArgs.h
+++ b/lib/Driver/SanitizerArgs.h
@@ -9,17 +9,17 @@
#ifndef CLANG_LIB_DRIVER_SANITIZERARGS_H_
#define CLANG_LIB_DRIVER_SANITIZERARGS_H_
-#include "clang/Driver/Driver.h"
-#include "clang/Driver/DriverDiagnostic.h"
-#include "clang/Driver/Options.h"
-#include "llvm/ADT/StringSwitch.h"
+#include <string>
+
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
-#include "llvm/Support/Path.h"
namespace clang {
namespace driver {
+class Driver;
+class ToolChain;
+
class SanitizerArgs {
/// Assign ordinals to sanitizer flags. We'll use the ordinal values as
/// bit positions within \c Kind.
@@ -50,8 +50,7 @@ class SanitizerArgs {
bool UbsanTrapOnError;
public:
- SanitizerArgs() : Kind(0), BlacklistFile(""), MsanTrackOrigins(false),
- AsanZeroBaseShadow(false), UbsanTrapOnError(false) {}
+ SanitizerArgs();
/// Parses the sanitizer arguments from an argument list.
SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args);
@@ -63,9 +62,7 @@ class SanitizerArgs {
return needsLeakDetection() && !needsAsanRt();
}
bool needsUbsanRt() const {
- if (UbsanTrapOnError)
- return false;
- return Kind & NeedsUbsanRt;
+ return !UbsanTrapOnError && (Kind & NeedsUbsanRt);
}
bool needsDfsanRt() const { return Kind & NeedsDfsanRt; }
@@ -76,111 +73,25 @@ class SanitizerArgs {
}
void addArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const {
- if (!Kind)
- return;
- SmallString<256> SanitizeOpt("-fsanitize=");
-#define SANITIZER(NAME, ID) \
- if (Kind & ID) \
- SanitizeOpt += NAME ",";
-#include "clang/Basic/Sanitizers.def"
- SanitizeOpt.pop_back();
- CmdArgs.push_back(Args.MakeArgString(SanitizeOpt));
- if (!BlacklistFile.empty()) {
- SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
- BlacklistOpt += BlacklistFile;
- CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
- }
-
- if (MsanTrackOrigins)
- CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins"));
-
- if (AsanZeroBaseShadow)
- CmdArgs.push_back(
- Args.MakeArgString("-fsanitize-address-zero-base-shadow"));
-
- // Workaround for PR16386.
- if (needsMsanRt())
- CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new"));
- }
+ llvm::opt::ArgStringList &CmdArgs) const;
private:
/// Parse a single value from a -fsanitize= or -fno-sanitize= value list.
/// Returns OR of members of the \c SanitizeKind enumeration, or \c 0
/// if \p Value is not known.
- static unsigned parse(const char *Value) {
- unsigned ParsedKind = llvm::StringSwitch<SanitizeKind>(Value)
-#define SANITIZER(NAME, ID) .Case(NAME, ID)
-#define SANITIZER_GROUP(NAME, ID, ALIAS) .Case(NAME, ID)
-#include "clang/Basic/Sanitizers.def"
- .Default(SanitizeKind());
- // Assume -fsanitize=address implies -fsanitize=init-order.
- // FIXME: This should be either specified in Sanitizers.def, or go away when
- // we get rid of "-fsanitize=init-order" flag at all.
- if (ParsedKind & Address)
- ParsedKind |= InitOrder;
- return ParsedKind;
- }
+ static unsigned parse(const char *Value);
/// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
/// invalid components.
static unsigned parse(const Driver &D, const llvm::opt::Arg *A,
- bool DiagnoseErrors) {
- unsigned Kind = 0;
- for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) {
- if (unsigned K = parse(A->getValue(I)))
- Kind |= K;
- else if (DiagnoseErrors)
- D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << A->getValue(I);
- }
- return Kind;
- }
+ bool DiagnoseErrors);
/// Parse a single flag of the form -f[no]sanitize=, or
/// -f*-sanitizer. Sets the masks defining required change of Kind value.
/// Returns true if the flag was parsed successfully.
static bool parse(const Driver &D, const llvm::opt::ArgList &Args,
const llvm::opt::Arg *A, unsigned &Add, unsigned &Remove,
- bool DiagnoseErrors) {
- Add = 0;
- Remove = 0;
- const char *DeprecatedReplacement = 0;
- if (A->getOption().matches(options::OPT_faddress_sanitizer)) {
- Add = Address;
- DeprecatedReplacement = "-fsanitize=address";
- } else if (A->getOption().matches(options::OPT_fno_address_sanitizer)) {
- Remove = Address;
- DeprecatedReplacement = "-fno-sanitize=address";
- } else if (A->getOption().matches(options::OPT_fthread_sanitizer)) {
- Add = Thread;
- DeprecatedReplacement = "-fsanitize=thread";
- } else if (A->getOption().matches(options::OPT_fno_thread_sanitizer)) {
- Remove = Thread;
- DeprecatedReplacement = "-fno-sanitize=thread";
- } else if (A->getOption().matches(options::OPT_fcatch_undefined_behavior)) {
- Add = UndefinedTrap;
- DeprecatedReplacement =
- "-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error";
- } else if (A->getOption().matches(options::OPT_fbounds_checking) ||
- A->getOption().matches(options::OPT_fbounds_checking_EQ)) {
- Add = Bounds;
- DeprecatedReplacement = "-fsanitize=bounds";
- } else if (A->getOption().matches(options::OPT_fsanitize_EQ)) {
- Add = parse(D, A, DiagnoseErrors);
- } else if (A->getOption().matches(options::OPT_fno_sanitize_EQ)) {
- Remove = parse(D, A, DiagnoseErrors);
- } else {
- // Flag is not relevant to sanitizers.
- return false;
- }
- // If this is a deprecated synonym, produce a warning directing users
- // towards the new spelling.
- if (DeprecatedReplacement && DiagnoseErrors)
- D.Diag(diag::warn_drv_deprecated_arg)
- << A->getAsString(Args) << DeprecatedReplacement;
- return true;
- }
+ bool DiagnoseErrors);
/// Produce an argument string from ArgList \p Args, which shows how it
/// provides a sanitizer kind in \p Mask. For example, the argument list
@@ -188,18 +99,7 @@ class SanitizerArgs {
/// would produce "-fsanitize=vptr".
static std::string lastArgumentForKind(const Driver &D,
const llvm::opt::ArgList &Args,
- unsigned Kind) {
- for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
- E = Args.rend();
- I != E; ++I) {
- unsigned Add, Remove;
- if (parse(D, Args, *I, Add, Remove, false) &&
- (Add & Kind))
- return describeSanitizeArg(Args, *I, Kind);
- Kind &= ~Remove;
- }
- llvm_unreachable("arg list didn't provide expected value");
- }
+ unsigned Kind);
/// Produce an argument string from argument \p A, which shows how it provides
/// a value in \p Mask. For instance, the argument
@@ -207,34 +107,10 @@ class SanitizerArgs {
/// "-fsanitize=alignment".
static std::string describeSanitizeArg(const llvm::opt::ArgList &Args,
const llvm::opt::Arg *A,
- unsigned Mask) {
- if (!A->getOption().matches(options::OPT_fsanitize_EQ))
- return A->getAsString(Args);
-
- for (unsigned I = 0, N = A->getNumValues(); I != N; ++I)
- if (parse(A->getValue(I)) & Mask)
- return std::string("-fsanitize=") + A->getValue(I);
-
- llvm_unreachable("arg didn't provide expected value");
- }
+ unsigned Mask);
static bool getDefaultBlacklistForKind(const Driver &D, unsigned Kind,
- std::string &BLPath) {
- const char *BlacklistFile = 0;
- if (Kind & NeedsAsanRt)
- BlacklistFile = "asan_blacklist.txt";
- else if (Kind & NeedsMsanRt)
- BlacklistFile = "msan_blacklist.txt";
- else if (Kind & NeedsTsanRt)
- BlacklistFile = "tsan_blacklist.txt";
- if (BlacklistFile) {
- SmallString<64> Path(D.ResourceDir);
- llvm::sys::path::append(Path, BlacklistFile);
- BLPath = Path.str();
- return true;
- }
- return false;
- }
+ std::string &BLPath);
};
} // namespace driver
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index ebfc3175f0..fb27bfde62 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -1616,130 +1616,6 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
}
}
-SanitizerArgs::SanitizerArgs(const ToolChain &TC, const ArgList &Args)
- : Kind(0), BlacklistFile(""), MsanTrackOrigins(false),
- AsanZeroBaseShadow(false) {
- unsigned AllKinds = 0; // All kinds of sanitizers that were turned on
- // at least once (possibly, disabled further).
- const Driver &D = TC.getDriver();
- for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) {
- unsigned Add, Remove;
- if (!parse(D, Args, *I, Add, Remove, true))
- continue;
- (*I)->claim();
- Kind |= Add;
- Kind &= ~Remove;
- AllKinds |= Add;
- }
-
- UbsanTrapOnError =
- Args.hasArg(options::OPT_fcatch_undefined_behavior) ||
- Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
- options::OPT_fno_sanitize_undefined_trap_on_error, false);
-
- if (Args.hasArg(options::OPT_fcatch_undefined_behavior) &&
- !Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
- options::OPT_fno_sanitize_undefined_trap_on_error, true)) {
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << "-fcatch-undefined-behavior"
- << "-fno-sanitize-undefined-trap-on-error";
- }
-
- // Warn about undefined sanitizer options that require runtime support.
- if (UbsanTrapOnError && notAllowedWithTrap()) {
- if (Args.hasArg(options::OPT_fcatch_undefined_behavior))
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, NotAllowedWithTrap)
- << "-fcatch-undefined-behavior";
- else if (Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
- options::OPT_fno_sanitize_undefined_trap_on_error,
- false))
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, NotAllowedWithTrap)
- << "-fsanitize-undefined-trap-on-error";
- }
-
- // Only one runtime library can be used at once.
- bool NeedsAsan = needsAsanRt();
- bool NeedsTsan = needsTsanRt();
- bool NeedsMsan = needsMsanRt();
- bool NeedsLsan = needsLeakDetection();
- if (NeedsAsan && NeedsTsan)
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, NeedsAsanRt)
- << lastArgumentForKind(D, Args, NeedsTsanRt);
- if (NeedsAsan && NeedsMsan)
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, NeedsAsanRt)
- << lastArgumentForKind(D, Args, NeedsMsanRt);
- if (NeedsTsan && NeedsMsan)
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, NeedsTsanRt)
- << lastArgumentForKind(D, Args, NeedsMsanRt);
- if (NeedsLsan && NeedsTsan)
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, NeedsLeakDetection)
- << lastArgumentForKind(D, Args, NeedsTsanRt);
- if (NeedsLsan && NeedsMsan)
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, NeedsLeakDetection)
- << lastArgumentForKind(D, Args, NeedsMsanRt);
- // FIXME: Currenly -fsanitize=leak is silently ignored in the presence of
- // -fsanitize=address. Perhaps it should print an error, or perhaps
- // -f(-no)sanitize=leak should change whether leak detection is enabled by
- // default in ASan?
-
- // If -fsanitize contains extra features of ASan, it should also
- // explicitly contain -fsanitize=address (probably, turned off later in the
- // command line).
- if ((Kind & AddressFull) != 0 && (AllKinds & Address) == 0)
- D.Diag(diag::warn_drv_unused_sanitizer)
- << lastArgumentForKind(D, Args, AddressFull)
- << "-fsanitize=address";
-
- // Parse -f(no-)sanitize-blacklist options.
- if (Arg *BLArg = Args.getLastArg(options::OPT_fsanitize_blacklist,
- options::OPT_fno_sanitize_blacklist)) {
- if (BLArg->getOption().matches(options::OPT_fsanitize_blacklist)) {
- std::string BLPath = BLArg->getValue();
- if (llvm::sys::fs::exists(BLPath))
- BlacklistFile = BLPath;
- else
- D.Diag(diag::err_drv_no_such_file) << BLPath;
- }
- } else {
- // If no -fsanitize-blacklist option is specified, try to look up for
- // blacklist in the resource directory.
- std::string BLPath;
- if (getDefaultBlacklistForKind(D, Kind, BLPath) &&
- llvm::sys::fs::exists(BLPath))
- BlacklistFile = BLPath;
- }
-
- // Parse -f(no-)sanitize-memory-track-origins options.
- if (NeedsMsan)
- MsanTrackOrigins =
- Args.hasFlag(options::OPT_fsanitize_memory_track_origins,
- options::OPT_fno_sanitize_memory_track_origins,
- /* Default */false);
-
- // Parse -f(no-)sanitize-address-zero-base-shadow options.
- if (NeedsAsan) {
- bool IsAndroid = (TC.getTriple().getEnvironment() == llvm::Triple::Android);
- bool ZeroBaseShadowDefault = IsAndroid;
- AsanZeroBaseShadow =
- Args.hasFlag(options::OPT_fsanitize_address_zero_base_shadow,
- options::OPT_fno_sanitize_address_zero_base_shadow,
- ZeroBaseShadowDefault);
- // Zero-base shadow is a requirement on Android.
- if (IsAndroid && !AsanZeroBaseShadow) {
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << "-fno-sanitize-address-zero-base-shadow"
- << lastArgumentForKind(D, Args, Address);
- }
- }
-}
-
static void addProfileRTLinux(
const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) {
if (!(Args.hasArg(options::OPT_fprofile_arcs) ||