/// this group enables.
SanitizerMask expandSanitizerGroups(SanitizerMask Kinds);
-/// Returns the mask of sanitizers which can be used without runtime library.
-SanitizerMask getSanitizersWithNoRequiredRuntime();
-
} // end namespace clang
#endif
#ifndef LLVM_CLANG_DRIVER_TOOLCHAIN_H
#define LLVM_CLANG_DRIVER_TOOLCHAIN_H
-#include "clang/Basic/Sanitizers.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Multilib.h"
#include "clang/Driver/Types.h"
virtual bool
AddFastMathRuntimeIfAvailable(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
-
- /// \brief Return sanitizers which are available in this toolchain.
- virtual SanitizerMask getSupportedSanitizers() const {
- return getSanitizersWithNoRequiredRuntime();
- }
};
} // end namespace driver
#include "clang/Basic/Sanitizers.def"
return Kinds;
}
-
-SanitizerMask clang::getSanitizersWithNoRequiredRuntime() {
- return SanitizerKind::UndefinedTrap | SanitizerKind::CFI |
- SanitizerKind::CFICastStrict | SanitizerKind::UnsignedIntegerOverflow |
- SanitizerKind::LocalBounds;
-}
}
return Triple.getTriple();
}
-
-SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
- SanitizerMask Res = ToolChain::getSupportedSanitizers();
- Res |= SanitizerKind::Address;
- // CFI checks are not implemented for MSVC ABI for now.
- Res &= ~SanitizerKind::CFI;
- Res &= ~SanitizerKind::CFICastStrict;
- return Res;
-}
/// Sanitizers set.
static std::string toString(const clang::SanitizerSet &Sanitizers);
+static SanitizerMask getToolchainUnsupportedKinds(const ToolChain &TC) {
+ bool IsFreeBSD = TC.getTriple().getOS() == llvm::Triple::FreeBSD;
+ bool IsLinux = TC.getTriple().getOS() == llvm::Triple::Linux;
+ bool IsX86 = TC.getTriple().getArch() == llvm::Triple::x86;
+ bool IsX86_64 = TC.getTriple().getArch() == llvm::Triple::x86_64;
+ bool IsMIPS64 = TC.getTriple().getArch() == llvm::Triple::mips64 ||
+ TC.getTriple().getArch() == llvm::Triple::mips64el;
+
+ SanitizerMask Unsupported = 0;
+ if (!(IsLinux && (IsX86_64 || IsMIPS64))) {
+ Unsupported |= Memory | DataFlow;
+ }
+ if (!((IsLinux || IsFreeBSD) && (IsX86_64 || IsMIPS64))) {
+ Unsupported |= Thread;
+ }
+ if (!(IsLinux && (IsX86 || IsX86_64))) {
+ Unsupported |= Function;
+ }
+ return Unsupported;
+}
+
static bool getDefaultBlacklist(const Driver &D, SanitizerMask Kinds,
std::string &BLPath) {
const char *BlacklistFile = nullptr;
return false;
}
-/// Sets group bits for every group that has at least one representative already
-/// enabled in \p Kinds.
-static SanitizerMask setGroupBits(SanitizerMask Kinds) {
-#define SANITIZER(NAME, ID)
-#define SANITIZER_GROUP(NAME, ID, ALIAS) \
- if (Kinds & SanitizerKind::ID) \
- Kinds |= SanitizerKind::ID##Group;
-#include "clang/Basic/Sanitizers.def"
- return Kinds;
-}
-
bool SanitizerArgs::needsUbsanRt() const {
return !UbsanTrapOnError && (Sanitizers.Mask & NeedsUbsanRt) &&
!Sanitizers.has(Address) &&
SanitizerMask DiagnosedKinds = 0; // All Kinds we have diagnosed up to now.
// Used to deduplicate diagnostics.
SanitizerMask Kinds = 0;
- SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers());
+ SanitizerMask NotSupported = getToolchainUnsupportedKinds(TC);
ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
const Driver &D = TC.getDriver();
// sanitizers in Add are those which have been explicitly enabled.
// Diagnose them.
if (SanitizerMask KindsToDiagnose =
- Add & ~Supported & ~DiagnosedKinds) {
+ Add & NotSupported & ~DiagnosedKinds) {
// Only diagnose the new kinds.
std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< Desc << TC.getTriple().str();
DiagnosedKinds |= KindsToDiagnose;
}
- Add &= Supported;
+ Add &= ~NotSupported;
// Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
// so we don't error out if -fno-rtti and -fsanitize=undefined were
Add &= ~AllRemove;
// Silently discard any unsupported sanitizers implicitly enabled through
// group expansion.
- Add &= Supported;
+ Add &= ~NotSupported;
Kinds |= Add;
} else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
const SanitizerArgs &Sanitize = getSanitizerArgs();
- if (Sanitize.needsAsanRt())
- AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");
- if (Sanitize.needsUbsanRt())
- AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan");
+
+ if (Sanitize.needsAsanRt()) {
+ if (!isTargetMacOS() && !isTargetIOSSimulator()) {
+ // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds.
+ getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
+ << "-fsanitize=address";
+ } else {
+ AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");
+ }
+ }
+
+ if (Sanitize.needsUbsanRt()) {
+ if (!isTargetMacOS() && !isTargetIOSSimulator()) {
+ // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds.
+ getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
+ << "-fsanitize=undefined";
+ } else {
+ AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan");
+ }
+ }
// Otherwise link libSystem, then the dynamic runtime library, and finally any
// target specific static runtime library.
getDriver().Diag(diag::err_arc_unsupported_on_toolchain);
}
-SanitizerMask Darwin::getSupportedSanitizers() const {
- SanitizerMask Res = ToolChain::getSupportedSanitizers();
- if (isTargetMacOS() || isTargetIOSSimulator()) {
- // ASan and UBSan are available on Mac OS and on iOS simulator.
- Res |= SanitizerKind::Address;
- Res |= SanitizerKind::Vptr;
- }
- if (isTargetMacOS())
- Res |= SanitizerKind::SafeStack;
- return Res;
-}
-
/// Generic_GCC - A tool chain using the 'gcc' command to perform
/// all subcommands; this relies on gcc translating the majority of
/// command line options.
return getSanitizerArgs().requiresPIE();
}
-SanitizerMask FreeBSD::getSupportedSanitizers() const {
- const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
- const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
- const bool IsMIPS64 = getTriple().getArch() == llvm::Triple::mips64 ||
- getTriple().getArch() == llvm::Triple::mips64el;
- SanitizerMask Res = ToolChain::getSupportedSanitizers();
- Res |= SanitizerKind::Address;
- Res |= SanitizerKind::Vptr;
- if (IsX86_64 || IsMIPS64) {
- Res |= SanitizerKind::Leak;
- Res |= SanitizerKind::Thread;
- }
- if (IsX86 || IsX86_64) {
- Res |= SanitizerKind::SafeStack;
- }
- return Res;
-}
-
/// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly.
NetBSD::NetBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
return getSanitizerArgs().requiresPIE();
}
-SanitizerMask Linux::getSupportedSanitizers() const {
- const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
- const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
- const bool IsMIPS64 = getTriple().getArch() == llvm::Triple::mips64 ||
- getTriple().getArch() == llvm::Triple::mips64el;
- SanitizerMask Res = ToolChain::getSupportedSanitizers();
- Res |= SanitizerKind::Address;
- Res |= SanitizerKind::Vptr;
- if (IsX86_64 || IsMIPS64) {
- Res |= SanitizerKind::DataFlow;
- Res |= SanitizerKind::Leak;
- Res |= SanitizerKind::Memory;
- Res |= SanitizerKind::Thread;
- }
- if (IsX86 || IsX86_64) {
- Res |= SanitizerKind::Function;
- Res |= SanitizerKind::SafeStack;
- }
- return Res;
-}
-
/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
DragonFly::DragonFly(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
void CheckObjCARC() const override;
bool UseSjLjExceptions() const override;
-
- SanitizerMask getSupportedSanitizers() const override;
};
/// DarwinClang - The Darwin toolchain used by Clang.
bool UseSjLjExceptions() const override;
bool isPIEDefault() const override;
- SanitizerMask getSupportedSanitizers() const override;
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
bool isPIEDefault() const override;
- SanitizerMask getSupportedSanitizers() const override;
std::string Linker;
std::vector<std::string> ExtraOpts;
std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
types::ID InputType) const override;
- SanitizerMask getSupportedSanitizers() const override;
protected:
void AddSystemIncludeWithSubfolder(const llvm::opt::ArgList &DriverArgs,
-// RUN: %clang -target i386-unknown-linux -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s
-// RUN: %clang -O1 -target i386-unknown-linux -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s
-// RUN: %clang -O2 -target i386-unknown-linux -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s
-// RUN: %clang -O3 -target i386-unknown-linux -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang -target i386-unknown-unknown -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang -O1 -target i386-unknown-unknown -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang -O2 -target i386-unknown-unknown -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang -O3 -target i386-unknown-unknown -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s
// Verify that -fsanitize=address invokes asan instrumentation.
int foo(int *a) { return *a; }
-// RUN: %clang -target x86_64-pc-openbsd -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP
-// RUN: %clang -target x86_64-pc-openbsd -fsanitize-undefined-trap-on-error -fsanitize=undefined-trap %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP
+// RUN: %clang -target x86_64-linux-gnu -fsanitize-undefined-trap-on-error -fsanitize=undefined-trap %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP
// CHECK-UNDEFINED-TRAP: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){17}"}}
// CHECK-UNDEFINED-TRAP: "-fsanitize-undefined-trap-on-error"
// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=function -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FSAN-UBSAN-DARWIN
// CHECK-FSAN-UBSAN-DARWIN: unsupported option '-fsanitize=function' for target 'x86_64-apple-darwin10'
-// RUN: %clang -target armv7-apple-ios7 -miphoneos-version-min=7.0 -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-IOS
-// CHECK-ASAN-IOS: unsupported option '-fsanitize=address' for target 'arm-apple-ios7'
-
-// RUN: %clang -target i386-pc-openbsd -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-OPENBSD
-// CHECK-ASAN-OPENBSD: unsupported option '-fsanitize=address' for target 'i386-pc-openbsd'
-
// RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI
// RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi-derived-cast -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-DCAST
// RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi-unrelated-cast -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-UCAST
// Make sure we only error/warn once, when trying to enable vptr and
// undefined and have -fno-rtti
// RUN: %clang -### -c -fsanitize=undefined -fsanitize=vptr -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-ERROR -check-prefix=CHECK-OK %s
-// RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=vptr %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
-// RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=vptr -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
-// RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=vptr -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-ERROR %s
-// RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=undefined %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
-// RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=undefined -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
+
+// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=vptr %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-WARN %s
+// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=vptr -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
+// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=vptr -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-ERROR %s
+// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=undefined -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
+// RUN: %clang -### -c -target x86_64-unknown-unknown -fsanitize=vptr %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
+// RUN: %clang -### -c -target x86_64-unknown-unknown -fsanitize=vptr -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
+// RUN: %clang -### -c -target x86_64-unknown-unknown -fsanitize=vptr -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-ERROR %s
+// RUN: %clang -### -c -target x86_64-unknown-unknown -fsanitize=undefined %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
+// RUN: %clang -### -c -target x86_64-unknown-unknown -fsanitize=undefined -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
// Exceptions + no/default rtti
// RUN: %clang -### -c -target x86_64-scei-ps4 -fcxx-exceptions -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-EXC-ERROR-CXX %s
// RUN: %clang -### -c -target x86_64-unknown-unknown %s 2>&1 | FileCheck -check-prefix=CHECK-RTTI %s
// CHECK-UNUSED: warning: argument unused during compilation: '-fcxx-exceptions'
+// CHECK-SAN-WARN: implicitly disabling vptr sanitizer because rtti wasn't enabled
// CHECK-SAN-ERROR: invalid argument '-fsanitize=vptr' not allowed with '-fno-rtti'
// CHECK-EXC-WARN: implicitly enabling rtti for exception handling
// CHECK-EXC-ERROR: invalid argument '-fno-rtti' not allowed with '-fexceptions'