aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/CodeGen/CGExpr.cpp9
-rw-r--r--lib/CodeGen/CGExprScalar.cpp2
-rw-r--r--lib/CodeGen/CodeGenFunction.h2
-rw-r--r--lib/Driver/SanitizerArgs.h18
-rw-r--r--lib/Driver/Tools.cpp32
-rw-r--r--lib/Frontend/CompilerInvocation.cpp2
6 files changed, 57 insertions, 8 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 9bef08b4a5..aad877134d 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -1975,6 +1975,13 @@ void CodeGenFunction::EmitCheck(llvm::Value *Checked, StringRef CheckName,
ArrayRef<llvm::Value *> DynamicArgs,
CheckRecoverableKind RecoverKind) {
assert(SanOpts != &SanitizerOptions::Disabled);
+
+ if (CGM.getCodeGenOpts().SanitizeUndefinedTrapOnError) {
+ assert (RecoverKind != CRK_AlwaysRecoverable &&
+ "Runtime call required for AlwaysRecoverable kind!");
+ return EmitTrapCheck(Checked);
+ }
+
llvm::BasicBlock *Cont = createBasicBlock("cont");
llvm::BasicBlock *Handler = createBasicBlock("handler." + CheckName);
@@ -2043,7 +2050,7 @@ void CodeGenFunction::EmitCheck(llvm::Value *Checked, StringRef CheckName,
EmitBlock(Cont);
}
-void CodeGenFunction::EmitTrapvCheck(llvm::Value *Checked) {
+void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked) {
llvm::BasicBlock *Cont = createBasicBlock("cont");
// If we're optimizing, collapse all calls to trap down to just one per
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 7f0eda8993..49494be901 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -2044,7 +2044,7 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
if (!isSigned || CGF.SanOpts->SignedIntegerOverflow)
EmitBinOpCheck(Builder.CreateNot(overflow), Ops);
else
- CGF.EmitTrapvCheck(Builder.CreateNot(overflow));
+ CGF.EmitTrapCheck(Builder.CreateNot(overflow));
return result;
}
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 6f06b3bc26..ce3db3f4ec 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -2606,7 +2606,7 @@ public:
/// \brief Create a basic block that will call the trap intrinsic, and emit a
/// conditional branch to it, for the -ftrapv checks.
- void EmitTrapvCheck(llvm::Value *Checked);
+ void EmitTrapCheck(llvm::Value *Checked);
/// EmitCallArg - Emit a single call argument.
void EmitCallArg(CallArgList &args, const Expr *E, QualType ArgType);
diff --git a/lib/Driver/SanitizerArgs.h b/lib/Driver/SanitizerArgs.h
index a281959891..bc3aa58331 100644
--- a/lib/Driver/SanitizerArgs.h
+++ b/lib/Driver/SanitizerArgs.h
@@ -36,25 +36,32 @@ class SanitizerArgs {
NeedsAsanRt = Address,
NeedsTsanRt = Thread,
NeedsMsanRt = Memory,
- NeedsUbsanRt = (Undefined & ~Bounds) | Integer
+ NeedsUbsanRt = (Undefined & ~Bounds) | Integer,
+ NotAllowedWithTrap = Vptr
};
unsigned Kind;
std::string BlacklistFile;
bool MsanTrackOrigins;
bool AsanZeroBaseShadow;
+ bool UbsanTrapOnError;
public:
SanitizerArgs() : Kind(0), BlacklistFile(""), MsanTrackOrigins(false),
- AsanZeroBaseShadow(false) {}
+ AsanZeroBaseShadow(false), UbsanTrapOnError(false) {}
/// Parses the sanitizer arguments from an argument list.
SanitizerArgs(const Driver &D, const ArgList &Args);
bool needsAsanRt() const { return Kind & NeedsAsanRt; }
bool needsTsanRt() const { return Kind & NeedsTsanRt; }
bool needsMsanRt() const { return Kind & NeedsMsanRt; }
- bool needsUbsanRt() const { return Kind & NeedsUbsanRt; }
+ bool needsUbsanRt() const {
+ if (UbsanTrapOnError)
+ return false;
+ return Kind & NeedsUbsanRt;
+ }
bool sanitizesVptr() const { return Kind & Vptr; }
+ bool notAllowedWithTrap() const { return Kind & NotAllowedWithTrap; }
void addArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
if (!Kind)
@@ -127,8 +134,9 @@ class SanitizerArgs {
Remove = Thread;
DeprecatedReplacement = "-fno-sanitize=thread";
} else if (A->getOption().matches(options::OPT_fcatch_undefined_behavior)) {
- Add = Undefined;
- DeprecatedReplacement = "-fsanitize=undefined";
+ 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;
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index e4be6935ea..f925f762e5 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -1459,6 +1459,33 @@ SanitizerArgs::SanitizerArgs(const Driver &D, const ArgList &Args)
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();
@@ -2501,6 +2528,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
true))
CmdArgs.push_back("-fno-sanitize-recover");
+ 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, false))
+ CmdArgs.push_back("-fsanitize-undefined-trap-on-error");
+
// Report and error for -faltivec on anything other then PowerPC.
if (const Arg *A = Args.getLastArg(options::OPT_faltivec))
if (!(getToolChain().getTriple().getArch() == llvm::Triple::ppc ||
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index b200637cb5..245de3416f 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -392,6 +392,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Args.hasArg(OPT_fsanitize_memory_track_origins);
Opts.SanitizeAddressZeroBaseShadow =
Args.hasArg(OPT_fsanitize_address_zero_base_shadow);
+ Opts.SanitizeUndefinedTrapOnError =
+ Args.hasArg(OPT_fsanitize_undefined_trap_on_error);
Opts.SSPBufferSize =
Args.getLastArgIntValue(OPT_stack_protector_buffer_size, 8, Diags);
Opts.StackRealignment = Args.hasArg(OPT_mstackrealign);