vsk updated this revision to Diff 114882.
vsk added a comment.

- Rebase to ToT.


https://reviews.llvm.org/D32842

Files:
  include/clang/AST/ASTContext.h
  include/clang/Basic/LangOptions.h
  include/clang/Basic/SanitizerBlacklist.h
  include/clang/Driver/SanitizerArgs.h
  lib/AST/ASTContext.cpp
  lib/AST/Decl.cpp
  lib/Basic/LangOptions.cpp
  lib/Basic/SanitizerBlacklist.cpp
  lib/CodeGen/CGClass.cpp
  lib/CodeGen/CGDeclCXX.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/CodeGen/CodeGenModule.cpp
  lib/CodeGen/CodeGenModule.h
  lib/Driver/SanitizerArgs.cpp
  lib/Frontend/CompilerInvocation.cpp
  test/CodeGen/address-safety-attr.cpp
  test/CodeGen/asan-globals.cpp
  test/CodeGen/sanitize-address-field-padding.cpp
  test/CodeGen/sanitize-init-order.cpp
  test/CodeGen/sanitize-thread-attr.cpp
  test/CodeGen/ubsan-blacklist.c
  test/CodeGen/ubsan-type-blacklist.cpp
  test/CodeGenCXX/cfi-blacklist.cpp
  test/Driver/Inputs/resource_dir/cfi_blacklist.txt
  test/Driver/fsanitize-blacklist.c
  test/Frontend/sanitizer-blacklists.c

Index: test/Frontend/sanitizer-blacklists.c
===================================================================
--- /dev/null
+++ test/Frontend/sanitizer-blacklists.c
@@ -0,0 +1,32 @@
+// Blacklisting a function for ASan shouldn't affect TSan instrumentation.
+//
+// RUN: echo "fun:foo" > %t.blacklist
+//
+// RUN: %clang_cc1 -fsanitize=address,thread -triple x86_64-apple-darwin10 \
+// RUN:   -fsanitize-blacklist=address:%t.blacklist \
+// RUN:   -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=COMMON,CHECK1
+
+// Check that we can blacklist a function for multiple sanitizers using
+// separate blacklists.
+//
+// RUN: %clang_cc1 -fsanitize=address,thread -triple x86_64-apple-darwin10 \
+// RUN:   -fsanitize-blacklist=address:%t.blacklist \
+// RUN:   -fsanitize-blacklist=thread:%t.blacklist \
+// RUN:   -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=COMMON,CHECK2
+
+// Check that we can blacklist a function for multiple sanitizers using the
+// same blacklist.
+//
+// RUN: %clang_cc1 -fsanitize=address,thread -triple x86_64-apple-darwin10 \
+// RUN:   -fsanitize-blacklist=address,thread:%t.blacklist \
+// RUN:   -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=COMMON,CHECK2
+
+// COMMON: define void @foo() [[FOO_ATTR:#[0-9]+]]
+void foo() {}
+
+// CHECK1: attributes [[FOO_ATTR]] = { {{[^}]*}} sanitize_thread
+// CHECK1-NOT: sanitize_address
+
+// CHECK2: attributes [[FOO_ATTR]]
+// CHECK2-NOT: sanitize_address
+// CHECK2-NOT: sanitize_thread
Index: test/Driver/fsanitize-blacklist.c
===================================================================
--- test/Driver/fsanitize-blacklist.c
+++ test/Driver/fsanitize-blacklist.c
@@ -20,15 +20,26 @@
 // CHECK-BLACKLIST2: -fdepfile-entry={{.*}}.good" "-fdepfile-entry={{.*}}.second
 
 // Check that the default blacklist is not added as an extra dependency.
-// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-BLACKLIST --implicit-check-not=fdepfile-entry
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -resource-dir=%S/Inputs/resource_dir %s -### &> %t.cc1_asan
+// RUN: FileCheck %s --check-prefix=CHECK-DEFAULT-BLACKLIST --implicit-check-not=fdepfile-entry -input-file %t.cc1_asan
 // CHECK-DEFAULT-BLACKLIST: -fsanitize-blacklist={{.*}}asan_blacklist.txt
 
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=integer -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-UBSAN-BLACKLIST --implicit-check-not=fdepfile-entry
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=nullability -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-UBSAN-BLACKLIST --implicit-check-not=fdepfile-entry
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-UBSAN-BLACKLIST --implicit-check-not=fdepfile-entry
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=alignment -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-UBSAN-BLACKLIST --implicit-check-not=fdepfile-entry
 // CHECK-DEFAULT-UBSAN-BLACKLIST: -fsanitize-blacklist={{.*}}ubsan_blacklist.txt
 
+// Check that default blacklists are not added unless the matching sanitizer is
+// enabled, even if the blacklist exists.
+// RUN: FileCheck %s --implicit-check-not=cfi_blacklist.txt -input-file %t.cc1_asan
+
+// Check that we can add multiple default blacklists if the matching sanitizers
+// are enabled.
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address,cfi -flto -fvisibility=hidden -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=MULTIPLE-DEFAULT-BLACKLISTS
+// MULTIPLE-DEFAULT-BLACKLISTS-DAG: -fsanitize-blacklist={{.*}}asan_blacklist.txt
+// MULTIPLE-DEFAULT-BLACKLISTS-DAG: -fsanitize-blacklist={{.*}}cfi_blacklist.txt
+
 // Ignore -fsanitize-blacklist flag if there is no -fsanitize flag.
 // RUN: %clang -target x86_64-linux-gnu -fsanitize-blacklist=%t.good %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-SANITIZE --check-prefix=DELIMITERS
 // CHECK-NO-SANITIZE-NOT: -fsanitize-blacklist
