summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Dietz <wdietz2@illinois.edu>2013-01-18 11:30:38 +0000
committerWill Dietz <wdietz2@illinois.edu>2013-01-18 11:30:38 +0000
commit4f45bc099f2665bc6e4bcbb169aa452390dbf3fe (patch)
tree67a70eeaf5da4ec49baf3ce37ac44bb15eb1c9fb
parentc79afdae8a2e12d1e8f27a2ae0a43dfca3b8283b (diff)
downloadclang-4f45bc099f2665bc6e4bcbb169aa452390dbf3fe.tar.gz
clang-4f45bc099f2665bc6e4bcbb169aa452390dbf3fe.tar.bz2
clang-4f45bc099f2665bc6e4bcbb169aa452390dbf3fe.tar.xz
[ubsan] Add support for -fsanitize-blacklist
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172808 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/LangOptions.def5
-rw-r--r--include/clang/Basic/LangOptions.h9
-rw-r--r--lib/Basic/LangOptions.cpp8
-rw-r--r--lib/Basic/Targets.cpp2
-rw-r--r--lib/CodeGen/BackendUtil.cpp16
-rw-r--r--lib/CodeGen/CGBuiltin.cpp2
-rw-r--r--lib/CodeGen/CGDeclCXX.cpp2
-rw-r--r--lib/CodeGen/CGExpr.cpp13
-rw-r--r--lib/CodeGen/CGExprScalar.cpp49
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp18
-rw-r--r--lib/CodeGen/CodeGenFunction.h5
-rw-r--r--lib/CodeGen/CodeGenModule.cpp15
-rw-r--r--lib/CodeGen/CodeGenModule.h15
-rw-r--r--lib/Frontend/CompilerInvocation.cpp2
-rw-r--r--lib/Lex/PPMacroExpansion.cpp6
-rw-r--r--lib/Serialization/ASTReader.cpp2
-rw-r--r--lib/Serialization/ASTWriter.cpp2
-rw-r--r--test/CodeGen/address-safety-attr.cpp2
-rw-r--r--test/CodeGen/ubsan-blacklist.c28
19 files changed, 133 insertions, 68 deletions
diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def
index b78c26118c..5e418cfdf0 100644
--- a/include/clang/Basic/LangOptions.def
+++ b/include/clang/Basic/LangOptions.def
@@ -170,11 +170,6 @@ BENIGN_LANGOPT(EmitMicrosoftInlineAsm , 1, 0,
BENIGN_LANGOPT(RetainCommentsFromSystemHeaders, 1, 0, "retain documentation comments from system headers in the AST")
-/// Runtime sanitizers.
-#define SANITIZER(NAME, ID) \
-BENIGN_LANGOPT(Sanitize##ID, 1, 0, NAME " sanitizer")
-#include "clang/Basic/Sanitizers.def"
-
#undef LANGOPT
#undef VALUE_LANGOPT
#undef BENIGN_LANGOPT
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index a016b68948..29c4e7b906 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -23,6 +23,14 @@
namespace clang {
+struct SanitizerOptions {
+#define SANITIZER(NAME, ID) unsigned ID : 1;
+#include "clang/Basic/Sanitizers.def"
+
+ /// \brief Cached set of sanitizer options with all sanitizers disabled.
+ static const SanitizerOptions Disabled;
+};
+
/// Bitfields of LangOptions, split out from LangOptions in order to ensure that
/// this large collection of bitfields is a trivial class type.
class LangOptionsBase {
@@ -32,6 +40,7 @@ public:
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description)
#include "clang/Basic/LangOptions.def"
+ SanitizerOptions Sanitize;
protected:
// Define language options of enumeration type. These are private, and will
// have accessors (below).
diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp
index 991992a477..e18d9256f5 100644
--- a/lib/Basic/LangOptions.cpp
+++ b/lib/Basic/LangOptions.cpp
@@ -14,10 +14,14 @@
using namespace clang;
+const SanitizerOptions SanitizerOptions::Disabled = {};
+
LangOptions::LangOptions() {
#define LANGOPT(Name, Bits, Default, Description) Name = Default;
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) set##Name(Default);
#include "clang/Basic/LangOptions.def"
+
+ Sanitize = SanitizerOptions::Disabled;
}
void LangOptions::resetNonModularOptions() {
@@ -26,7 +30,9 @@ void LangOptions::resetNonModularOptions() {
#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
Name = Default;
#include "clang/Basic/LangOptions.def"
-
+
+ Sanitize = SanitizerOptions::Disabled;
+
CurrentModule.clear();
}
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 9f7e97cf7f..8e45804bff 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -94,7 +94,7 @@ static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
Builder.defineMacro("OBJC_NEW_PROPERTIES");
// AddressSanitizer doesn't play well with source fortification, which is on
// by default on Darwin.
- if (Opts.SanitizeAddress) Builder.defineMacro("_FORTIFY_SOURCE", "0");
+ if (Opts.Sanitize.Address) Builder.defineMacro("_FORTIFY_SOURCE", "0");
if (!Opts.ObjCAutoRefCount) {
// __weak is always defined, for use in blocks and with objc pointers.
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index d343207545..8a3ee398cd 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/lib/CodeGen/BackendUtil.cpp
@@ -164,11 +164,11 @@ static void addAddressSanitizerPasses(const PassManagerBuilder &Builder,
static_cast<const PassManagerBuilderWrapper&>(Builder);
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
const LangOptions &LangOpts = BuilderWrapper.getLangOpts();
- PM.add(createAddressSanitizerFunctionPass(LangOpts.SanitizeInitOrder,
- LangOpts.SanitizeUseAfterReturn,
- LangOpts.SanitizeUseAfterScope,
+ PM.add(createAddressSanitizerFunctionPass(LangOpts.Sanitize.InitOrder,
+ LangOpts.Sanitize.UseAfterReturn,
+ LangOpts.Sanitize.UseAfterScope,
CGOpts.SanitizerBlacklistFile));
- PM.add(createAddressSanitizerModulePass(LangOpts.SanitizeInitOrder,
+ PM.add(createAddressSanitizerModulePass(LangOpts.Sanitize.InitOrder,
CGOpts.SanitizerBlacklistFile));
}
@@ -218,28 +218,28 @@ void EmitAssemblyHelper::CreatePasses(TargetMachine *TM) {
addObjCARCOptPass);
}
- if (LangOpts.SanitizeBounds) {
+ if (LangOpts.Sanitize.Bounds) {
PMBuilder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate,
addBoundsCheckingPass);
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
addBoundsCheckingPass);
}
- if (LangOpts.SanitizeAddress) {
+ if (LangOpts.Sanitize.Address) {
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
addAddressSanitizerPasses);
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
addAddressSanitizerPasses);
}
- if (LangOpts.SanitizeMemory) {
+ if (LangOpts.Sanitize.Memory) {
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
addMemorySanitizerPass);
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
addMemorySanitizerPass);
}
- if (LangOpts.SanitizeThread) {
+ if (LangOpts.Sanitize.Thread) {
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
addThreadSanitizerPass);
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 6678ebe71c..9e09131a53 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -436,7 +436,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(Builder.CreateCall(F));
}
case Builtin::BI__builtin_unreachable: {
- if (getLangOpts().SanitizeUnreachable)
+ if (SanOpts->Unreachable)
EmitCheck(Builder.getFalse(), "builtin_unreachable",
EmitCheckSourceLocation(E->getExprLoc()),
ArrayRef<llvm::Value *>(), CRK_Unrecoverable);
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
index 11f1609a3b..f9d8199bb8 100644
--- a/lib/CodeGen/CGDeclCXX.cpp
+++ b/lib/CodeGen/CGDeclCXX.cpp
@@ -232,7 +232,7 @@ CreateGlobalInitOrDestructFunction(CodeGenModule &CGM,
if (!CGM.getLangOpts().Exceptions)
Fn->setDoesNotThrow();
- if (CGM.getLangOpts().SanitizeAddress)
+ if (CGM.getSanOpts().Address)
Fn->addFnAttr(llvm::Attribute::AddressSafety);
return Fn;
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 85adf35961..cdbd6e7bb7 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -487,13 +487,13 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
llvm::Value *Cond = 0;
- if (getLangOpts().SanitizeNull) {
+ if (SanOpts->Null) {
// The glvalue must not be an empty glvalue.
Cond = Builder.CreateICmpNE(
Address, llvm::Constant::getNullValue(Address->getType()));
}
- if (getLangOpts().SanitizeObjectSize && !Ty->isIncompleteType()) {
+ if (SanOpts->ObjectSize && !Ty->isIncompleteType()) {
uint64_t Size = getContext().getTypeSizeInChars(Ty).getQuantity();
// The glvalue must refer to a large enough storage region.
@@ -510,7 +510,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
uint64_t AlignVal = 0;
- if (getLangOpts().SanitizeAlignment) {
+ if (SanOpts->Alignment) {
AlignVal = Alignment.getQuantity();
if (!Ty->isIncompleteType() && !AlignVal)
AlignVal = getContext().getTypeAlignInChars(Ty).getQuantity();
@@ -545,7 +545,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
// -- the [pointer or glvalue] is used to access a non-static data member
// or call a non-static member function
CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
- if (getLangOpts().SanitizeVptr &&
+ if (SanOpts->Vptr &&
(TCK == TCK_MemberAccess || TCK == TCK_MemberCall) &&
RD && RD->hasDefinition() && RD->isDynamicClass()) {
// Compute a hash of the mangled name of the type.
@@ -1028,8 +1028,8 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
if (Ty->isAtomicType())
Load->setAtomic(llvm::SequentiallyConsistent);
- if ((getLangOpts().SanitizeBool && hasBooleanRepresentation(Ty)) ||
- (getLangOpts().SanitizeEnum && Ty->getAs<EnumType>())) {
+ if ((SanOpts->Bool && hasBooleanRepresentation(Ty)) ||
+ (SanOpts->Enum && Ty->getAs<EnumType>())) {
llvm::APInt Min, End;
if (getRangeForType(*this, Ty, Min, End, true)) {
--End;
@@ -1974,6 +1974,7 @@ void CodeGenFunction::EmitCheck(llvm::Value *Checked, StringRef CheckName,
ArrayRef<llvm::Constant *> StaticArgs,
ArrayRef<llvm::Value *> DynamicArgs,
CheckRecoverableKind RecoverKind) {
+ assert(SanOpts != &SanitizerOptions::Disabled);
llvm::BasicBlock *Cont = createBasicBlock("cont");
llvm::BasicBlock *Handler = createBasicBlock("handler." + CheckName);
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index ebabf76448..5715913b6a 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -406,7 +406,7 @@ public:
case LangOptions::SOB_Defined:
return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
case LangOptions::SOB_Undefined:
- if (!CGF.getLangOpts().SanitizeSignedIntegerOverflow)
+ if (!CGF.SanOpts->SignedIntegerOverflow)
return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
// Fall through.
case LangOptions::SOB_Trapping:
@@ -414,8 +414,7 @@ public:
}
}
- if (Ops.Ty->isUnsignedIntegerType() &&
- CGF.getLangOpts().SanitizeUnsignedIntegerOverflow)
+ if (Ops.Ty->isUnsignedIntegerType() && CGF.SanOpts->UnsignedIntegerOverflow)
return EmitOverflowCheckedBinOp(Ops);
if (Ops.LHS->getType()->isFPOrFPVectorTy())
@@ -730,9 +729,10 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
// An overflowing conversion has undefined behavior if either the source type
// or the destination type is a floating-point type.
- if (CGF.getLangOpts().SanitizeFloatCastOverflow &&
+ if (CGF.SanOpts->FloatCastOverflow &&
(OrigSrcType->isFloatingType() || DstType->isFloatingType()))
- EmitFloatConversionCheck(OrigSrc, OrigSrcType, Src, SrcType, DstType, DstTy);
+ EmitFloatConversionCheck(OrigSrc, OrigSrcType, Src, SrcType, DstType,
+ DstTy);
// Cast to half via float
if (DstType->isHalfType())
@@ -1406,7 +1406,7 @@ EmitAddConsiderOverflowBehavior(const UnaryOperator *E,
case LangOptions::SOB_Defined:
return Builder.CreateAdd(InVal, NextVal, IsInc ? "inc" : "dec");
case LangOptions::SOB_Undefined:
- if (!CGF.getLangOpts().SanitizeSignedIntegerOverflow)
+ if (!CGF.SanOpts->SignedIntegerOverflow)
return Builder.CreateNSWAdd(InVal, NextVal, IsInc ? "inc" : "dec");
// Fall through.
case LangOptions::SOB_Trapping:
@@ -1466,9 +1466,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
type->isSignedIntegerOrEnumerationType()) {
value = EmitAddConsiderOverflowBehavior(E, value, amt, isInc);
} else if (value->getType()->getPrimitiveSizeInBits() >=
- CGF.IntTy->getBitWidth() &&
- type->isUnsignedIntegerType() &&
- CGF.getLangOpts().SanitizeUnsignedIntegerOverflow) {
+ CGF.IntTy->getBitWidth() && type->isUnsignedIntegerType() &&
+ CGF.SanOpts->UnsignedIntegerOverflow) {
BinOpInfo BinOp;
BinOp.LHS = value;
BinOp.RHS = llvm::ConstantInt::get(value->getType(), 1, false);
@@ -1927,10 +1926,10 @@ void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) {
llvm::Value *Cond = 0;
- if (CGF.getLangOpts().SanitizeIntegerDivideByZero)
+ if (CGF.SanOpts->IntegerDivideByZero)
Cond = Builder.CreateICmpNE(Ops.RHS, Zero);
- if (CGF.getLangOpts().SanitizeSignedIntegerOverflow &&
+ if (CGF.SanOpts->SignedIntegerOverflow &&
Ops.Ty->hasSignedIntegerRepresentation()) {
llvm::IntegerType *Ty = cast<llvm::IntegerType>(Zero->getType());
@@ -1949,12 +1948,12 @@ void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
}
Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) {
- if ((CGF.getLangOpts().SanitizeIntegerDivideByZero ||
- CGF.getLangOpts().SanitizeSignedIntegerOverflow) &&
+ if ((CGF.SanOpts->IntegerDivideByZero ||
+ CGF.SanOpts->SignedIntegerOverflow) &&
Ops.Ty->isIntegerType()) {
llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty));
EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, true);
- } else if (CGF.getLangOpts().SanitizeFloatDivideByZero &&
+ } else if (CGF.SanOpts->FloatDivideByZero &&
Ops.Ty->isRealFloatingType()) {
llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty));
EmitBinOpCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero), Ops);
@@ -1980,7 +1979,7 @@ Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) {
Value *ScalarExprEmitter::EmitRem(const BinOpInfo &Ops) {
// Rem in C can't be a floating point type: C99 6.5.5p2.
- if (CGF.getLangOpts().SanitizeIntegerDivideByZero) {
+ if (CGF.SanOpts->IntegerDivideByZero) {
llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty));
if (Ops.Ty->isIntegerType())
@@ -2038,7 +2037,7 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
if (handlerName->empty()) {
// If the signed-integer-overflow sanitizer is enabled, emit a call to its
// runtime. Otherwise, this is a -ftrapv check, so just emit a trap.
- if (!isSigned || CGF.getLangOpts().SanitizeSignedIntegerOverflow)
+ if (!isSigned || CGF.SanOpts->SignedIntegerOverflow)
EmitBinOpCheck(Builder.CreateNot(overflow), Ops);
else
CGF.EmitTrapvCheck(Builder.CreateNot(overflow));
@@ -2256,7 +2255,7 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &op) {
case LangOptions::SOB_Defined:
return Builder.CreateAdd(op.LHS, op.RHS, "add");
case LangOptions::SOB_Undefined:
- if (!CGF.getLangOpts().SanitizeSignedIntegerOverflow)
+ if (!CGF.SanOpts->SignedIntegerOverflow)
return Builder.CreateNSWAdd(op.LHS, op.RHS, "add");
// Fall through.
case LangOptions::SOB_Trapping:
@@ -2264,8 +2263,7 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &op) {
}
}
- if (op.Ty->isUnsignedIntegerType() &&
- CGF.getLangOpts().SanitizeUnsignedIntegerOverflow)
+ if (op.Ty->isUnsignedIntegerType() && CGF.SanOpts->UnsignedIntegerOverflow)
return EmitOverflowCheckedBinOp(op);
if (op.LHS->getType()->isFPOrFPVectorTy()) {
@@ -2287,7 +2285,7 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &op) {
case LangOptions::SOB_Defined:
return Builder.CreateSub(op.LHS, op.RHS, "sub");
case LangOptions::SOB_Undefined:
- if (!CGF.getLangOpts().SanitizeSignedIntegerOverflow)
+ if (!CGF.SanOpts->SignedIntegerOverflow)
return Builder.CreateNSWSub(op.LHS, op.RHS, "sub");
// Fall through.
case LangOptions::SOB_Trapping:
@@ -2295,8 +2293,7 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &op) {
}
}
- if (op.Ty->isUnsignedIntegerType() &&
- CGF.getLangOpts().SanitizeUnsignedIntegerOverflow)
+ if (op.Ty->isUnsignedIntegerType() && CGF.SanOpts->UnsignedIntegerOverflow)
return EmitOverflowCheckedBinOp(op);
if (op.LHS->getType()->isFPOrFPVectorTy()) {
@@ -2383,8 +2380,8 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
if (Ops.LHS->getType() != RHS->getType())
RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom");
- if (CGF.getLangOpts().SanitizeShift && !CGF.getLangOpts().OpenCL
- && isa<llvm::IntegerType>(Ops.LHS->getType())) {
+ if (CGF.SanOpts->Shift && !CGF.getLangOpts().OpenCL &&
+ isa<llvm::IntegerType>(Ops.LHS->getType())) {
llvm::Value *WidthMinusOne = GetWidthMinusOneValue(Ops.LHS, RHS);
// FIXME: Emit the branching explicitly rather than emitting the check
// twice.
@@ -2424,8 +2421,8 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) {
if (Ops.LHS->getType() != RHS->getType())
RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom");
- if (CGF.getLangOpts().SanitizeShift && !CGF.getLangOpts().OpenCL
- && isa<llvm::IntegerType>(Ops.LHS->getType()))
+ if (CGF.SanOpts->Shift && !CGF.getLangOpts().OpenCL &&
+ isa<llvm::IntegerType>(Ops.LHS->getType()))
EmitBinOpCheck(Builder.CreateICmpULE(RHS, GetWidthMinusOneValue(Ops.LHS, RHS)), Ops);
// OpenCL 6.3j: shift values are effectively % word size of LHS.
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 8ba1bf4b6f..1fdcc6f9ec 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -33,10 +33,11 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
: CodeGenTypeCache(cgm), CGM(cgm),
Target(CGM.getContext().getTargetInfo()),
Builder(cgm.getModule().getContext()),
- SanitizePerformTypeCheck(CGM.getLangOpts().SanitizeNull |
- CGM.getLangOpts().SanitizeAlignment |
- CGM.getLangOpts().SanitizeObjectSize |
- CGM.getLangOpts().SanitizeVptr),
+ SanitizePerformTypeCheck(CGM.getSanOpts().Null |
+ CGM.getSanOpts().Alignment |
+ CGM.getSanOpts().ObjectSize |
+ CGM.getSanOpts().Vptr),
+ SanOpts(&CGM.getSanOpts()),
AutoreleaseResult(false), BlockInfo(0), BlockPointer(0),
LambdaThisCaptureField(0), NormalCleanupDest(0), NextCleanupDestIndex(1),
FirstBlockInfo(0), EHResumeBlock(0), ExceptionSlot(0), EHSelectorSlot(0),
@@ -347,6 +348,11 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
CurFnInfo = &FnInfo;
assert(CurFn->isDeclaration() && "Function already has body?");
+ if (CGM.getSanitizerBlacklist().isIn(*Fn)) {
+ SanOpts = &SanitizerOptions::Disabled;
+ SanitizePerformTypeCheck = false;
+ }
+
// Pass inline keyword to optimizer if it appears explicitly on any
// declaration.
if (!CGM.getCodeGenOpts().NoInline)
@@ -558,7 +564,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
// function call is used by the caller, the behavior is undefined.
if (getLangOpts().CPlusPlus && !FD->hasImplicitReturnZero() &&
!FD->getResultType()->isVoidType() && Builder.GetInsertBlock()) {
- if (getLangOpts().SanitizeReturn)
+ if (SanOpts->Return)
EmitCheck(Builder.getFalse(), "missing_return",
EmitCheckSourceLocation(FD->getLocation()),
ArrayRef<llvm::Value *>(), CRK_Unrecoverable);
@@ -1143,7 +1149,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
// If the size is an expression that is not an integer constant
// expression [...] each time it is evaluated it shall have a value
// greater than zero.
- if (getLangOpts().SanitizeVLABound &&
+ if (SanOpts->VLABound &&
size->getType()->isSignedIntegerType()) {
llvm::Value *Zero = llvm::Constant::getNullValue(Size->getType());
llvm::Constant *StaticArgs[] = {
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 61122666a1..afe99381ae 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -598,6 +598,9 @@ public:
/// calls to EmitTypeCheck can be skipped.
bool SanitizePerformTypeCheck;
+ /// \brief Sanitizer options to use for this function.
+ const SanitizerOptions *SanOpts;
+
/// In ARC, whether we should autorelease the return value.
bool AutoreleaseResult;
@@ -800,7 +803,7 @@ public:
protected:
CodeGenFunction& CGF;
-
+
public:
/// \brief Enter a new cleanup scope.
explicit RunCleanupsScope(CodeGenFunction &CGF)
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 04a08a92d8..9faba75433 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -77,8 +77,11 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
VMContext(M.getContext()),
NSConcreteGlobalBlock(0), NSConcreteStackBlock(0),
BlockObjectAssign(0), BlockObjectDispose(0),
- BlockDescriptorType(0), GenericBlockLiteralType(0) {
-
+ BlockDescriptorType(0), GenericBlockLiteralType(0),
+ SanitizerBlacklist(CGO.SanitizerBlacklistFile),
+ SanOpts(SanitizerBlacklist.isIn(M) ?
+ SanitizerOptions::Disabled : LangOpts.Sanitize) {
+
// Initialize the type cache.
llvm::LLVMContext &LLVMContext = M.getContext();
VoidTy = llvm::Type::getVoidTy(LLVMContext);
@@ -104,7 +107,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
createCUDARuntime();
// Enable TBAA unless it's suppressed. ThreadSanitizer needs TBAA even at O0.
- if (LangOpts.SanitizeThread ||
+ if (SanOpts.Thread ||
(!CodeGenOpts.RelaxedAliasing && CodeGenOpts.OptimizationLevel > 0))
TBAA = new CodeGenTBAA(Context, VMContext, CodeGenOpts, getLangOpts(),
ABI.getMangleContext());
@@ -603,8 +606,8 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
F->addFnAttr(llvm::Attribute::StackProtect);
else if (LangOpts.getStackProtector() == LangOptions::SSPReq)
F->addFnAttr(llvm::Attribute::StackProtectReq);
-
- if (LangOpts.SanitizeAddress) {
+
+ if (SanOpts.Address) {
// When AddressSanitizer is enabled, set AddressSafety attribute
// unless __attribute__((no_address_safety_analysis)) is used.
if (!D->hasAttr<NoAddressSafetyAnalysisAttr>())
@@ -1851,7 +1854,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
// If we are compiling with ASan, add metadata indicating dynamically
// initialized globals.
- if (LangOpts.SanitizeAddress && NeedsGlobalCtor) {
+ if (SanOpts.Address && NeedsGlobalCtor) {
llvm::Module &M = getModule();
llvm::NamedMDNode *DynamicInitializers =
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 00a98a6424..0f011205a7 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -30,6 +30,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/ValueHandle.h"
+#include "llvm/Transforms/Utils/BlackList.h"
namespace llvm {
class Module;
@@ -209,7 +210,7 @@ struct ARCEntrypoints {
/// a call will be immediately retain.
llvm::InlineAsm *retainAutoreleasedReturnValueMarker;
};
-
+
/// CodeGenModule - This class organizes the cross-function state that is used
/// while generating LLVM code.
class CodeGenModule : public CodeGenTypeCache {
@@ -364,9 +365,13 @@ class CodeGenModule : public CodeGenTypeCache {
struct {
int GlobalUniqueCount;
} Block;
-
+
GlobalDecl initializedGlobalDecl;
+ llvm::BlackList SanitizerBlacklist;
+
+ const SanitizerOptions &SanOpts;
+
/// @}
public:
CodeGenModule(ASTContext &C, const CodeGenOptions &CodeGenOpts,
@@ -889,6 +894,12 @@ public:
/// annotations are emitted during finalization of the LLVM code.
void AddGlobalAnnotations(const ValueDecl *D, llvm::GlobalValue *GV);
+ const llvm::BlackList &getSanitizerBlacklist() const {
+ return SanitizerBlacklist;
+ }
+
+ const SanitizerOptions &getSanOpts() const { return SanOpts; }
+
private:
llvm::GlobalValue *GetGlobalValue(StringRef Ref);
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index e810a22dce..2c02c423c1 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -1300,7 +1300,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
.Default(Unknown)) {
#define SANITIZER(NAME, ID) \
case ID: \
- Opts.Sanitize##ID = true; \
+ Opts.Sanitize.ID = true; \
break;
#include "clang/Basic/Sanitizers.def"
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index e8a1f8dd88..7901705fec 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -785,7 +785,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
Feature = Feature.substr(2, Feature.size() - 4);
return llvm::StringSwitch<bool>(Feature)
- .Case("address_sanitizer", LangOpts.SanitizeAddress)
+ .Case("address_sanitizer", LangOpts.Sanitize.Address)
.Case("attribute_analyzer_noreturn", true)
.Case("attribute_availability", true)
.Case("attribute_availability_with_message", true)
@@ -807,8 +807,8 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
.Case("cxx_exceptions", LangOpts.Exceptions)
.Case("cxx_rtti", LangOpts.RTTI)
.Case("enumerator_attributes", true)
- .Case("memory_sanitizer", LangOpts.SanitizeMemory)
- .Case("thread_sanitizer", LangOpts.SanitizeThread)
+ .Case("memory_sanitizer", LangOpts.Sanitize.Memory)
+ .Case("thread_sanitizer", LangOpts.Sanitize.Thread)
// Objective-C features
.Case("objc_arr", LangOpts.ObjCAutoRefCount) // FIXME: REMOVE?
.Case("objc_arc", LangOpts.ObjCAutoRefCount)
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 81d3cea7ba..1bafc2a4c5 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -3638,6 +3638,8 @@ bool ASTReader::ParseLanguageOptions(const RecordData &Record,
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
LangOpts.set##Name(static_cast<LangOptions::Type>(Record[Idx++]));
#include "clang/Basic/LangOptions.def"
+#define SANITIZER(NAME, ID) LangOpts.Sanitize.ID = Record[Idx++];
+#include "clang/Basic/Sanitizers.def"
ObjCRuntime::Kind runtimeKind = (ObjCRuntime::Kind) Record[Idx++];
VersionTuple runtimeVersion = ReadVersionTuple(Record, Idx);
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 36e1bb3a69..37577ce071 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -1048,6 +1048,8 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
Record.push_back(static_cast<unsigned>(LangOpts.get##Name()));
#include "clang/Basic/LangOptions.def"
+#define SANITIZER(NAME, ID) Record.push_back(LangOpts.Sanitize.ID);
+#include "clang/Basic/Sanitizers.def"
Record.push_back((unsigned) LangOpts.ObjCRuntime.getKind());
AddVersionTuple(LangOpts.ObjCRuntime.getVersion(), Record);
diff --git a/test/CodeGen/address-safety-attr.cpp b/test/CodeGen/address-safety-attr.cpp
index 5c9862d85b..6556e7bf1d 100644
--- a/test/CodeGen/address-safety-attr.cpp
+++ b/test/CodeGen/address-safety-attr.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -emit-llvm -o - %s -fsanitize=address | FileCheck -check-prefix ASAN %s
+// RUN: echo "src:%s" > %t
+// RUN: %clang_cc1 -emit-llvm -o - %s -fsanitize=address -fsanitize-blacklist=%t | FileCheck %s
// The address_safety attribute should be attached to functions
// when AddressSanitizer is enabled, unless no_address_safety_analysis attribute
diff --git a/test/CodeGen/ubsan-blacklist.c b/test/CodeGen/ubsan-blacklist.c
new file mode 100644
index 0000000000..1173b58e46
--- /dev/null
+++ b/test/CodeGen/ubsan-blacklist.c
@@ -0,0 +1,28 @@
+// Verify ubsan doesn't emit checks for blacklisted functions and files
+// RUN: echo "fun:hash" > %t-func.blacklist
+// RUN: echo "src:%s" > %t-file.blacklist
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow -emit-llvm %s -o - | FileCheck %s --check-prefix=DEFAULT
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow -fsanitize-blacklist=%t-func.blacklist -emit-llvm %s -o - | FileCheck %s --check-prefix=FUNC
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow -fsanitize-blacklist=%t-file.blacklist -emit-llvm %s -o - | FileCheck %s --check-prefix=FILE
+
+unsigned i;
+
+// DEFAULT: @hash
+// FUNC: @hash
+// FILE: @hash
+unsigned hash() {
+// DEFAULT: call void @__ubsan
+// FUNC-NOT: call void @__ubsan
+// FILE-NOT: call void @__ubsan
+ return i * 37;
+}
+
+// DEFAULT: @add
+// FUNC: @add
+// FILE: @add
+unsigned add() {
+// DEFAULT: call void @__ubsan
+// FUNC: call void @__ubsan
+// FILE-NOT: call void @__ubsan
+ return i + 1;
+}