forked from OSchip/llvm-project
Introduce -fsanitize-trap= flag.
This flag controls whether a given sanitizer traps upon detecting an error. It currently only supports UBSan. The existing flag -fsanitize-undefined-trap-on-error has been made an alias of -fsanitize-trap=undefined. This change also cleans up some awkward behavior around the combination of -fsanitize-trap=undefined and -fsanitize=undefined. Previously we would reject command lines containing the combination of these two flags, as -fsanitize=vptr is not compatible with trapping. This required the creation of -fsanitize=undefined-trap, which excluded -fsanitize=vptr (and -fsanitize=function, but this seems like an oversight). Now, -fsanitize=undefined is an alias for -fsanitize=undefined-trap, and if -fsanitize-trap=undefined is specified, we treat -fsanitize=vptr as an "unsupported" flag, which means that we error out if the flag is specified explicitly, but implicitly disable it if the flag was implied by -fsanitize=undefined. Differential Revision: http://reviews.llvm.org/D10464 llvm-svn: 240105
This commit is contained in:
parent
c847e7e543
commit
9881b78b53
|
@ -970,12 +970,9 @@ are listed below.
|
|||
includes all of the checks listed below other than
|
||||
``unsigned-integer-overflow``.
|
||||
|
||||
- ``-fsanitize=undefined-trap``: This includes all sanitizers
|
||||
included by ``-fsanitize=undefined``, except those that require
|
||||
runtime support. This group of sanitizers is intended to be
|
||||
used in conjunction with the ``-fsanitize-undefined-trap-on-error``
|
||||
flag. This includes all of the checks listed below other than
|
||||
``unsigned-integer-overflow`` and ``vptr``.
|
||||
- ``-fsanitize=undefined-trap``: This is a deprecated alias for
|
||||
``-fsanitize=undefined``.
|
||||
|
||||
- ``-fsanitize=dataflow``: :doc:`DataFlowSanitizer`, a general data
|
||||
flow analysis.
|
||||
- ``-fsanitize=cfi``: :doc:`control flow integrity <ControlFlowIntegrity>`
|
||||
|
@ -1069,15 +1066,6 @@ are listed below.
|
|||
through. This mode may use extra memory in programs that copy
|
||||
uninitialized memory a lot.
|
||||
|
||||
Extra features of UndefinedBehaviorSanitizer:
|
||||
|
||||
- ``-fsanitize-undefined-trap-on-error``: Causes traps to be emitted
|
||||
rather than calls to runtime libraries when a problem is detected.
|
||||
This option is intended for use in cases where the sanitizer runtime
|
||||
cannot be used (for instance, when building libc or a kernel module).
|
||||
This is only compatible with the sanitizers in the ``undefined-trap``
|
||||
group.
|
||||
|
||||
The ``-fsanitize=`` argument must also be provided when linking, in
|
||||
order to link to the appropriate runtime library. When using
|
||||
``-fsanitize=vptr`` (or a group that includes it, such as
|
||||
|
@ -1101,11 +1089,39 @@ are listed below.
|
|||
sanitizers (e.g. :doc:`AddressSanitizer`) may not support recovery,
|
||||
and always crash the program after the issue is detected.
|
||||
|
||||
Note that the ``-fsanitize-trap`` flag has precedence over this flag.
|
||||
This means that if a check has been configured to trap elsewhere on the
|
||||
command line, or if the check traps by default, this flag will not have
|
||||
any effect unless that sanitizer's trapping behavior is disabled with
|
||||
``-fno-sanitize-trap``.
|
||||
|
||||
For example, if a command line contains the flags ``-fsanitize=undefined
|
||||
-fsanitize-trap=undefined``, the flag ``-fsanitize-recover=alignment``
|
||||
will have no effect on its own; it will need to be accompanied by
|
||||
``-fno-sanitize-trap=alignment``.
|
||||
|
||||
**-f[no-]sanitize-trap=check1,check2,...**
|
||||
|
||||
Controls which checks enabled by the ``-fsanitize=`` flag trap. This
|
||||
option is intended for use in cases where the sanitizer runtime cannot
|
||||
be used (for instance, when building libc or a kernel module), or where
|
||||
the binary size increase caused by the sanitizer runtime is a concern.
|
||||
|
||||
This flag is only compatible with ``local-bounds``,
|
||||
``unsigned-integer-overflow`` and sanitizers in the ``undefined``
|
||||
group other than ``vptr``. If this flag is supplied together with
|
||||
``-fsanitize=undefined``, the ``vptr`` sanitizer will be implicitly
|
||||
disabled.
|
||||
|
||||
**-f[no-]sanitize-coverage=[type,features,...]**
|
||||
|
||||
Enable simple code coverage in addition to certain sanitizers.
|
||||
See :doc:`SanitizerCoverage` for more details.
|
||||
|
||||
.. option:: -fsanitize-undefined-trap-on-error
|
||||
|
||||
Deprecated alias for ``-fsanitize-trap=undefined``.
|
||||
|
||||
.. option:: -fno-assume-sane-operator-new
|
||||
|
||||
Don't assume that the C++'s new operator is sane.
|
||||
|
|
|
@ -90,18 +90,17 @@ SANITIZER_GROUP("cfi", CFI,
|
|||
// Safe Stack
|
||||
SANITIZER("safe-stack", SafeStack)
|
||||
|
||||
// -fsanitize=undefined-trap includes sanitizers from -fsanitize=undefined
|
||||
// that can be used without runtime support, generally by providing extra
|
||||
// -fsanitize-undefined-trap-on-error flag.
|
||||
SANITIZER_GROUP("undefined-trap", UndefinedTrap,
|
||||
// -fsanitize=undefined includes all the sanitizers which have low overhead, no
|
||||
// ABI or address space layout implications, and only catch undefined behavior.
|
||||
SANITIZER_GROUP("undefined", Undefined,
|
||||
Alignment | Bool | ArrayBounds | Enum | FloatCastOverflow |
|
||||
FloatDivideByZero | IntegerDivideByZero | NonnullAttribute |
|
||||
Null | ObjectSize | Return | ReturnsNonnullAttribute |
|
||||
Shift | SignedIntegerOverflow | Unreachable | VLABound)
|
||||
Shift | SignedIntegerOverflow | Unreachable | VLABound |
|
||||
Function | Vptr)
|
||||
|
||||
// -fsanitize=undefined includes all the sanitizers which have low overhead, no
|
||||
// ABI or address space layout implications, and only catch undefined behavior.
|
||||
SANITIZER_GROUP("undefined", Undefined, UndefinedTrap | Function | Vptr)
|
||||
// -fsanitize=undefined-trap is an alias for -fsanitize=undefined.
|
||||
SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined)
|
||||
|
||||
SANITIZER_GROUP("integer", Integer,
|
||||
SignedIntegerOverflow | UnsignedIntegerOverflow | Shift |
|
||||
|
|
|
@ -561,8 +561,13 @@ def fno_sanitize_recover_EQ
|
|||
: CommaJoined<["-"], "fno-sanitize-recover=">,
|
||||
Group<f_clang_Group>,
|
||||
HelpText<"Disable recovery for specified sanitizers">;
|
||||
def fsanitize_trap_EQ : CommaJoined<["-"], "fsanitize-trap=">, Group<f_clang_Group>,
|
||||
Flags<[CC1Option, CoreOption]>,
|
||||
HelpText<"Enable trapping for specified sanitizers">;
|
||||
def fno_sanitize_trap_EQ : CommaJoined<["-"], "fno-sanitize-trap=">, Group<f_clang_Group>,
|
||||
HelpText<"Disable trapping for specified sanitizers">;
|
||||
def fsanitize_undefined_trap_on_error : Flag<["-"], "fsanitize-undefined-trap-on-error">,
|
||||
Group<f_clang_Group>, Flags<[CC1Option]>;
|
||||
Group<f_clang_Group>;
|
||||
def fno_sanitize_undefined_trap_on_error : Flag<["-"], "fno-sanitize-undefined-trap-on-error">,
|
||||
Group<f_clang_Group>;
|
||||
def fsanitize_link_cxx_runtime : Flag<["-"], "fsanitize-link-c++-runtime">,
|
||||
|
|
|
@ -23,13 +23,13 @@ class ToolChain;
|
|||
class SanitizerArgs {
|
||||
SanitizerSet Sanitizers;
|
||||
SanitizerSet RecoverableSanitizers;
|
||||
SanitizerSet TrapSanitizers;
|
||||
|
||||
std::vector<std::string> BlacklistFiles;
|
||||
int CoverageFeatures;
|
||||
int MsanTrackOrigins;
|
||||
int AsanFieldPadding;
|
||||
bool AsanZeroBaseShadow;
|
||||
bool UbsanTrapOnError;
|
||||
bool AsanSharedRuntime;
|
||||
bool LinkCXXRuntimes;
|
||||
|
||||
|
|
|
@ -120,8 +120,6 @@ CODEGENOPT(SanitizeCoverageTraceCmp, 1, 0) ///< Enable cmp instruction tracing
|
|||
///< in sanitizer coverage.
|
||||
CODEGENOPT(SanitizeCoverage8bitCounters, 1, 0) ///< Use 8-bit frequency counters
|
||||
///< in sanitizer coverage.
|
||||
CODEGENOPT(SanitizeUndefinedTrapOnError, 1, 0) ///< Set on
|
||||
/// -fsanitize-undefined-trap-on-error
|
||||
CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled.
|
||||
CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float.
|
||||
CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition.
|
||||
|
|
|
@ -197,6 +197,9 @@ public:
|
|||
/// continued when possible).
|
||||
SanitizerSet SanitizeRecover;
|
||||
|
||||
/// Set of sanitizer checks that trap rather than diagnose.
|
||||
SanitizerSet SanitizeTrap;
|
||||
|
||||
public:
|
||||
// Define accessors/mutators for code generation options of enumeration type.
|
||||
#define CODEGENOPT(Name, Bits, Default)
|
||||
|
|
|
@ -2300,15 +2300,24 @@ void CodeGenFunction::EmitCheck(
|
|||
|
||||
llvm::Value *FatalCond = nullptr;
|
||||
llvm::Value *RecoverableCond = nullptr;
|
||||
llvm::Value *TrapCond = nullptr;
|
||||
for (int i = 0, n = Checked.size(); i < n; ++i) {
|
||||
llvm::Value *Check = Checked[i].first;
|
||||
// -fsanitize-trap= overrides -fsanitize-recover=.
|
||||
llvm::Value *&Cond =
|
||||
CGM.getCodeGenOpts().SanitizeRecover.has(Checked[i].second)
|
||||
? RecoverableCond
|
||||
: FatalCond;
|
||||
CGM.getCodeGenOpts().SanitizeTrap.has(Checked[i].second)
|
||||
? TrapCond
|
||||
: CGM.getCodeGenOpts().SanitizeRecover.has(Checked[i].second)
|
||||
? RecoverableCond
|
||||
: FatalCond;
|
||||
Cond = Cond ? Builder.CreateAnd(Cond, Check) : Check;
|
||||
}
|
||||
|
||||
if (TrapCond)
|
||||
EmitTrapCheck(TrapCond);
|
||||
if (!FatalCond && !RecoverableCond)
|
||||
return;
|
||||
|
||||
llvm::Value *JointCond;
|
||||
if (FatalCond && RecoverableCond)
|
||||
JointCond = Builder.CreateAnd(FatalCond, RecoverableCond);
|
||||
|
@ -2326,15 +2335,6 @@ void CodeGenFunction::EmitCheck(
|
|||
}
|
||||
#endif
|
||||
|
||||
if (CGM.getCodeGenOpts().SanitizeUndefinedTrapOnError) {
|
||||
assert(RecoverKind != CheckRecoverableKind::AlwaysRecoverable &&
|
||||
"Runtime call required for AlwaysRecoverable kind!");
|
||||
// Assume that -fsanitize-undefined-trap-on-error overrides
|
||||
// -fsanitize-recover= options, as we can only print meaningful error
|
||||
// message and recover if we have a runtime support.
|
||||
return EmitTrapCheck(JointCond);
|
||||
}
|
||||
|
||||
llvm::BasicBlock *Cont = createBasicBlock("cont");
|
||||
llvm::BasicBlock *Handlers = createBasicBlock("handler." + CheckName);
|
||||
llvm::Instruction *Branch = Builder.CreateCondBr(JointCond, Cont, Handlers);
|
||||
|
|
|
@ -34,6 +34,8 @@ enum : SanitizerMask {
|
|||
Unrecoverable = Address | Unreachable | Return,
|
||||
LegacyFsanitizeRecoverMask = Undefined | Integer,
|
||||
NeedsLTO = CFI,
|
||||
TrappingSupported =
|
||||
(Undefined & ~Vptr) | UnsignedIntegerOverflow | LocalBounds,
|
||||
};
|
||||
|
||||
enum CoverageFeature {
|
||||
|
@ -116,8 +118,59 @@ static bool getDefaultBlacklist(const Driver &D, SanitizerMask Kinds,
|
|||
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;
|
||||
}
|
||||
|
||||
static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
|
||||
const llvm::opt::ArgList &Args) {
|
||||
SanitizerMask TrapRemove = 0; // During the loop below, the accumulated set of
|
||||
// sanitizers disabled by the current sanitizer
|
||||
// argument or any argument after it.
|
||||
SanitizerMask TrappingKinds = 0;
|
||||
SanitizerMask TrappingSupportedWithGroups = setGroupBits(TrappingSupported);
|
||||
|
||||
for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
|
||||
I != E; ++I) {
|
||||
const auto *Arg = *I;
|
||||
if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) {
|
||||
Arg->claim();
|
||||
SanitizerMask Add = parseArgValues(D, Arg, true);
|
||||
Add &= ~TrapRemove;
|
||||
if (SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups) {
|
||||
SanitizerSet S;
|
||||
S.Mask = InvalidValues;
|
||||
D.Diag(diag::err_drv_unsupported_option_argument) << "-fsanitize-trap"
|
||||
<< toString(S);
|
||||
}
|
||||
TrappingKinds |= expandSanitizerGroups(Add) & ~TrapRemove;
|
||||
} else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
|
||||
Arg->claim();
|
||||
TrapRemove |= expandSanitizerGroups(parseArgValues(D, Arg, true));
|
||||
} else if (Arg->getOption().matches(
|
||||
options::OPT_fsanitize_undefined_trap_on_error)) {
|
||||
Arg->claim();
|
||||
TrappingKinds |=
|
||||
expandSanitizerGroups(UndefinedGroup & ~TrapRemove) & ~TrapRemove;
|
||||
} else if (Arg->getOption().matches(
|
||||
options::OPT_fno_sanitize_undefined_trap_on_error)) {
|
||||
Arg->claim();
|
||||
TrapRemove |= expandSanitizerGroups(UndefinedGroup);
|
||||
}
|
||||
}
|
||||
|
||||
return TrappingKinds;
|
||||
}
|
||||
|
||||
bool SanitizerArgs::needsUbsanRt() const {
|
||||
return !UbsanTrapOnError && (Sanitizers.Mask & NeedsUbsanRt) &&
|
||||
return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) &&
|
||||
!Sanitizers.has(Address) &&
|
||||
!Sanitizers.has(Memory) &&
|
||||
!Sanitizers.has(Thread);
|
||||
|
@ -138,12 +191,12 @@ bool SanitizerArgs::needsLTO() const {
|
|||
void SanitizerArgs::clear() {
|
||||
Sanitizers.clear();
|
||||
RecoverableSanitizers.clear();
|
||||
TrapSanitizers.clear();
|
||||
BlacklistFiles.clear();
|
||||
CoverageFeatures = 0;
|
||||
MsanTrackOrigins = 0;
|
||||
AsanFieldPadding = 0;
|
||||
AsanZeroBaseShadow = false;
|
||||
UbsanTrapOnError = false;
|
||||
AsanSharedRuntime = false;
|
||||
LinkCXXRuntimes = false;
|
||||
}
|
||||
|
@ -166,6 +219,9 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
|
|||
ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
|
||||
|
||||
const Driver &D = TC.getDriver();
|
||||
SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args);
|
||||
NotSupported |= TrappingKinds & NotAllowedWithTrap;
|
||||
|
||||
for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
|
||||
I != E; ++I) {
|
||||
const auto *Arg = *I;
|
||||
|
@ -180,7 +236,14 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
|
|||
// sanitizers in Add are those which have been explicitly enabled.
|
||||
// Diagnose them.
|
||||
if (SanitizerMask KindsToDiagnose =
|
||||
Add & NotSupported & ~DiagnosedKinds) {
|
||||
Add & TrappingKinds & NotAllowedWithTrap & ~DiagnosedKinds) {
|
||||
std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
|
||||
D.Diag(diag::err_drv_argument_not_allowed_with)
|
||||
<< Desc << "-fsanitize-trap=undefined";
|
||||
DiagnosedKinds |= KindsToDiagnose;
|
||||
Add &= ~KindsToDiagnose;
|
||||
}
|
||||
if (SanitizerMask KindsToDiagnose = Add & NotSupported & ~DiagnosedKinds) {
|
||||
// Only diagnose the new kinds.
|
||||
std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
|
||||
D.Diag(diag::err_drv_unsupported_opt_for_target)
|
||||
|
@ -234,17 +297,6 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
|
|||
Kinds &= ~Vptr;
|
||||
}
|
||||
|
||||
// Warn about undefined sanitizer options that require runtime support.
|
||||
UbsanTrapOnError =
|
||||
Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
|
||||
options::OPT_fno_sanitize_undefined_trap_on_error, false);
|
||||
if (UbsanTrapOnError && (Kinds & NotAllowedWithTrap)) {
|
||||
D.Diag(clang::diag::err_drv_argument_not_allowed_with)
|
||||
<< lastArgumentForMask(D, Args, NotAllowedWithTrap)
|
||||
<< "-fsanitize-undefined-trap-on-error";
|
||||
Kinds &= ~NotAllowedWithTrap;
|
||||
}
|
||||
|
||||
// Warn about incompatible groups of sanitizers.
|
||||
std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
|
||||
std::make_pair(Address, Thread), std::make_pair(Address, Memory),
|
||||
|
@ -305,6 +357,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
|
|||
RecoverableKinds &= Kinds;
|
||||
RecoverableKinds &= ~Unrecoverable;
|
||||
|
||||
TrappingKinds &= Kinds;
|
||||
|
||||
// Setup blacklist files.
|
||||
// Add default blacklist from resource directory.
|
||||
{
|
||||
|
@ -460,6 +514,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
|
|||
// Finally, initialize the set of available and recoverable sanitizers.
|
||||
Sanitizers.Mask |= Kinds;
|
||||
RecoverableSanitizers.Mask |= RecoverableKinds;
|
||||
TrapSanitizers.Mask |= TrappingKinds;
|
||||
}
|
||||
|
||||
static std::string toString(const clang::SanitizerSet &Sanitizers) {
|
||||
|
@ -484,8 +539,9 @@ void SanitizerArgs::addArgs(const llvm::opt::ArgList &Args,
|
|||
CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
|
||||
toString(RecoverableSanitizers)));
|
||||
|
||||
if (UbsanTrapOnError)
|
||||
CmdArgs.push_back("-fsanitize-undefined-trap-on-error");
|
||||
if (!TrapSanitizers.empty())
|
||||
CmdArgs.push_back(
|
||||
Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
|
||||
|
||||
for (const auto &BLPath : BlacklistFiles) {
|
||||
SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
|
||||
|
@ -528,7 +584,9 @@ SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
|
|||
assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
|
||||
A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
|
||||
A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
|
||||
A->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) &&
|
||||
A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
|
||||
A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
|
||||
A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
|
||||
"Invalid argument in parseArgValues!");
|
||||
SanitizerMask Kinds = 0;
|
||||
for (int i = 0, n = A->getNumValues(); i != n; ++i) {
|
||||
|
|
|
@ -555,8 +555,6 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
|
|||
Args.hasArg(OPT_fsanitize_coverage_8bit_counters);
|
||||
Opts.SanitizeMemoryTrackOrigins =
|
||||
getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags);
|
||||
Opts.SanitizeUndefinedTrapOnError =
|
||||
Args.hasArg(OPT_fsanitize_undefined_trap_on_error);
|
||||
Opts.SSPBufferSize =
|
||||
getLastArgIntValue(Args, OPT_stack_protector_buffer_size, 8, Diags);
|
||||
Opts.StackRealignment = Args.hasArg(OPT_mstackrealign);
|
||||
|
@ -666,6 +664,9 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
|
|||
parseSanitizerKinds("-fsanitize-recover=",
|
||||
Args.getAllArgValues(OPT_fsanitize_recover_EQ), Diags,
|
||||
Opts.SanitizeRecover);
|
||||
parseSanitizerKinds("-fsanitize-trap=",
|
||||
Args.getAllArgValues(OPT_fsanitize_trap_EQ), Diags,
|
||||
Opts.SanitizeTrap);
|
||||
|
||||
Opts.CudaGpuBinaryFileNames =
|
||||
Args.getAllArgValues(OPT_fcuda_include_gpubinary);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// RUN: %clang_cc1 -fsanitize=local-bounds -emit-llvm -triple x86_64-apple-darwin10 %s -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -fsanitize=array-bounds -O -fsanitize-undefined-trap-on-error -emit-llvm -triple x86_64-apple-darwin10 -DNO_DYNAMIC %s -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -fsanitize=array-bounds -O -fsanitize-trap=array-bounds -emit-llvm -triple x86_64-apple-darwin10 -DNO_DYNAMIC %s -o - | FileCheck %s
|
||||
|
||||
// CHECK-LABEL: @f
|
||||
double f(int b, int i) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// RUN: %clang_cc1 -fsanitize=alignment,null,object-size,shift-base,shift-exponent,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -fsanitize-recover=alignment,null,object-size,shift-base,shift-exponent,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-UBSAN
|
||||
// RUN: %clang_cc1 -fsanitize-undefined-trap-on-error -fsanitize=alignment,null,object-size,shift-base,shift-exponent,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -fsanitize-recover=alignment,null,object-size,shift-base,shift-exponent,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-TRAP
|
||||
// RUN: %clang_cc1 -fsanitize-trap=alignment,null,object-size,shift-base,shift-exponent,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -fsanitize-recover=alignment,null,object-size,shift-base,shift-exponent,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -fsanitize=alignment,null,object-size,shift-base,shift-exponent,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -fsanitize-recover=alignment,null,object-size,shift-base,shift-exponent,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-TRAP
|
||||
// RUN: %clang_cc1 -fsanitize=null -fsanitize-recover=null -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-NULL
|
||||
// RUN: %clang_cc1 -fsanitize=signed-integer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-OVERFLOW
|
||||
// REQUIRES: asserts
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
// RUN: %clang_cc1 -emit-llvm -o - %s -fsanitize=signed-integer-overflow,integer-divide-by-zero -fsanitize-trap=integer-divide-by-zero | FileCheck %s
|
||||
|
||||
int f(int x, int y) {
|
||||
// CHECK: %[[B1:.*]] = icmp ne i32 %[[D:.*]], 0
|
||||
// CHECK: %[[B2:.*]] = icmp ne i32 %[[N:.*]], -2147483648
|
||||
// CHECK: %[[B3:.*]] = icmp ne i32 %[[D]], -1
|
||||
// CHECK: %[[B4:.*]] = or i1 %[[B2]], %[[B3]]
|
||||
// CHECK: br i1 %[[B1]], label %[[L1:[0-9a-z_.]*]], label %[[L2:[0-9a-z_.]*]]
|
||||
|
||||
// CHECK: [[L2]]
|
||||
// CHECK-NEXT: call void @llvm.trap()
|
||||
// CHECK-NEXT: unreachable
|
||||
|
||||
// CHECK: [[L1]]
|
||||
// CHECK-NEXT: br i1 %[[B4]], label %[[L3:[0-9a-z_.]*]], label %[[L4:[0-9a-z_.]*]]
|
||||
|
||||
// CHECK: [[L4]]
|
||||
// CHECK-NEXT: zext
|
||||
// CHECK-NEXT: zext
|
||||
// CHECK-NEXT: __ubsan_handle_divrem_overflow
|
||||
|
||||
// CHECK: [[L3]]
|
||||
// CHECK-NEXT: sdiv i32 %[[N]], %[[D]]
|
||||
return x / y;
|
||||
}
|
|
@ -1,7 +1,11 @@
|
|||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fno-sanitize-trap=signed-integer-overflow %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP2
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -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 -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"
|
||||
// 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|function),?){18}"}}
|
||||
// CHECK-UNDEFINED-TRAP: "-fsanitize-trap=alignment,array-bounds,bool,enum,float-cast-overflow,float-divide-by-zero,function,integer-divide-by-zero,nonnull-attribute,null,object-size,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound"
|
||||
// CHECK-UNDEFINED-TRAP2: "-fsanitize-trap=alignment,array-bounds,bool,enum,float-cast-overflow,float-divide-by-zero,function,integer-divide-by-zero,nonnull-attribute,null,object-size,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound"
|
||||
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED
|
||||
// CHECK-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|vptr|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){19}"}}
|
||||
|
@ -27,11 +31,9 @@
|
|||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=shift -fno-sanitize=shift-base %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FSANITIZE-SHIFT-PARTIAL
|
||||
// CHECK-FSANITIZE-SHIFT-PARTIAL: "-fsanitize=shift-exponent"
|
||||
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize-undefined-trap-on-error %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP-ON-ERROR-UNDEF
|
||||
// CHECK-UNDEFINED-TRAP-ON-ERROR-UNDEF: '-fsanitize=undefined' not allowed with '-fsanitize-undefined-trap-on-error'
|
||||
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=vptr -fsanitize-undefined-trap-on-error %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP-ON-ERROR-VPTR
|
||||
// CHECK-UNDEFINED-TRAP-ON-ERROR-VPTR: '-fsanitize=vptr' not allowed with '-fsanitize-undefined-trap-on-error'
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=vptr -fsanitize-trap=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-TRAP-UNDEF
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=vptr -fsanitize-undefined-trap-on-error %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-TRAP-UNDEF
|
||||
// CHECK-VPTR-TRAP-UNDEF: error: invalid argument '-fsanitize=vptr' not allowed with '-fsanitize-trap=undefined'
|
||||
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=vptr -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-NO-RTTI
|
||||
// CHECK-VPTR-NO-RTTI: '-fsanitize=vptr' not allowed with '-fno-rtti'
|
||||
|
@ -199,6 +201,9 @@
|
|||
// CHECK-CFI-NVCALL: -emit-llvm-bc{{.*}}-fsanitize=cfi-nvcall
|
||||
// CHECK-CFI-VCALL: -emit-llvm-bc{{.*}}-fsanitize=cfi-vcall
|
||||
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize-trap=address -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-TRAP
|
||||
// CHECK-ASAN-TRAP: error: unsupported argument 'address' to option '-fsanitize-trap'
|
||||
|
||||
// RUN: %clang_cl -fsanitize=address -c -MDd -### -- %s 2>&1 | FileCheck %s -check-prefix=CHECK-ASAN-DEBUGRTL
|
||||
// RUN: %clang_cl -fsanitize=address -c -MTd -### -- %s 2>&1 | FileCheck %s -check-prefix=CHECK-ASAN-DEBUGRTL
|
||||
// RUN: %clang_cl -fsanitize=address -c -LDd -### -- %s 2>&1 | FileCheck %s -check-prefix=CHECK-ASAN-DEBUGRTL
|
||||
|
|
Loading…
Reference in New Issue