Index: test/CodeGenCXX/cfi-blacklist.cpp
===================================================================
--- test/CodeGenCXX/cfi-blacklist.cpp
+++ test/CodeGenCXX/cfi-blacklist.cpp
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOBL %s
 // RUN: echo "type:std::*" > %t.txt
-// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=cfi-vcall:%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
 
 struct S1 {
   virtual void f();
Index: test/CodeGen/ubsan-type-blacklist.cpp
===================================================================
--- test/CodeGen/ubsan-type-blacklist.cpp
+++ test/CodeGen/ubsan-type-blacklist.cpp
@@ -1,7 +1,7 @@
 // Verify ubsan vptr does not check down-casts on blacklisted types.
 // RUN: echo "type:_ZTI3Foo" > %t-type.blacklist
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-recover=vptr -emit-llvm %s -o - | FileCheck %s --check-prefix=DEFAULT
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-recover=vptr -fsanitize-blacklist=%t-type.blacklist -emit-llvm %s -o - | FileCheck %s --check-prefix=TYPE
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-recover=vptr -fsanitize-blacklist=vptr:%t-type.blacklist -emit-llvm %s -o - | FileCheck %s --check-prefix=TYPE
 
 class Bar {
 public:
Index: test/CodeGen/ubsan-blacklist.c
===================================================================
--- test/CodeGen/ubsan-blacklist.c
+++ test/CodeGen/ubsan-blacklist.c
@@ -2,8 +2,8 @@
 // RUN: echo "fun:hash" > %t-func.blacklist
 // RUN: echo "src:%s" | sed -e 's/\\/\\\\/g' > %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
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow -fsanitize-blacklist=unsigned-integer-overflow:%t-func.blacklist -emit-llvm %s -o - | FileCheck %s --check-prefix=FUNC
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow -fsanitize-blacklist=unsigned-integer-overflow:%t-file.blacklist -emit-llvm %s -o - | FileCheck %s --check-prefix=FILE
 
 unsigned i;
 
Index: test/CodeGen/sanitize-thread-attr.cpp
===================================================================
--- test/CodeGen/sanitize-thread-attr.cpp
+++ test/CodeGen/sanitize-thread-attr.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck -check-prefix=WITHOUT %s
 // RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=thread | FileCheck -check-prefix=TSAN %s
 // RUN: echo "src:%s" | sed -e 's/\\/\\\\/g' > %t
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=thread -fsanitize-blacklist=%t | FileCheck -check-prefix=BL %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=thread -fsanitize-blacklist=thread:%t | FileCheck -check-prefix=BL %s
 
 // The sanitize_thread attribute should be attached to functions
 // when ThreadSanitizer is enabled, unless no_sanitize_thread attribute
Index: test/CodeGen/sanitize-init-order.cpp
===================================================================
--- test/CodeGen/sanitize-init-order.cpp
+++ test/CodeGen/sanitize-init-order.cpp
@@ -4,8 +4,8 @@
 // RUN: echo "src:%s=init" | sed -e 's/\\/\\\\/g' > %t-file.blacklist
 // RUN: echo "type:PODWithCtorAndDtor=init" > %t-type.blacklist
 // RUN: echo "type:NS::PODWithCtor=init" >> %t-type.blacklist
-// RUN: %clang_cc1 -fsanitize=address -fsanitize-blacklist=%t-file.blacklist -emit-llvm -o - %s | FileCheck %s --check-prefix=BLACKLIST
-// RUN: %clang_cc1 -fsanitize=address -fsanitize-blacklist=%t-type.blacklist -emit-llvm -o - %s | FileCheck %s --check-prefix=BLACKLIST
+// RUN: %clang_cc1 -fsanitize=address -fsanitize-blacklist=address:%t-file.blacklist -emit-llvm -o - %s | FileCheck %s --check-prefix=BLACKLIST
+// RUN: %clang_cc1 -fsanitize=address -fsanitize-blacklist=address:%t-type.blacklist -emit-llvm -o - %s | FileCheck %s --check-prefix=BLACKLIST
 
 struct PODStruct {
   int x;
Index: test/CodeGen/sanitize-address-field-padding.cpp
===================================================================
--- test/CodeGen/sanitize-address-field-padding.cpp
+++ test/CodeGen/sanitize-address-field-padding.cpp
@@ -1,9 +1,9 @@
 // Test -fsanitize-address-field-padding
 // RUN: echo 'type:SomeNamespace::BlacklistedByName=field-padding' > %t.type.blacklist
 // RUN: echo 'src:*sanitize-address-field-padding.cpp=field-padding' > %t.file.blacklist
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsanitize=address -fsanitize-address-field-padding=1 -fsanitize-blacklist=%t.type.blacklist -Rsanitize-address -emit-llvm -o - %s 2>&1 | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsanitize=address -fsanitize-address-field-padding=1 -fsanitize-blacklist=%t.type.blacklist -Rsanitize-address -emit-llvm -o - %s -O1 -mconstructor-aliases 2>&1 | FileCheck %s --check-prefix=WITH_CTOR_ALIASES
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsanitize=address -fsanitize-address-field-padding=1 -fsanitize-blacklist=%t.file.blacklist -Rsanitize-address -emit-llvm -o - %s 2>&1 | FileCheck %s --check-prefix=FILE_BLACKLIST
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsanitize=address -fsanitize-address-field-padding=1 -fsanitize-blacklist=address:%t.type.blacklist -Rsanitize-address -emit-llvm -o - %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsanitize=address -fsanitize-address-field-padding=1 -fsanitize-blacklist=address:%t.type.blacklist -Rsanitize-address -emit-llvm -o - %s -O1 -mconstructor-aliases 2>&1 | FileCheck %s --check-prefix=WITH_CTOR_ALIASES
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsanitize=address -fsanitize-address-field-padding=1 -fsanitize-blacklist=address:%t.file.blacklist -Rsanitize-address -emit-llvm -o - %s 2>&1 | FileCheck %s --check-prefix=FILE_BLACKLIST
 // RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - %s 2>&1 | FileCheck %s --check-prefix=NO_PADDING
 // Try to emulate -save-temps option and make sure -disable-llvm-passes will not run sanitize instrumentation.
 // RUN: %clang_cc1 -fsanitize=address -emit-llvm -disable-llvm-passes -o - %s | %clang_cc1 -fsanitize=address -emit-llvm -o - -x ir | FileCheck %s --check-prefix=NO_PADDING
Index: test/CodeGen/asan-globals.cpp
===================================================================
--- test/CodeGen/asan-globals.cpp
+++ test/CodeGen/asan-globals.cpp
@@ -1,9 +1,9 @@
 // RUN: echo "int extra_global;" > %t.extra-source.cpp
 // RUN: echo "global:*blacklisted_global*" > %t.blacklist
-// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=%t.blacklist -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=address:%t.blacklist -emit-llvm -o - %s | FileCheck %s
 // The blacklist file uses regexps, so Windows path backslashes.
 // RUN: echo "src:%s" | sed -e 's/\\/\\\\/g' > %t.blacklist-src
-// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=%t.blacklist-src -emit-llvm -o - %s | FileCheck %s --check-prefix=BLACKLIST-SRC
+// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=address:%t.blacklist-src -emit-llvm -o - %s | FileCheck %s --check-prefix=BLACKLIST-SRC
 
 int global;
 int dyn_init_global = global;
Index: test/CodeGen/address-safety-attr.cpp
===================================================================
--- test/CodeGen/address-safety-attr.cpp
+++ test/CodeGen/address-safety-attr.cpp
@@ -7,12 +7,12 @@
 // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin -disable-O0-optnone -emit-llvm -o - %s -include %t.extra-source.cpp -fsanitize=address | FileCheck -check-prefix=ASAN %s
 
 // RUN: echo "fun:*BlacklistedFunction*" > %t.func.blacklist
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin -disable-O0-optnone -emit-llvm -o - %s -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=%t.func.blacklist | FileCheck -check-prefix=BLFUNC %s
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin -disable-O0-optnone -emit-llvm -o - %s -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=address:%t.func.blacklist | FileCheck -check-prefix=BLFUNC %s
 
 // The blacklist file uses regexps, so escape backslashes, which are common in
 // Windows paths.
 // RUN: echo "src:%s" | sed -e 's/\\/\\\\/g' > %t.file.blacklist
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin -disable-O0-optnone -emit-llvm -o - %s -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=%t.file.blacklist | FileCheck -check-prefix=BLFILE %s
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin -disable-O0-optnone -emit-llvm -o - %s -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=address:%t.file.blacklist | FileCheck -check-prefix=BLFILE %s
 
 // The sanitize_address attribute should be attached to functions
 // when AddressSanitizer is enabled, unless no_sanitize_address attribute
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -15,6 +15,7 @@
 #include "clang/Config/config.h"
 #include "clang/Driver/DriverDiagnostic.h"
 #include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
 #include "clang/Driver/Util.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "clang/Frontend/LangStandard.h"
@@ -392,6 +393,23 @@
   }
 }
 
+static void
+parseSanitizerBlacklists(StringRef FlagName, LangOptions &Opts,
+                         const std::vector<std::string> &BlacklistArgs,
+                         DiagnosticsEngine &Diags) {
+  for (const std::string &BA : BlacklistArgs) {
+    SanitizerMask Kind;
+    std::string Path;
+    if (!SanitizerArgs::decodeBlacklistArg(BA, Kind, Path)) {
+      Diags.Report(diag::err_drv_invalid_value) << FlagName << BA;
+      continue;
+    }
+    Opts.SanitizerBlacklistFiles.emplace_back(std::move(Path));
+    Opts.SanitizerBlacklists.emplace_back(Kind,
+                                          Opts.SanitizerBlacklistFiles.back());
+  }
+}
+
 // Set the profile kind for fprofile-instrument.
 static void setPGOInstrumentor(CodeGenOptions &Opts, ArgList &Args,
                                DiagnosticsEngine &Diags) {
@@ -2453,7 +2471,9 @@
   // -fsanitize-address-field-padding=N has to be a LangOpt, parse it here.
   Opts.SanitizeAddressFieldPadding =
       getLastArgIntValue(Args, OPT_fsanitize_address_field_padding, 0, Diags);
-  Opts.SanitizerBlacklistFiles = Args.getAllArgValues(OPT_fsanitize_blacklist);
+  parseSanitizerBlacklists("-fsanitize-blacklist", Opts,
+                           Args.getAllArgValues(OPT_fsanitize_blacklist),
+                           Diags);
 
   // -fxray-instrument
   Opts.XRayInstrument =
Index: lib/Driver/SanitizerArgs.cpp
===================================================================
--- lib/Driver/SanitizerArgs.cpp
+++ lib/Driver/SanitizerArgs.cpp
@@ -89,31 +89,34 @@
 
 /// Produce a string containing comma-separated names of sanitizers in \p
 /// Sanitizers set.
-static std::string toString(const clang::SanitizerSet &Sanitizers);
-
-static bool getDefaultBlacklist(const Driver &D, SanitizerMask Kinds,
-                                std::string &BLPath) {
-  const char *BlacklistFile = nullptr;
-  if (Kinds & Address)
-    BlacklistFile = "asan_blacklist.txt";
-  else if (Kinds & Memory)
-    BlacklistFile = "msan_blacklist.txt";
-  else if (Kinds & Thread)
-    BlacklistFile = "tsan_blacklist.txt";
-  else if (Kinds & DataFlow)
-    BlacklistFile = "dfsan_abilist.txt";
-  else if (Kinds & CFI)
-    BlacklistFile = "cfi_blacklist.txt";
-  else if (Kinds & (Undefined | Integer | Nullability))
-    BlacklistFile = "ubsan_blacklist.txt";
-
-  if (BlacklistFile) {
+static std::string toString(SanitizerMask Kinds);
+static std::string toString(SanitizerSet Sanitizers);
+
+/// Given the name of a sanitizer, produce the corresponding ordinal value.
+static SanitizerMask toMask(StringRef SanitizerFlag);
+
+void SanitizerArgs::collectDefaultBlacklists(const Driver &D,
+                                             SanitizerMask Kinds) {
+  const std::pair<SanitizerMask, const char *> Blacklists[] = {
+      {Address, "asan_blacklist.txt"},
+      {Memory, "msan_blacklist.txt"},
+      {Thread, "tsan_blacklist.txt"},
+      {DataFlow, "dfsan_abilist.txt"},
+      {CFI, "cfi_blacklist.txt"},
+      {Undefined | Nullability | Integer, "ubsan_blacklist.txt"}};
+
+  for (const auto &BL : Blacklists) {
+    if (!(BL.first & Kinds))
+      continue;
+
     clang::SmallString<64> Path(D.ResourceDir);
-    llvm::sys::path::append(Path, BlacklistFile);
-    BLPath = Path.str();
-    return true;
+    llvm::sys::path::append(Path, BL.second);
+    if (llvm::sys::fs::exists(Path)) {
+      SanitizerBlacklistFiles.push_back(Path.str());
+      SanitizerBlacklists.emplace_back(BL.first,
+                                       SanitizerBlacklistFiles.back());
+    }
   }
-  return false;
 }
 
 /// Sets group bits for every group that has at least one representative already
@@ -437,34 +440,32 @@
   TrappingKinds &= Kinds;
 
   // Setup blacklist files.
-  // Add default blacklist from resource directory.
-  {
-    std::string BLPath;
-    if (getDefaultBlacklist(D, Kinds, BLPath) && llvm::sys::fs::exists(BLPath))
-      BlacklistFiles.push_back(BLPath);
-  }
+  collectDefaultBlacklists(D, Kinds);
+
   // Parse -f(no-)sanitize-blacklist options.
   for (const auto *Arg : Args) {
     if (Arg->getOption().matches(options::OPT_fsanitize_blacklist)) {
       Arg->claim();
       std::string BLPath = Arg->getValue();
       if (llvm::sys::fs::exists(BLPath)) {
-        BlacklistFiles.push_back(BLPath);
-        ExtraDeps.push_back(BLPath);
+        SanitizerBlacklistFiles.push_back(BLPath);
+        SanitizerBlacklists.emplace_back(All, SanitizerBlacklistFiles.back());
+        ExtraDeps.emplace_back(SanitizerBlacklistFiles.back());
       } else
         D.Diag(clang::diag::err_drv_no_such_file) << BLPath;
 
     } else if (Arg->getOption().matches(options::OPT_fno_sanitize_blacklist)) {
       Arg->claim();
-      BlacklistFiles.clear();
+      SanitizerBlacklistFiles.clear();
+      SanitizerBlacklists.clear();
       ExtraDeps.clear();
     }
   }
   // Validate blacklists format.
   {
     std::string BLError;
     std::unique_ptr<llvm::SpecialCaseList> SCL(
-        llvm::SpecialCaseList::create(BlacklistFiles, BLError));
+        llvm::SpecialCaseList::create(SanitizerBlacklistFiles, BLError));
     if (!SCL.get())
       D.Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError;
   }
@@ -665,18 +666,34 @@
   TrapSanitizers.Mask |= TrappingKinds;
 }
 
-static std::string toString(const clang::SanitizerSet &Sanitizers) {
+static std::string toString(SanitizerMask Kinds) {
   std::string Res;
 #define SANITIZER(NAME, ID)                                                    \
-  if (Sanitizers.has(ID)) {                                                    \
+  if (Kinds & ID) {                                                            \
     if (!Res.empty())                                                          \
       Res += ",";                                                              \
     Res += NAME;                                                               \
   }
+
 #include "clang/Basic/Sanitizers.def"
+#undef SANITIZER
   return Res;
 }
 
+static std::string toString(SanitizerSet Sanitizers) {
+  return toString(Sanitizers.Mask);
+}
+
+static SanitizerMask toMask(StringRef SanitizerFlag) {
+#define SANITIZER(NAME, ID)                                                    \
+  if (SanitizerFlag == NAME)                                                   \
+    return ID;
+
+#include "clang/Basic/Sanitizers.def"
+#undef SANITIZER
+  return SanitizerMask();
+}
+
 static void addIncludeLinkerOption(const ToolChain &TC,
                                    const llvm::opt::ArgList &Args,
                                    llvm::opt::ArgStringList &CmdArgs,
@@ -691,6 +708,34 @@
   CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
 }
 
+std::string SanitizerArgs::encodeBlacklistArg(const SanitizerBlacklist &SB) {
+  return toString(SB.Sanitizers) + ":" + SB.Path.str();
+}
+
+bool SanitizerArgs::decodeBlacklistArg(const std::string &Arg,
+                                       SanitizerMask &Kinds,
+                                       std::string &Path) {
+  StringRef LHS, RHS;
+  std::tie(LHS, RHS) = StringRef(Arg).split(':');
+  if (LHS.empty() || RHS.empty())
+    return false;
+
+  SmallVector<StringRef, 4> Sanitizers;
+  LHS.split(Sanitizers, ',', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+  if (Sanitizers.empty())
+    return false;
+
+  for (StringRef Sanitizer : Sanitizers) {
+    if (SanitizerMask Kind = toMask(Sanitizer))
+      Kinds |= Kind;
+    else
+      return false;
+  }
+
+  Path = RHS.str();
+  return true;
+}
+
 void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
                             llvm::opt::ArgStringList &CmdArgs,
                             types::ID InputType) const {
@@ -758,9 +803,9 @@
     CmdArgs.push_back(
         Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
 
-  for (const auto &BLPath : BlacklistFiles) {
+  for (const auto &SB : SanitizerBlacklists) {
     SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
-    BlacklistOpt += BLPath;
+    BlacklistOpt += encodeBlacklistArg(SB);
     CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
   }
   for (const auto &Dep : ExtraDeps) {
Index: lib/CodeGen/CodeGenModule.h
===================================================================
--- lib/CodeGen/CodeGenModule.h
+++ lib/CodeGen/CodeGenModule.h
@@ -1106,7 +1106,8 @@
   /// annotations are emitted during finalization of the LLVM code.
   void AddGlobalAnnotations(const ValueDecl *D, llvm::GlobalValue *GV);
 
-  bool isInSanitizerBlacklist(llvm::Function *Fn, SourceLocation Loc) const;
+  bool isInSanitizerBlacklist(SanitizerMask Kind, llvm::Function *Fn,
+                              SourceLocation Loc) const;
 
   bool isInSanitizerBlacklist(llvm::GlobalVariable *GV, SourceLocation Loc,
                               QualType Ty,
Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -1538,35 +1538,37 @@
     Annotations.push_back(EmitAnnotateAttr(GV, I, D->getLocation()));
 }
 
-bool CodeGenModule::isInSanitizerBlacklist(llvm::Function *Fn,
+bool CodeGenModule::isInSanitizerBlacklist(SanitizerMask Kind,
+                                           llvm::Function *Fn,
                                            SourceLocation Loc) const {
   const auto &SanitizerBL = getContext().getSanitizerBlacklist();
   // Blacklist by function name.
-  if (SanitizerBL.isBlacklistedFunction(Fn->getName()))
+  if (SanitizerBL.isBlacklistedFunction(Fn->getName(), Kind))
     return true;
   // Blacklist by location.
   if (Loc.isValid())
-    return SanitizerBL.isBlacklistedLocation(Loc);
+    return SanitizerBL.isBlacklistedLocation(Loc, Kind);
   // If location is unknown, this may be a compiler-generated function. Assume
   // it's located in the main file.
   auto &SM = Context.getSourceManager();
   if (const auto *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
-    return SanitizerBL.isBlacklistedFile(MainFile->getName());
+    return SanitizerBL.isBlacklistedFile(MainFile->getName(), Kind);
   }
   return false;
 }
 
 bool CodeGenModule::isInSanitizerBlacklist(llvm::GlobalVariable *GV,
                                            SourceLocation Loc, QualType Ty,
                                            StringRef Category) const {
   // For now globals can be blacklisted only in ASan and KASan.
-  if (!LangOpts.Sanitize.hasOneOf(
-          SanitizerKind::Address | SanitizerKind::KernelAddress))
+  SanitizerMask ASanMask =
+      SanitizerKind::Address | SanitizerKind::KernelAddress;
+  if (!LangOpts.Sanitize.hasOneOf(ASanMask))
     return false;
   const auto &SanitizerBL = getContext().getSanitizerBlacklist();
-  if (SanitizerBL.isBlacklistedGlobal(GV->getName(), Category))
+  if (SanitizerBL.isBlacklistedGlobal(GV->getName(), ASanMask, Category))
     return true;
-  if (SanitizerBL.isBlacklistedLocation(Loc, Category))
+  if (SanitizerBL.isBlacklistedLocation(Loc, ASanMask, Category))
     return true;
   // Check global type.
   if (!Ty.isNull()) {
@@ -1578,7 +1580,7 @@
     // We allow to blacklist only record types (classes, structs etc.)
     if (Ty->isRecordType()) {
       std::string TypeStr = Ty.getAsString(getContext().getPrintingPolicy());
-      if (SanitizerBL.isBlacklistedType(TypeStr, Category))
+      if (SanitizerBL.isBlacklistedType(TypeStr, ASanMask, Category))
         return true;
     }
   }
Index: lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -767,8 +767,19 @@
   CurFnInfo = &FnInfo;
   assert(CurFn->isDeclaration() && "Function already has body?");
 
-  if (CGM.isInSanitizerBlacklist(Fn, Loc))
-    SanOpts.clear();
+  // If this function has been blacklisted for any of the enabled sanitizers,
+  // disable the sanitizer for the function.
+  do {
+#define SANITIZER(NAME, ID)                                                    \
+  if (SanOpts.empty())                                                         \
+    break;                                                                     \
+  if (SanOpts.has(SanitizerKind::ID))                                          \
+    if (CGM.isInSanitizerBlacklist(SanitizerKind::ID, Fn, Loc))                \
+      SanOpts.set(SanitizerKind::ID, false);
+
+#include "clang/Basic/Sanitizers.def"
+#undef SANITIZER
+  } while (0);
 
   if (D) {
     // Apply the no_sanitize* attributes to SanOpts.
Index: lib/CodeGen/CGExpr.cpp
===================================================================
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -725,7 +725,7 @@
 
     // Blacklist based on the mangled type.
     if (!CGM.getContext().getSanitizerBlacklist().isBlacklistedType(
-            Out.str())) {
+            Out.str(), SanitizerKind::Vptr)) {
       llvm::hash_code TypeHash = hash_value(Out.str());
 
       // Load the vptr, and compute hash_16_bytes(TypeHash, vptr).
Index: lib/CodeGen/CGDeclCXX.cpp
===================================================================
--- lib/CodeGen/CGDeclCXX.cpp
+++ lib/CodeGen/CGDeclCXX.cpp
@@ -316,17 +316,23 @@
   if (!getLangOpts().Exceptions)
     Fn->setDoesNotThrow();
 
-  if (!isInSanitizerBlacklist(Fn, Loc)) {
-    if (getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address |
-                                        SanitizerKind::KernelAddress))
+  SanitizerMask ASanMask =
+      SanitizerKind::Address | SanitizerKind::KernelAddress;
+  if (getLangOpts().Sanitize.hasOneOf(ASanMask))
+    if (!isInSanitizerBlacklist(ASanMask, Fn, Loc))
       Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
-    if (getLangOpts().Sanitize.has(SanitizerKind::Thread))
+
+  if (getLangOpts().Sanitize.has(SanitizerKind::Thread))
+    if (!isInSanitizerBlacklist(SanitizerKind::Thread, Fn, Loc))
       Fn->addFnAttr(llvm::Attribute::SanitizeThread);
-    if (getLangOpts().Sanitize.has(SanitizerKind::Memory))
+
+  if (getLangOpts().Sanitize.has(SanitizerKind::Memory))
+    if (!isInSanitizerBlacklist(SanitizerKind::Memory, Fn, Loc))
       Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
-    if (getLangOpts().Sanitize.has(SanitizerKind::SafeStack))
+
+  if (getLangOpts().Sanitize.has(SanitizerKind::SafeStack))
+    if (!isInSanitizerBlacklist(SanitizerKind::SafeStack, Fn, Loc))
       Fn->addFnAttr(llvm::Attribute::SafeStack);
-  }
 
   return Fn;
 }
Index: lib/CodeGen/CGClass.cpp
===================================================================
--- lib/CodeGen/CGClass.cpp
+++ lib/CodeGen/CGClass.cpp
@@ -2604,7 +2604,8 @@
     return;
 
   std::string TypeName = RD->getQualifiedNameAsString();
-  if (getContext().getSanitizerBlacklist().isBlacklistedType(TypeName))
+  if (getContext().getSanitizerBlacklist().isBlacklistedType(
+          TypeName, SanitizerKind::CFI))
     return;
 
   SanitizerScope SanScope(this);
@@ -2687,7 +2688,8 @@
     return false;
 
   std::string TypeName = RD->getQualifiedNameAsString();
-  return !getContext().getSanitizerBlacklist().isBlacklistedType(TypeName);
+  return !getContext().getSanitizerBlacklist().isBlacklistedType(
+      TypeName, SanitizerKind::CFI);
 }
 
 llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
Index: lib/Basic/SanitizerBlacklist.cpp
===================================================================
--- lib/Basic/SanitizerBlacklist.cpp
+++ lib/Basic/SanitizerBlacklist.cpp
@@ -15,32 +15,50 @@
 
 using namespace clang;
 
-SanitizerBlacklist::SanitizerBlacklist(
-    const std::vector<std::string> &BlacklistPaths, SourceManager &SM)
-    : SCL(llvm::SpecialCaseList::createOrDie(BlacklistPaths)), SM(SM) {}
-
-bool SanitizerBlacklist::isBlacklistedGlobal(StringRef GlobalName,
-                                             StringRef Category) const {
-  return SCL->inSection("global", GlobalName, Category);
+SanitizerBlacklistInfo::SanitizerBlacklistInfo(
+    ArrayRef<SanitizerBlacklist> Blacklists, SourceManager &SM)
+    : SM(SM) {
+  for (const auto &SB : Blacklists)
+    BLs.emplace_back(SB.Sanitizers,
+                     llvm::SpecialCaseList::createOrDie({SB.Path}));
 }
 
-bool SanitizerBlacklist::isBlacklistedType(StringRef MangledTypeName,
+bool SanitizerBlacklistInfo::isBlacklisted(StringRef SectionName,
+                                           StringRef Ident, SanitizerMask Kind,
                                            StringRef Category) const {
-  return SCL->inSection("type", MangledTypeName, Category);
+  for (const auto &BL : BLs)
+    if ((BL.Sanitizers & Kind) &&
+        BL.SCL->inSection(SectionName, Ident, Category))
+      return true;
+  return false;
 }
 
-bool SanitizerBlacklist::isBlacklistedFunction(StringRef FunctionName) const {
-  return SCL->inSection("fun", FunctionName);
+bool SanitizerBlacklistInfo::isBlacklistedGlobal(StringRef GlobalName,
+                                                 SanitizerMask Kind,
+                                                 StringRef Category) const {
+  return isBlacklisted("global", GlobalName, Kind, Category);
 }
 
-bool SanitizerBlacklist::isBlacklistedFile(StringRef FileName,
-                                           StringRef Category) const {
-  return SCL->inSection("src", FileName, Category);
+bool SanitizerBlacklistInfo::isBlacklistedType(StringRef MangledTypeName,
+                                               SanitizerMask Kind,
+                                               StringRef Category) const {
+  return isBlacklisted("type", MangledTypeName, Kind, Category);
+}
+
+bool SanitizerBlacklistInfo::isBlacklistedFunction(StringRef FunctionName,
+                                                   SanitizerMask Kind) const {
+  return isBlacklisted("fun", FunctionName, Kind, StringRef());
 }
 
-bool SanitizerBlacklist::isBlacklistedLocation(SourceLocation Loc,
+bool SanitizerBlacklistInfo::isBlacklistedFile(StringRef FileName,
+                                               SanitizerMask Kind,
                                                StringRef Category) const {
-  return Loc.isValid() &&
-         isBlacklistedFile(SM.getFilename(SM.getFileLoc(Loc)), Category);
+  return isBlacklisted("src", FileName, Kind, Category);
 }
 
+bool SanitizerBlacklistInfo::isBlacklistedLocation(SourceLocation Loc,
+                                                   SanitizerMask Kind,
+                                                   StringRef Category) const {
+  return Loc.isValid() &&
+         isBlacklistedFile(SM.getFilename(SM.getFileLoc(Loc)), Kind, Category);
+}
Index: lib/Basic/LangOptions.cpp
===================================================================
--- lib/Basic/LangOptions.cpp
+++ lib/Basic/LangOptions.cpp
@@ -30,6 +30,7 @@
 #include "clang/Basic/LangOptions.def"
 
   // These options do not affect AST generation.
+  SanitizerBlacklists.clear();
   SanitizerBlacklistFiles.clear();
   XRayAlwaysInstrumentFiles.clear();
   XRayNeverInstrumentFiles.clear();
Index: lib/AST/Decl.cpp
===================================================================
--- lib/AST/Decl.cpp
+++ lib/AST/Decl.cpp
@@ -3929,8 +3929,9 @@
 
 bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const {
   ASTContext &Context = getASTContext();
-  if (!Context.getLangOpts().Sanitize.hasOneOf(
-          SanitizerKind::Address | SanitizerKind::KernelAddress) ||
+  SanitizerMask ASanMask =
+      SanitizerKind::Address | SanitizerKind::KernelAddress;
+  if (!Context.getLangOpts().Sanitize.hasOneOf(ASanMask) ||
       !Context.getLangOpts().SanitizeAddressFieldPadding)
     return false;
   const auto &Blacklist = Context.getSanitizerBlacklist();
@@ -3949,9 +3950,10 @@
     ReasonToReject = 4;  // has trivial destructor.
   else if (CXXRD->isStandardLayout())
     ReasonToReject = 5;  // is standard layout.
-  else if (Blacklist.isBlacklistedLocation(getLocation(), "field-padding"))
+  else if (Blacklist.isBlacklistedLocation(getLocation(), ASanMask,
+                                           "field-padding"))
     ReasonToReject = 6;  // is in a blacklisted file.
-  else if (Blacklist.isBlacklistedType(getQualifiedNameAsString(),
+  else if (Blacklist.isBlacklistedType(getQualifiedNameAsString(), ASanMask,
                                        "field-padding"))
     ReasonToReject = 7;  // is blacklisted.
 
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -748,7 +748,7 @@
       cudaConfigureCallDecl(nullptr), FirstLocalImport(), LastLocalImport(),
       ExternCContext(nullptr), MakeIntegerSeqDecl(nullptr),
       TypePackElementDecl(nullptr), SourceMgr(SM), LangOpts(LOpts),
-      SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)),
+      SanitizerBL(new SanitizerBlacklistInfo(LangOpts.SanitizerBlacklists, SM)),
       XRayFilter(new XRayFunctionFilter(LangOpts.XRayAlwaysInstrumentFiles,
                                         LangOpts.XRayNeverInstrumentFiles, SM)),
       AddrSpaceMap(nullptr), Target(nullptr), AuxTarget(nullptr),
Index: include/clang/Driver/SanitizerArgs.h
===================================================================
--- include/clang/Driver/SanitizerArgs.h
+++ include/clang/Driver/SanitizerArgs.h
@@ -10,24 +10,25 @@
 #define LLVM_CLANG_DRIVER_SANITIZERARGS_H
 
 #include "clang/Basic/Sanitizers.h"
+#include "clang/Basic/SanitizerBlacklist.h"
 #include "clang/Driver/Types.h"
+#include "llvm/ADT/Optional.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
 #include <string>
 #include <vector>
 
 namespace clang {
 namespace driver {
 
+class Driver;
 class ToolChain;
 
 class SanitizerArgs {
   SanitizerSet Sanitizers;
   SanitizerSet RecoverableSanitizers;
   SanitizerSet TrapSanitizers;
 
-  std::vector<std::string> BlacklistFiles;
-  std::vector<std::string> ExtraDeps;
   int CoverageFeatures = 0;
   int MsanTrackOrigins = 0;
   bool MsanUseAfterDtor = false;
@@ -45,6 +46,18 @@
   bool TsanAtomics = true;
   bool MinimalRuntime = false;
 
+  /// Blacklists which each apply to specific sanitizers.
+  std::vector<SanitizerBlacklist> SanitizerBlacklists;
+
+  /// Paths to all sanitizer blacklist files.
+  std::vector<std::string> SanitizerBlacklistFiles;
+
+  /// Paths to sanitizer blacklist files which need depfile entries.
+  std::vector<StringRef> ExtraDeps;
+
+  /// Collect all default blacklists for the sanitizers enabled in \p Kinds.
+  void collectDefaultBlacklists(const Driver &D, SanitizerMask Kinds);
+
  public:
   /// Parses the sanitizer arguments from an argument list.
   SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args);
@@ -75,6 +88,13 @@
   bool hasCrossDsoCfi() const { return CfiCrossDso; }
   void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
                llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const;
+
+  /// Encode a sanitizer blacklist argument as a string.
+  static std::string encodeBlacklistArg(const SanitizerBlacklist &SB);
+
+  /// Decode a sanitizer blacklist argument. Returns true on success.
+  static bool decodeBlacklistArg(const std::string &Arg, SanitizerMask &Kinds,
+                                 std::string &Path);
 };
 
 }  // namespace driver
Index: include/clang/Basic/SanitizerBlacklist.h
===================================================================
--- include/clang/Basic/SanitizerBlacklist.h
+++ include/clang/Basic/SanitizerBlacklist.h
@@ -15,29 +15,54 @@
 #define LLVM_CLANG_BASIC_SANITIZERBLACKLIST_H
 
 #include "clang/Basic/LLVM.h"
+#include "clang/Basic/Sanitizers.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/SpecialCaseList.h"
 #include <memory>
 
 namespace clang {
 
-class SanitizerBlacklist {
-  std::unique_ptr<llvm::SpecialCaseList> SCL;
+struct SanitizerBlacklist {
+  /// The set of sanitizers this blacklist applies to.
+  SanitizerMask Sanitizers;
+
+  /// The path to the blacklist file.
+  StringRef Path;
+
+  SanitizerBlacklist(SanitizerMask SM, StringRef P) : Sanitizers(SM), Path(P) {}
+};
+
+class SanitizerBlacklistInfo {
+  struct Blacklist {
+    SanitizerMask Sanitizers;
+    std::unique_ptr<llvm::SpecialCaseList> SCL;
+
+    Blacklist(SanitizerMask Sanitizers,
+              std::unique_ptr<llvm::SpecialCaseList> SCL)
+        : Sanitizers(Sanitizers), SCL(std::move(SCL)) {}
+  };
+
+  SmallVector<Blacklist, 2> BLs;
   SourceManager &SM;
 
+  bool isBlacklisted(StringRef SectionName, StringRef Ident, SanitizerMask Kind,
+                     StringRef Category) const;
+
 public:
-  SanitizerBlacklist(const std::vector<std::string> &BlacklistPaths,
-                     SourceManager &SM);
-  bool isBlacklistedGlobal(StringRef GlobalName,
+  SanitizerBlacklistInfo(ArrayRef<SanitizerBlacklist> Blacklists,
+                         SourceManager &SM);
+  bool isBlacklistedGlobal(StringRef GlobalName, SanitizerMask Kind,
                            StringRef Category = StringRef()) const;
-  bool isBlacklistedType(StringRef MangledTypeName,
+  bool isBlacklistedType(StringRef MangledTypeName, SanitizerMask Kind,
                          StringRef Category = StringRef()) const;
-  bool isBlacklistedFunction(StringRef FunctionName) const;
-  bool isBlacklistedFile(StringRef FileName,
+  bool isBlacklistedFunction(StringRef FunctionName, SanitizerMask Kind) const;
+  bool isBlacklistedFile(StringRef FileName, SanitizerMask Kind,
                          StringRef Category = StringRef()) const;
-  bool isBlacklistedLocation(SourceLocation Loc,
+  bool isBlacklistedLocation(SourceLocation Loc, SanitizerMask Kind,
                              StringRef Category = StringRef()) const;
 };
 
Index: include/clang/Basic/LangOptions.h
===================================================================
--- include/clang/Basic/LangOptions.h
+++ include/clang/Basic/LangOptions.h
@@ -19,6 +19,7 @@
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/ObjCRuntime.h"
 #include "clang/Basic/Sanitizers.h"
+#include "clang/Basic/SanitizerBlacklist.h"
 #include "clang/Basic/Visibility.h"
 #include <string>
 #include <vector>
@@ -99,8 +100,11 @@
   /// \brief Set of enabled sanitizers.
   SanitizerSet Sanitize;
 
-  /// \brief Paths to blacklist files specifying which objects
+  /// \brief Per-sanitizer blacklist files specifying which objects
   /// (files, functions, variables) should not be instrumented.
+  std::vector<SanitizerBlacklist> SanitizerBlacklists;
+
+  /// Paths to sanitizer blacklist files.
   std::vector<std::string> SanitizerBlacklistFiles;
 
   /// \brief Paths to the XRay "always instrument" files specifying which
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -474,7 +474,7 @@
 
   /// \brief Blacklist object that is used by sanitizers to decide which
   /// entities should not be instrumented.
-  std::unique_ptr<SanitizerBlacklist> SanitizerBL;
+  std::unique_ptr<SanitizerBlacklistInfo> SanitizerBL;
 
   /// \brief Function filtering mechanism to determine whether a given function
   /// should be imbued with the XRay "always" or "never" attributes.
@@ -658,7 +658,7 @@
 
   const LangOptions& getLangOpts() const { return LangOpts; }
 
-  const SanitizerBlacklist &getSanitizerBlacklist() const {
+  const SanitizerBlacklistInfo &getSanitizerBlacklist() const {
     return *SanitizerBL;
   }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to