[𝘀𝗽𝗿] changes to main this commit is based on

Created using spr 1.3.6

[skip ci]
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ac9baf22..cea8ae1 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -960,6 +960,7 @@
 ----------
 
 - ``-fsanitize=vptr`` is no longer a part of ``-fsanitize=undefined``.
+- Sanitizer ignorelists now support the syntax ``src:*=sanitize``.
 
 Python Binding Changes
 ----------------------
diff --git a/clang/docs/SanitizerSpecialCaseList.rst b/clang/docs/SanitizerSpecialCaseList.rst
index 5c88c29..2a1da62 100644
--- a/clang/docs/SanitizerSpecialCaseList.rst
+++ b/clang/docs/SanitizerSpecialCaseList.rst
@@ -58,7 +58,7 @@
 ability to adjust instrumentation based on type.
 
 By default, supported sanitizers will have their instrumentation disabled for
-types specified within an ignorelist.
+entris specified within an ignorelist.
 
 .. code-block:: bash
 
@@ -77,10 +77,8 @@
 ``-fsanitize-ignorelist=ignorelist.txt`` disables overflow sanitizer
 instrumentation for arithmetic operations containing values of type ``int``.
 
-The ``=sanitize`` category is also supported. Any types assigned to the
-``sanitize`` category will have their sanitizer instrumentation remain. If the
-same type appears within or across ignorelists with different categories the
-``sanitize`` category takes precedence -- regardless of order.
+The ``=sanitize`` category is also supported. Any entries assigned to the
+``sanitize`` category will have their sanitizer instrumentation remain.
 
 With this, one may disable instrumentation for some or all types and
 specifically allow instrumentation for one or many types -- including types
@@ -103,6 +101,22 @@
     char c = toobig; // also not instrumented
   }
 
