Index: include/clang/CodeGen/BackendUtil.h =================================================================== --- include/clang/CodeGen/BackendUtil.h +++ include/clang/CodeGen/BackendUtil.h @@ -11,9 +11,11 @@ #define LLVM_CLANG_CODEGEN_BACKEND_UTIL_H #include "clang/Basic/LLVM.h" +#include namespace llvm { class Module; + class SpecialCaseList; } namespace clang { @@ -31,6 +33,9 @@ Backend_EmitObj ///< Emit native object files }; + std::unique_ptr + CreateSpecialCaseList(const CodeGenOptions &CGOpts); + void EmitBackendOutput(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts, const TargetOptions &TOpts, const LangOptions &LOpts, StringRef TDesc, llvm::Module *M, BackendAction Action, Index: include/clang/Driver/SanitizerArgs.h =================================================================== --- include/clang/Driver/SanitizerArgs.h +++ include/clang/Driver/SanitizerArgs.h @@ -9,6 +9,7 @@ #ifndef CLANG_LIB_DRIVER_SANITIZERARGS_H_ #define CLANG_LIB_DRIVER_SANITIZERARGS_H_ +#include "llvm/ADT/StringRef.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include @@ -47,7 +48,7 @@ }; unsigned Kind; - std::string BlacklistFile; + std::vector BlacklistFiles; int MsanTrackOrigins; bool AsanZeroBaseShadow; bool UbsanTrapOnError; @@ -83,6 +84,8 @@ private: void clear(); + void addBlacklistFile(const Driver &D, llvm::StringRef Path); + /// Parse a single value from a -fsanitize= or -fno-sanitize= value list. /// Returns OR of members of the \c SanitizeKind enumeration, or \c 0 /// if \p Value is not known. Index: include/clang/Frontend/CodeGenOptions.h =================================================================== --- include/clang/Frontend/CodeGenOptions.h +++ include/clang/Frontend/CodeGenOptions.h @@ -134,8 +134,8 @@ /// The name of the relocation model to use. std::string RelocationModel; - /// Path to blacklist file for sanitizers. - std::string SanitizerBlacklistFile; + /// Paths to blacklist files for sanitizers. + std::vector SanitizerBlacklistFiles; /// If not an empty string, trap intrinsics are lowered to calls to this /// function instead of to trap instructions. Index: lib/CodeGen/BackendUtil.cpp =================================================================== --- lib/CodeGen/BackendUtil.cpp +++ lib/CodeGen/BackendUtil.cpp @@ -18,6 +18,7 @@ #include "llvm/Bitcode/BitcodeWriterPass.h" #include "llvm/CodeGen/RegAllocRegistry.h" #include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/Module.h" @@ -27,6 +28,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/SpecialCaseList.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" @@ -214,7 +216,7 @@ const PassManagerBuilderWrapper &BuilderWrapper = static_cast(Builder); const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); - PM.add(createDataFlowSanitizerPass(CGOpts.SanitizerBlacklistFile)); + PM.add(createDataFlowSanitizerPass(CreateSpecialCaseList(CGOpts))); } void EmitAssemblyHelper::CreatePasses() { @@ -587,6 +589,18 @@ } } +std::unique_ptr clang::CreateSpecialCaseList(const CodeGenOptions &CGOpts) { + auto SCL = llvm::make_unique(); + for (const auto &Path : CGOpts.SanitizerBlacklistFiles) { + std::string Error; + if (!SCL->loadFromFile(Path, Error)) { + report_fatal_error(Error); + } + } + + return std::move(SCL); +} + void clang::EmitBackendOutput(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts, const clang::TargetOptions &TOpts, Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -38,6 +38,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Version.h" +#include "clang/CodeGen/BackendUtil.h" #include "clang/Frontend/CodeGenOptions.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/APSInt.h" @@ -87,8 +88,7 @@ NSConcreteStackBlock(nullptr), BlockObjectAssign(nullptr), BlockObjectDispose(nullptr), BlockDescriptorType(nullptr), GenericBlockLiteralType(nullptr), LifetimeStartFn(nullptr), - LifetimeEndFn(nullptr), SanitizerBL(llvm::SpecialCaseList::createOrDie( - CGO.SanitizerBlacklistFile)) { + LifetimeEndFn(nullptr), SanitizerBL(CreateSpecialCaseList(CGO)) { // Initialize the type cache. llvm::LLVMContext &LLVMContext = M.getContext(); Index: lib/CodeGen/SanitizerBlacklist.h =================================================================== --- lib/CodeGen/SanitizerBlacklist.h +++ lib/CodeGen/SanitizerBlacklist.h @@ -32,7 +32,8 @@ std::unique_ptr SCL; public: - SanitizerBlacklist(llvm::SpecialCaseList *SCL) : SCL(SCL) {} + SanitizerBlacklist(std::unique_ptr SCL) + : SCL(std::move(SCL)) {} bool isIn(const llvm::Module &M, const StringRef Category = StringRef()) const; bool isIn(const llvm::Function &F) const; Index: lib/Driver/SanitizerArgs.cpp =================================================================== --- lib/Driver/SanitizerArgs.cpp +++ lib/Driver/SanitizerArgs.cpp @@ -23,7 +23,7 @@ void SanitizerArgs::clear() { Kind = 0; - BlacklistFile = ""; + BlacklistFiles.clear(); MsanTrackOrigins = 0; AsanZeroBaseShadow = false; UbsanTrapOnError = false; @@ -113,31 +113,23 @@ // -f(-no)sanitize=leak should change whether leak detection is enabled by // default in ASan? - // Parse -f(no-)sanitize-blacklist options. - if (Arg *BLArg = Args.getLastArg(options::OPT_fsanitize_blacklist, - options::OPT_fno_sanitize_blacklist)) { - if (BLArg->getOption().matches(options::OPT_fsanitize_blacklist)) { - std::string BLPath = BLArg->getValue(); - if (llvm::sys::fs::exists(BLPath)) { - // Validate the blacklist format. - std::string BLError; - std::unique_ptr SCL( - llvm::SpecialCaseList::create(BLPath, BLError)); - if (!SCL.get()) - D.Diag(diag::err_drv_malformed_sanitizer_blacklist) << BLError; - else - BlacklistFile = BLPath; - } else { - D.Diag(diag::err_drv_no_such_file) << BLPath; - } - } - } else { - // If no -fsanitize-blacklist option is specified, try to look up for - // blacklist in the resource directory. + // If -fno-sanitize-blacklist option is not specified, try to look up the + // blacklist in the resource directory. + if (!Args.hasArg(options::OPT_fno_sanitize_blacklist)) { std::string BLPath; if (getDefaultBlacklistForKind(D, Kind, BLPath) && llvm::sys::fs::exists(BLPath)) - BlacklistFile = BLPath; + addBlacklistFile(D, BLPath); + } + + // Parse -fsanitize-blacklist options. + for (auto Arg : Args.filtered(options::OPT_fsanitize_blacklist)) { + Arg->claim(); + if (llvm::sys::fs::exists(Arg->getValue())) { + addBlacklistFile(D, Arg->getValue()); + } else { + D.Diag(diag::err_drv_no_such_file) << Arg->getValue(); + } } // Parse -f[no-]sanitize-memory-track-origins[=level] options. @@ -170,6 +162,16 @@ } } +void SanitizerArgs::addBlacklistFile(const Driver &D, StringRef BLPath) { + // Validate the blacklist format. + std::string BLError; + llvm::SpecialCaseList SCL; + if (!SCL.loadFromFile(BLPath, BLError)) + D.Diag(diag::err_drv_malformed_sanitizer_blacklist) << BLError; + else + BlacklistFiles.push_back(BLPath); +} + void SanitizerArgs::addArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const { if (!Kind) @@ -181,9 +183,9 @@ #include "clang/Basic/Sanitizers.def" SanitizeOpt.pop_back(); CmdArgs.push_back(Args.MakeArgString(SanitizeOpt)); - if (!BlacklistFile.empty()) { + for (const auto &File : BlacklistFiles) { SmallString<64> BlacklistOpt("-fsanitize-blacklist="); - BlacklistOpt += BlacklistFile; + BlacklistOpt += File; CmdArgs.push_back(Args.MakeArgString(BlacklistOpt)); } Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -481,7 +481,7 @@ Opts.CompressDebugSections = Args.hasArg(OPT_compress_debug_sections); Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir); Opts.LinkBitcodeFile = Args.getLastArgValue(OPT_mlink_bitcode_file); - Opts.SanitizerBlacklistFile = Args.getLastArgValue(OPT_fsanitize_blacklist); + Opts.SanitizerBlacklistFiles = Args.getAllArgValues(OPT_fsanitize_blacklist); Opts.SanitizeMemoryTrackOrigins = getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags); Opts.SanitizeUndefinedTrapOnError = Index: test/Driver/fsanitize-blacklist.c =================================================================== --- test/Driver/fsanitize-blacklist.c +++ test/Driver/fsanitize-blacklist.c @@ -13,10 +13,6 @@ // RUN: %clang -fsanitize-blacklist=%t.good %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-SANITIZE // CHECK-NO-SANITIZE-NOT: -fsanitize-blacklist -// Flag -fno-sanitize-blacklist wins if it is specified later. -// RUN: %clang -fsanitize=address -fsanitize-blacklist=%t.good -fno-sanitize-blacklist %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-BLACKLIST -// CHECK-NO-BLACKLIST-NOT: -fsanitize-blacklist - // Driver barks on unexisting blacklist files. // RUN: %clang -fno-sanitize-blacklist -fsanitize-blacklist=unexisting.txt %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-SUCH-FILE // CHECK-NO-SUCH-FILE: error: no such file or directory: 'unexisting.txt'