summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp4
-rw-r--r--clang/lib/CodeGen/CGCall.cpp5
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp72
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp34
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp6
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h12
6 files changed, 85 insertions, 48 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 533d1581e5c..3086de61abc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -476,8 +476,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
if (SanOpts.has(SanitizerKind::Unreachable)) {
SanitizerScope SanScope(this);
EmitCheck(Builder.getFalse(), "builtin_unreachable",
- EmitCheckSourceLocation(E->getExprLoc()),
- None, CRK_Unrecoverable);
+ EmitCheckSourceLocation(E->getExprLoc()), None,
+ SanitizerKind::Unreachable);
} else
Builder.CreateUnreachable();
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 6f2a27f977a..ca5db851df3 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -2300,7 +2300,8 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
EmitCheckSourceLocation(EndLoc),
EmitCheckSourceLocation(RetNNAttr->getLocation()),
};
- EmitCheck(Cond, "nonnull_return", StaticData, None, CRK_Recoverable);
+ EmitCheck(Cond, "nonnull_return", StaticData, None,
+ SanitizerKind::ReturnsNonnullAttribute);
}
}
Ret = Builder.CreateRet(RV);
@@ -2636,7 +2637,7 @@ static void emitNonNullArgCheck(CodeGenFunction &CGF, RValue RV,
llvm::ConstantInt::get(CGF.Int32Ty, ArgNo + 1),
};
CGF.EmitCheck(Cond, "nonnull_arg", StaticData, None,
- CodeGenFunction::CRK_Recoverable);
+ SanitizerKind::NonnullAttribute);
}
void CodeGenFunction::EmitCallArgs(CallArgList &Args,
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index e1b9b7b3577..389cd000a72 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -475,6 +475,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
if (Address->getType()->getPointerAddressSpace())
return;
+ SmallVector<SanitizerKind, 3> Kinds;
SanitizerScope SanScope(this);
llvm::Value *Cond = nullptr;
@@ -496,6 +497,8 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
Builder.CreateCondBr(Cond, Rest, Done);
EmitBlock(Rest);
Cond = nullptr;
+ } else {
+ Kinds.push_back(SanitizerKind::Null);
}
}
@@ -514,6 +517,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
Builder.CreateICmpUGE(Builder.CreateCall2(F, CastAddr, Min),
llvm::ConstantInt::get(IntPtrTy, Size));
Cond = Cond ? Builder.CreateAnd(Cond, LargeEnough) : LargeEnough;
+ Kinds.push_back(SanitizerKind::ObjectSize);
}
uint64_t AlignVal = 0;
@@ -531,6 +535,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
llvm::Value *Aligned =
Builder.CreateICmpEQ(Align, llvm::ConstantInt::get(IntPtrTy, 0));
Cond = Cond ? Builder.CreateAnd(Cond, Aligned) : Aligned;
+ Kinds.push_back(SanitizerKind::Alignment);
}
}
@@ -541,7 +546,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
llvm::ConstantInt::get(SizeTy, AlignVal),
llvm::ConstantInt::get(Int8Ty, TCK)
};
- EmitCheck(Cond, "type_mismatch", StaticData, Address, CRK_Recoverable);
+ EmitCheck(Cond, "type_mismatch", StaticData, Address, Kinds);
}
// If possible, check that the vptr indicates that there is a subobject of
@@ -606,9 +611,8 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
llvm::ConstantInt::get(Int8Ty, TCK)
};
llvm::Value *DynamicData[] = { Address, Hash };
- EmitCheck(Builder.CreateICmpEQ(CacheVal, Hash),
- "dynamic_type_cache_miss", StaticData, DynamicData,
- CRK_AlwaysRecoverable);
+ EmitCheck(Builder.CreateICmpEQ(CacheVal, Hash), "dynamic_type_cache_miss",
+ StaticData, DynamicData, SanitizerKind::Vptr);
}
}
@@ -696,7 +700,8 @@ void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base,
};
llvm::Value *Check = Accessed ? Builder.CreateICmpULT(IndexVal, BoundVal)
: Builder.CreateICmpULE(IndexVal, BoundVal);
- EmitCheck(Check, "out_of_bounds", StaticData, Index, CRK_Recoverable);
+ EmitCheck(Check, "out_of_bounds", StaticData, Index,
+ SanitizerKind::ArrayBounds);
}
@@ -1151,8 +1156,11 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
CGM.DecorateInstruction(Load, TBAAPath, false/*ConvertTypeToTag*/);
}
- if ((SanOpts.has(SanitizerKind::Bool) && hasBooleanRepresentation(Ty)) ||
- (SanOpts.has(SanitizerKind::Enum) && Ty->getAs<EnumType>())) {
+ bool NeedsBoolCheck =
+ SanOpts.has(SanitizerKind::Bool) && hasBooleanRepresentation(Ty);
+ bool NeedsEnumCheck =
+ SanOpts.has(SanitizerKind::Enum) && Ty->getAs<EnumType>();
+ if (NeedsBoolCheck || NeedsEnumCheck) {
SanitizerScope SanScope(this);
llvm::APInt Min, End;
if (getRangeForType(*this, Ty, Min, End, true)) {
@@ -1173,7 +1181,7 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
EmitCheckTypeDescriptor(Ty)
};
EmitCheck(Check, "load_invalid_value", StaticArgs, EmitCheckValue(Load),
- CRK_Recoverable);
+ NeedsEnumCheck ? SanitizerKind::Enum : SanitizerKind::Bool);
}
} else if (CGM.getCodeGenOpts().OptimizationLevel > 0)
if (llvm::MDNode *RangeInfo = getRangeForLoadFromType(Ty))
@@ -2169,14 +2177,45 @@ llvm::Constant *CodeGenFunction::EmitCheckSourceLocation(SourceLocation Loc) {
return llvm::ConstantStruct::getAnon(Data);
}
+namespace {
+/// \brief Specify under what conditions this check can be recovered
+enum class CheckRecoverableKind {
+ /// Always terminate program execution if this check fails
+ Unrecoverable,
+ /// Check supports recovering, allows user to specify which
+ Recoverable,
+ /// Runtime conditionally aborts, always need to support recovery.
+ AlwaysRecoverable
+};
+}
+
+static CheckRecoverableKind getRecoverableKind(SanitizerKind Kind) {
+ switch (Kind) {
+ case SanitizerKind::Vptr:
+ return CheckRecoverableKind::AlwaysRecoverable;
+ case SanitizerKind::Return:
+ case SanitizerKind::Unreachable:
+ return CheckRecoverableKind::Unrecoverable;
+ default:
+ return CheckRecoverableKind::Recoverable;
+ }
+}
+
void CodeGenFunction::EmitCheck(llvm::Value *Checked, StringRef CheckName,
ArrayRef<llvm::Constant *> StaticArgs,
ArrayRef<llvm::Value *> DynamicArgs,
- CheckRecoverableKind RecoverKind) {
+ ArrayRef<SanitizerKind> Kinds) {
assert(IsSanitizerScope);
+ assert(Kinds.size() > 0);
+ CheckRecoverableKind RecoverKind = getRecoverableKind(Kinds[0]);
+ for (int i = 1, n = Kinds.size(); i < n; ++i)
+ assert(RecoverKind == getRecoverableKind(Kinds[i]) &&
+ "All recoverable kinds in a single check must be same!");
+ for (auto Kind : Kinds)
+ assert(SanOpts.has(Kind));
if (CGM.getCodeGenOpts().SanitizeUndefinedTrapOnError) {
- assert (RecoverKind != CRK_AlwaysRecoverable &&
+ assert (RecoverKind != CheckRecoverableKind::AlwaysRecoverable &&
"Runtime call required for AlwaysRecoverable kind!");
return EmitTrapCheck(Checked);
}
@@ -2217,8 +2256,8 @@ void CodeGenFunction::EmitCheck(llvm::Value *Checked, StringRef CheckName,
ArgTypes.push_back(IntPtrTy);
}
- bool Recover = RecoverKind == CRK_AlwaysRecoverable ||
- (RecoverKind == CRK_Recoverable &&
+ bool Recover = RecoverKind == CheckRecoverableKind::AlwaysRecoverable ||
+ (RecoverKind == CheckRecoverableKind::Recoverable &&
CGM.getCodeGenOpts().SanitizeRecover);
llvm::FunctionType *FnType =
@@ -2231,7 +2270,7 @@ void CodeGenFunction::EmitCheck(llvm::Value *Checked, StringRef CheckName,
B.addAttribute(llvm::Attribute::UWTable);
// Checks that have two variants use a suffix to differentiate them
- bool NeedsAbortSuffix = RecoverKind != CRK_Unrecoverable &&
+ bool NeedsAbortSuffix = RecoverKind != CheckRecoverableKind::Unrecoverable &&
!CGM.getCodeGenOpts().SanitizeRecover;
std::string FunctionName = ("__ubsan_handle_" + CheckName +
(NeedsAbortSuffix? "_abort" : "")).str();
@@ -3260,11 +3299,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
EmitCheckSourceLocation(E->getLocStart()),
EmitCheckTypeDescriptor(CalleeType)
};
- EmitCheck(CalleeRTTIMatch,
- "function_type_mismatch",
- StaticData,
- Callee,
- CRK_Recoverable);
+ EmitCheck(CalleeRTTIMatch, "function_type_mismatch", StaticData, Callee,
+ SanitizerKind::Function);
Builder.CreateBr(Cont);
EmitBlock(Cont);
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 36a001f242b..10094228995 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -85,7 +85,8 @@ public:
return CGF.EmitCheckedLValue(E, TCK);
}
- void EmitBinOpCheck(Value *Check, const BinOpInfo &Info);
+ void EmitBinOpCheck(Value *Check, const BinOpInfo &Info,
+ ArrayRef<SanitizerKind> Kinds);
Value *EmitLoadOfLValue(LValue LV, SourceLocation Loc) {
return CGF.EmitLoadOfLValue(LV, Loc).getScalarVal();
@@ -726,7 +727,7 @@ void ScalarExprEmitter::EmitFloatConversionCheck(Value *OrigSrc,
CGF.EmitCheckTypeDescriptor(DstType)
};
CGF.EmitCheck(Check, "float_cast_overflow", StaticArgs, OrigSrc,
- CodeGenFunction::CRK_Recoverable);
+ SanitizerKind::FloatCastOverflow);
}
/// EmitScalarConversion - Emit a conversion from the specified type to the
@@ -885,7 +886,8 @@ Value *ScalarExprEmitter::EmitNullValue(QualType Ty) {
/// \brief Emit a sanitization check for the given "binary" operation (which
/// might actually be a unary increment which has been lowered to a binary
/// operation). The check passes if \p Check, which is an \c i1, is \c true.
-void ScalarExprEmitter::EmitBinOpCheck(Value *Check, const BinOpInfo &Info) {
+void ScalarExprEmitter::EmitBinOpCheck(Value *Check, const BinOpInfo &Info,
+ ArrayRef<SanitizerKind> Kinds) {
assert(CGF.IsSanitizerScope);
StringRef CheckName;
SmallVector<llvm::Constant *, 4> StaticData;
@@ -915,7 +917,7 @@ void ScalarExprEmitter::EmitBinOpCheck(Value *Check, const BinOpInfo &Info) {
CheckName = "divrem_overflow";
StaticData.push_back(CGF.EmitCheckTypeDescriptor(Info.Ty));
} else {
- // Signed arithmetic overflow (+, -, *).
+ // Arithmetic overflow (+, -, *).
switch (Opcode) {
case BO_Add: CheckName = "add_overflow"; break;
case BO_Sub: CheckName = "sub_overflow"; break;
@@ -928,8 +930,7 @@ void ScalarExprEmitter::EmitBinOpCheck(Value *Check, const BinOpInfo &Info) {
DynamicData.push_back(Info.RHS);
}
- CGF.EmitCheck(Check, CheckName, StaticData, DynamicData,
- CodeGenFunction::CRK_Recoverable);
+ CGF.EmitCheck(Check, CheckName, StaticData, DynamicData, Kinds);
}
//===----------------------------------------------------------------------===//
@@ -2179,9 +2180,12 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E,
void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) {
llvm::Value *Cond = nullptr;
+ SmallVector<SanitizerKind, 2> Kinds;
- if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero))
+ if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero)) {
Cond = Builder.CreateICmpNE(Ops.RHS, Zero);
+ Kinds.push_back(SanitizerKind::IntegerDivideByZero);
+ }
if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow) &&
Ops.Ty->hasSignedIntegerRepresentation()) {
@@ -2195,10 +2199,11 @@ void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
llvm::Value *RHSCmp = Builder.CreateICmpNE(Ops.RHS, NegOne);
llvm::Value *Overflow = Builder.CreateOr(LHSCmp, RHSCmp, "or");
Cond = Cond ? Builder.CreateAnd(Cond, Overflow, "and") : Overflow;
+ Kinds.push_back(SanitizerKind::SignedIntegerOverflow);
}
if (Cond)
- EmitBinOpCheck(Cond, Ops);
+ EmitBinOpCheck(Cond, Ops, Kinds);
}
Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) {
@@ -2212,7 +2217,8 @@ Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) {
} else if (CGF.SanOpts.has(SanitizerKind::FloatDivideByZero) &&
Ops.Ty->isRealFloatingType()) {
llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty));
- EmitBinOpCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero), Ops);
+ EmitBinOpCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero), Ops,
+ SanitizerKind::FloatDivideByZero);
}
}
@@ -2297,7 +2303,9 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
// runtime. Otherwise, this is a -ftrapv check, so just emit a trap.
if (!isSigned || CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) {
CodeGenFunction::SanitizerScope SanScope(&CGF);
- EmitBinOpCheck(Builder.CreateNot(overflow), Ops);
+ EmitBinOpCheck(Builder.CreateNot(overflow), Ops,
+ isSigned ? SanitizerKind::SignedIntegerOverflow
+ : SanitizerKind::UnsignedIntegerOverflow);
} else
CGF.EmitTrapCheck(Builder.CreateNot(overflow));
return result;
@@ -2687,7 +2695,7 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
Valid = P;
}
- EmitBinOpCheck(Valid, Ops);
+ EmitBinOpCheck(Valid, Ops, SanitizerKind::Shift);
}
// OpenCL 6.3j: shift values are effectively % word size of LHS.
if (CGF.getLangOpts().OpenCL)
@@ -2706,7 +2714,9 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) {
if (CGF.SanOpts.has(SanitizerKind::Shift) && !CGF.getLangOpts().OpenCL &&
isa<llvm::IntegerType>(Ops.LHS->getType())) {
CodeGenFunction::SanitizerScope SanScope(&CGF);
- EmitBinOpCheck(Builder.CreateICmpULE(RHS, GetWidthMinusOneValue(Ops.LHS, RHS)), Ops);
+ EmitBinOpCheck(
+ Builder.CreateICmpULE(RHS, GetWidthMinusOneValue(Ops.LHS, RHS)), Ops,
+ SanitizerKind::Shift);
}
// OpenCL 6.3j: shift values are effectively % word size of LHS.
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 5853e076839..cbedf61c559 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -900,8 +900,8 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
if (SanOpts.has(SanitizerKind::Return)) {
SanitizerScope SanScope(this);
EmitCheck(Builder.getFalse(), "missing_return",
- EmitCheckSourceLocation(FD->getLocation()),
- None, CRK_Unrecoverable);
+ EmitCheckSourceLocation(FD->getLocation()), None,
+ SanitizerKind::Return);
} else if (CGM.getCodeGenOpts().OptimizationLevel == 0)
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::trap));
Builder.CreateUnreachable();
@@ -1562,7 +1562,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
};
EmitCheck(Builder.CreateICmpSGT(Size, Zero),
"vla_bound_not_positive", StaticArgs, Size,
- CRK_Recoverable);
+ SanitizerKind::VLABound);
}
// Always zexting here would be wrong if it weren't
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index a683e88783f..de2f4daed9b 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -2649,23 +2649,13 @@ public:
/// passing to a runtime sanitizer handler.
llvm::Constant *EmitCheckSourceLocation(SourceLocation Loc);
- /// \brief Specify under what conditions this check can be recovered
- enum CheckRecoverableKind {
- /// Always terminate program execution if this check fails
- CRK_Unrecoverable,
- /// Check supports recovering, allows user to specify which
- CRK_Recoverable,
- /// Runtime conditionally aborts, always need to support recovery.
- CRK_AlwaysRecoverable
- };
-
/// \brief Create a basic block that will call a handler function in a
/// sanitizer runtime with the provided arguments, and create a conditional
/// branch to it.
void EmitCheck(llvm::Value *Checked, StringRef CheckName,
ArrayRef<llvm::Constant *> StaticArgs,
ArrayRef<llvm::Value *> DynamicArgs,
- CheckRecoverableKind Recoverable);
+ ArrayRef<SanitizerKind> Kinds);
/// \brief Create a basic block that will call the trap intrinsic, and emit a
/// conditional branch to it, for the -ftrapv checks.
OpenPOWER on IntegriCloud