+Conflicting entries are resolved by the latest entry, which takes precedence.
+
+.. code-block:: bash
+
+  $ cat ignorelist1.txt
+  # test.cc will be instrumented.
+  src:*
+  src:*/mylib/*=sanitize
+  src:*/mylib/test.cc
+
+  $ cat ignorelist2.txt
+  # test.cc will not be instrumented.
+  src:*
+  src:*/mylib/test.cc
+  src:*/mylib/*=sanitize
+
 Format
 ======
 
diff --git a/clang/include/clang/Basic/SanitizerSpecialCaseList.h b/clang/include/clang/Basic/SanitizerSpecialCaseList.h
index d024b7d..25d518e 100644
--- a/clang/include/clang/Basic/SanitizerSpecialCaseList.h
+++ b/clang/include/clang/Basic/SanitizerSpecialCaseList.h
@@ -43,13 +43,18 @@
   bool inSection(SanitizerMask Mask, StringRef Prefix, StringRef Query,
                  StringRef Category = StringRef()) const;
 
+  // Query ignorelisted entries if any bit in Mask matches the entry's section.
+  // Return 0 if not found. If found, return the line number (starts with 1).
+  unsigned inSectionBlame(SanitizerMask Mask, StringRef Prefix, StringRef Query,
+                          StringRef Category = StringRef()) const;
+
 protected:
   // Initialize SanitizerSections.
   void createSanitizerSections();
 
   struct SanitizerSection {
     SanitizerSection(SanitizerMask SM, SectionEntries &E)
-        : Mask(SM), Entries(E){};
+        : Mask(SM), Entries(E) {};
 
     SanitizerMask Mask;
     SectionEntries &Entries;
diff --git a/clang/lib/Basic/NoSanitizeList.cpp b/clang/lib/Basic/NoSanitizeList.cpp
index e7e63c1..4feef5c 100644
--- a/clang/lib/Basic/NoSanitizeList.cpp
+++ b/clang/lib/Basic/NoSanitizeList.cpp
@@ -44,7 +44,15 @@
 
 bool NoSanitizeList::containsFile(SanitizerMask Mask, StringRef FileName,
                                   StringRef Category) const {
-  return SSCL->inSection(Mask, "src", FileName, Category);
+  unsigned NoSanLine = SSCL->inSectionBlame(Mask, "src", FileName, Category);
+  if (NoSanLine == 0)
+    return false;
+  unsigned SanLine = SSCL->inSectionBlame(Mask, "src", FileName, "sanitize");
+  // If we have two cases such as `src:a.cpp=sanitize` and `src:a.cpp`, the
+  // current entry override the previous entry.
+  if (SanLine > 0)
+    return NoSanLine > SanLine;
+  return true;
 }
 
 bool NoSanitizeList::containsMainFile(SanitizerMask Mask, StringRef FileName,
diff --git a/clang/lib/Basic/SanitizerSpecialCaseList.cpp b/clang/lib/Basic/SanitizerSpecialCaseList.cpp
index 2dbf04c..0e269eb 100644
--- a/clang/lib/Basic/SanitizerSpecialCaseList.cpp
+++ b/clang/lib/Basic/SanitizerSpecialCaseList.cpp
@@ -56,10 +56,20 @@
 bool SanitizerSpecialCaseList::inSection(SanitizerMask Mask, StringRef Prefix,
                                          StringRef Query,
                                          StringRef Category) const {
-  for (auto &S : SanitizerSections)
-    if ((S.Mask & Mask) &&
-        SpecialCaseList::inSectionBlame(S.Entries, Prefix, Query, Category))
-      return true;
+  return inSectionBlame(Mask, Prefix, Query, Category) > 0;
+}
 
-  return false;
+unsigned SanitizerSpecialCaseList::inSectionBlame(SanitizerMask Mask,
+                                                  StringRef Prefix,
+                                                  StringRef Query,
+                                                  StringRef Category) const {
+  for (auto &S : SanitizerSections) {
+    if (S.Mask & Mask) {
+      unsigned lineNum =
+          SpecialCaseList::inSectionBlame(S.Entries, Prefix, Query, Category);
+      if (lineNum > 0)
+        return lineNum;
+    }
+  }
+  return 0;
 }
diff --git a/clang/test/CodeGen/ubsan-src-ignorelist-category.test b/clang/test/CodeGen/ubsan-src-ignorelist-category.test
index 556b17d..bb37f0e 100644
--- a/clang/test/CodeGen/ubsan-src-ignorelist-category.test
+++ b/clang/test/CodeGen/ubsan-src-ignorelist-category.test
@@ -3,11 +3,11 @@
 
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow -fsanitize-ignorelist=%t/src.ignorelist -emit-llvm %t/test2.c -o -             | FileCheck %s --check-prefixes=CHECK2
 
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow -fsanitize-ignorelist=%t/src.ignorelist -emit-llvm %t/test1.c -o -             | FileCheck %s --check-prefixes=CHECK1,IGNORE
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow -fsanitize-ignorelist=%t/src.ignorelist -emit-llvm %t/test1.c -o -             | FileCheck %s --check-prefixes=CHECK1,SANITIZE
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow -fsanitize-ignorelist=%t/src.ignorelist.contradict1 -emit-llvm %t/test1.c -o - | FileCheck %s --check-prefixes=CHECK1,IGNORE
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow -fsanitize-ignorelist=%t/src.ignorelist.contradict2 -emit-llvm %t/test1.c -o - | FileCheck %s --check-prefixes=CHECK1,IGNORE
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow -fsanitize-ignorelist=%t/src.ignorelist.contradict2 -emit-llvm %t/test1.c -o - | FileCheck %s --check-prefixes=CHECK1,SANITIZE
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow -fsanitize-ignorelist=%t/src.ignorelist.contradict3 -emit-llvm %t/test1.c -o - | FileCheck %s --check-prefixes=CHECK1,IGNORE
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow -fsanitize-ignorelist=%t/src.ignorelist.contradict4 -emit-llvm %t/test1.c -o - | FileCheck %s --check-prefixes=CHECK1,IGNORE
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow -fsanitize-ignorelist=%t/src.ignorelist.contradict4 -emit-llvm %t/test1.c -o - | FileCheck %s --check-prefixes=CHECK1,SANITIZE
 
 
 // Verify ubsan only emits checks for files in the allowlist
diff --git a/llvm/lib/Support/SpecialCaseList.cpp b/llvm/lib/Support/SpecialCaseList.cpp
index dddf84c..5145ccc 100644
--- a/llvm/lib/Support/SpecialCaseList.cpp
+++ b/llvm/lib/Support/SpecialCaseList.cpp
@@ -63,6 +63,11 @@
                        .moveInto(Pair.first))
       return Err;
     Pair.second = LineNumber;
+  } else {
+    // We should update the new line number if an entry with the same pattern
+    // repeats.
+    auto &Pair = It->getValue();
+    Pair.second = LineNumber;
   }
   return Error::success();
 }
diff --git a/llvm/unittests/Support/SpecialCaseListTest.cpp b/llvm/unittests/Support/SpecialCaseListTest.cpp
index 4289a5e..d6d5621 100644
--- a/llvm/unittests/Support/SpecialCaseListTest.cpp
+++ b/llvm/unittests/Support/SpecialCaseListTest.cpp
@@ -306,4 +306,26 @@
   EXPECT_TRUE(SCL->inSection("sect2", "fun", "bar"));
   EXPECT_FALSE(SCL->inSection("sect3", "fun", "bar"));
 }
+
+TEST_F(SpecialCaseListTest, Version3) {
+  std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("[sect1]\n"
+                                                             "src:foo*\n"
+                                                             "[sect1]\n"
+                                                             "src:bar*\n"
+                                                             "src:def\n"
+                                                             "[sect2]\n"
+                                                             "src:def\n"
+                                                             "src:def\n");
+  EXPECT_TRUE(SCL->inSection("sect1", "src", "fooz"));
+  EXPECT_TRUE(SCL->inSection("sect1", "src", "barz"));
+  EXPECT_FALSE(SCL->inSection("sect2", "src", "fooz"));
+
+  EXPECT_TRUE(SCL->inSection("sect2", "src", "def"));
+  EXPECT_TRUE(SCL->inSection("sect1", "src", "def"));
+
+  EXPECT_EQ(2u, SCL->inSectionBlame("sect1", "src", "fooz"));
+  EXPECT_EQ(4u, SCL->inSectionBlame("sect1", "src", "barz"));
+  EXPECT_EQ(5u, SCL->inSectionBlame("sect1", "src", "def"));
+  EXPECT_EQ(8u, SCL->inSectionBlame("sect2", "src", "def"));
+}
 }