https://github.com/dbartol updated 
https://github.com/llvm/llvm-project/pull/168153

>From f23857c7df24ef166aa0bb4a90e2ba13e5e49bdc Mon Sep 17 00:00:00 2001
From: Dave Bartolomeo <[email protected]>
Date: Fri, 14 Nov 2025 17:45:25 -0500
Subject: [PATCH 1/2] [clang] [diagnostics] Stable IDs for Clang diagnostics

SARIF diagnostics require that each rule have a stable `id` property to 
identify that rule across runs, even when the compiler or analysis tool has 
changed. We were previously setting the `id` property to the numeric value of 
the enum value for that diagnostic within the Clang implementation; this value 
changes whenever an unrelated diagnostic is inserted or removed earlier in the 
list.

This change sets the `id` property to the _text_ of that same enum value. This 
value would only change if someone renames the enum value for that diagnostic, 
which should happen much less frequently than renumbering.

For now, we will just assume that renaming happens infrequently enough that 
existing consumers of SARIF will not notice. In the future, we could take 
advantage of SARIF's support for `deprecatedIds`, which let a rule specify the 
IDs by which it was previously known. This would let us rename, split, or 
combine diagnostics while still being able to correlate the new diagnostic IDs 
with older SARIF logs and/or suppressions.

Nothing in this change affects how warnings are configured on the command line 
or in `#pragma clang diagnostic`. Those still use warning groups, not the 
stable IDs.
---
 clang/include/clang/Basic/DiagnosticIDs.h |  3 ++
 clang/lib/Basic/DiagnosticIDs.cpp         | 45 ++++++++++++++++++++++-
 clang/lib/Frontend/SARIFDiagnostic.cpp    |  4 +-
 clang/test/Frontend/sarif-diagnostics.cpp | 36 +++++++++---------
 4 files changed, 68 insertions(+), 20 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticIDs.h 
b/clang/include/clang/Basic/DiagnosticIDs.h
index 06446cf580389..9fc49325205a2 100644
--- a/clang/include/clang/Basic/DiagnosticIDs.h
+++ b/clang/include/clang/Basic/DiagnosticIDs.h
@@ -332,6 +332,9 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
   /// Given a diagnostic ID, return a description of the issue.
   StringRef getDescription(unsigned DiagID) const;
 
+  /// Given a diagnostic ID, return the stable ID of the diagnostic.
+  std::string getStableID(unsigned DiagID) const;
+
   /// Return true if the unmapped diagnostic levelof the specified
   /// diagnostic ID is a Warning or Extension.
   ///
diff --git a/clang/lib/Basic/DiagnosticIDs.cpp 
b/clang/lib/Basic/DiagnosticIDs.cpp
index a1d9d0f34d20d..e3903a3edadfd 100644
--- a/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/clang/lib/Basic/DiagnosticIDs.cpp
@@ -51,6 +51,22 @@ const StaticDiagInfoDescriptionStringTable 
StaticDiagInfoDescriptions = {
 #undef DIAG
 };
 
+struct StaticDiagInfoStableIDStringTable {
+#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR,     
\
+             SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY)            
\
+  char ENUM##_id[sizeof(#ENUM)];
+#include "clang/Basic/AllDiagnosticKinds.inc"
+#undef DIAG
+};
+
+const StaticDiagInfoStableIDStringTable StaticDiagInfoStableIDs = {
+#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR,     
\
+             SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY)            
\
+  #ENUM,
+#include "clang/Basic/AllDiagnosticKinds.inc"
+#undef DIAG
+};
+
 extern const StaticDiagInfoRec StaticDiagInfo[];
 
 // Stored separately from StaticDiagInfoRec to pack better.  Otherwise,
@@ -63,6 +79,14 @@ const uint32_t StaticDiagInfoDescriptionOffsets[] = {
 #undef DIAG
 };
 
+const uint32_t StaticDiagInfoStableIDOffsets[] = {
+#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR,     
\
+             SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY)            
\
+  offsetof(StaticDiagInfoStableIDStringTable, ENUM##_id),
+#include "clang/Basic/AllDiagnosticKinds.inc"
+#undef DIAG
+};
+
 enum DiagnosticClass {
   CLASS_NOTE = DiagnosticIDs::CLASS_NOTE,
   CLASS_REMARK = DiagnosticIDs::CLASS_REMARK,
@@ -95,6 +119,7 @@ struct StaticDiagInfoRec {
   uint16_t Deferrable : 1;
 
   uint16_t DescriptionLen;
+  uint16_t StableIDLen;
 
   unsigned getOptionGroupIndex() const {
     return OptionGroupIndex;
@@ -107,6 +132,14 @@ struct StaticDiagInfoRec {
     return StringRef(&Table[StringOffset], DescriptionLen);
   }
 
+  StringRef getStableID() const {
+    size_t MyIndex = this - &StaticDiagInfo[0];
+    uint32_t StringOffset = StaticDiagInfoStableIDOffsets[MyIndex];
+    const char *Table =
+        reinterpret_cast<const char *>(&StaticDiagInfoStableIDs);
+    return StringRef(&Table[StringOffset], StableIDLen);
+  }
+
   diag::Flavor getFlavor() const {
     return Class == CLASS_REMARK ? diag::Flavor::Remark
                                  : diag::Flavor::WarningOrError;
@@ -159,7 +192,8 @@ const StaticDiagInfoRec StaticDiagInfo[] = {
       SHOWINSYSMACRO,                                                          
\
       GROUP,                                                                   
\
            DEFERRABLE,                                                         
     \
-      STR_SIZE(DESC, uint16_t)},
+      STR_SIZE(DESC, uint16_t),                                               \
+      STR_SIZE(#ENUM, uint16_t)},
 #include "clang/Basic/DiagnosticCommonKinds.inc"
 #include "clang/Basic/DiagnosticDriverKinds.inc"
 #include "clang/Basic/DiagnosticFrontendKinds.inc"
@@ -434,6 +468,15 @@ StringRef DiagnosticIDs::getDescription(unsigned DiagID) 
const {
   return CustomDiagInfo->getDescription(DiagID).GetDescription();
 }
 
+/// getIDString - Given a diagnostic ID, return the stable ID of the 
diagnostic.
+std::string DiagnosticIDs::getStableID(unsigned DiagID) const {
+  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+    return Info->getStableID().str();
+  assert(CustomDiagInfo && "Invalid CustomDiagInfo");
+  // TODO: Stable IDs for custom diagnostics?
+  return std::to_string(DiagID);
+}
+
 static DiagnosticIDs::Level toLevel(diag::Severity SV) {
   switch (SV) {
   case diag::Severity::Ignored:
diff --git a/clang/lib/Frontend/SARIFDiagnostic.cpp 
b/clang/lib/Frontend/SARIFDiagnostic.cpp
index ac27d7480de3e..ac72a7af05429 100644
--- a/clang/lib/Frontend/SARIFDiagnostic.cpp
+++ b/clang/lib/Frontend/SARIFDiagnostic.cpp
@@ -46,7 +46,9 @@ void SARIFDiagnostic::emitDiagnosticMessage(
   if (!Diag)
     return;
 
-  SarifRule Rule = 
SarifRule::create().setRuleId(std::to_string(Diag->getID()));
+  std::string StableID =
+      Diag->getDiags()->getDiagnosticIDs()->getStableID(Diag->getID());
+  SarifRule Rule = SarifRule::create().setRuleId(StableID);
 
   Rule = addDiagnosticLevelToRule(Rule, Level);
 
diff --git a/clang/test/Frontend/sarif-diagnostics.cpp 
b/clang/test/Frontend/sarif-diagnostics.cpp
index 767c5802ca13d..3f7adb80c67fd 100644
--- a/clang/test/Frontend/sarif-diagnostics.cpp
+++ b/clang/test/Frontend/sarif-diagnostics.cpp
@@ -34,35 +34,35 @@ void f1(t1 x, t1 y) {
 // Omit filepath to llvm project directory
 // CHECK: 
test/Frontend/sarif-diagnostics.cpp"},"mimeType":"text/plain","roles":["resultFile"]}],"columnKind":"unicodeCodePoints","results":
 // CHECK: 
[{"level":"error","locations":[{"physicalLocation":{"artifactLocation":{"index":0,"uri":"file://
-// CHECK: 
{"endColumn":1,"startColumn":1,"startLine":12}}}],"message":{"text":"'main' 
must return 'int'"},"ruleId":"{{[0-9]+}}","ruleIndex":0},
+// CHECK: 
{"endColumn":1,"startColumn":1,"startLine":12}}}],"message":{"text":"'main' 
must return 'int'"},"ruleId":"{{[A-Za-z0-9_]+}}","ruleIndex":0},
 // CHECK: 
{"level":"error","locations":[{"physicalLocation":{"artifactLocation":{"index":0,"uri":"file://
 // CHECK: 
{"endColumn":11,"startColumn":11,"startLine":13}}}],"message":{"text":"use of 
undeclared identifier
-// CHECK: 
'hello'"},"ruleId":"{{[0-9]+}}","ruleIndex":1},{"level":"error","locations":[{"physicalLocation":{"artifactLocation":
+// CHECK: 
'hello'"},"ruleId":"{{[A-Za-z0-9_]+}}","ruleIndex":1},{"level":"error","locations":[{"physicalLocation":{"artifactLocation":
 // CHECK: 
{"index":0,"uri":"file://{{.+}}"},"region":{"endColumn":17,"startColumn":17,"startLine":15}}}],"message":{"text":"invalid
 digit 'a' in decimal
-// CHECK: 
constant"},"ruleId":"{{[0-9]+}}","ruleIndex":2},{"level":"warning","locations":[{"physicalLocation":{"artifactLocation":
+// CHECK: 
constant"},"ruleId":"{{[A-Za-z0-9_]+}}","ruleIndex":2},{"level":"warning","locations":[{"physicalLocation":{"artifactLocation":
 // CHECK: 
{"index":0,"uri":"file://{{.+}}"},"region":{"endColumn":5,"startColumn":5,"startLine":19}}}],"message":{"text":"misleading
 indentation; statement is not part
-// CHECK: of the previous 
'if'"},"ruleId":"{{[0-9]+}}","ruleIndex":3},{"level":"note","locations":[{"physicalLocation":{"artifactLocation":
+// CHECK: of the previous 
'if'"},"ruleId":"{{[A-Za-z0-9_]+}}","ruleIndex":3},{"level":"note","locations":[{"physicalLocation":{"artifactLocation":
 // CHECK: 
{"index":0,"uri":"file://{{.+}}"},"region":{"endColumn":3,"startColumn":3,"startLine":17}}}],"message":{"text":"previous
 statement is
-// CHECK: 
here"},"ruleId":"{{[0-9]+}}","ruleIndex":4},{"level":"warning","locations":[{"physicalLocation":{"artifactLocation":
+// CHECK: 
here"},"ruleId":"{{[A-Za-z0-9_]+}}","ruleIndex":4},{"level":"warning","locations":[{"physicalLocation":{"artifactLocation":
 // CHECK: 
{"index":0,"uri":"file://{{.+}}"},"region":{"endColumn":10,"startColumn":10,"startLine":18}}}],"message":{"text":"unused
 variable
-// CHECK: 
'Yes'"},"ruleId":"{{[0-9]+}}","ruleIndex":5},{"level":"error","locations":[{"physicalLocation":{"artifactLocation":{"index":0,"uri":"file://
+// CHECK: 
'Yes'"},"ruleId":"{{[A-Za-z0-9_]+}}","ruleIndex":5},{"level":"error","locations":[{"physicalLocation":{"artifactLocation":{"index":0,"uri":"file://
 // CHECK: 
{"endColumn":12,"startColumn":12,"startLine":21}}}],"message":{"text":"use of 
undeclared identifier
-// CHECK: 
'hi'"},"ruleId":"{{[0-9]+}}","ruleIndex":6},{"level":"error","locations":[{"physicalLocation":{"artifactLocation":{"index":0,"uri":"file://
+// CHECK: 
'hi'"},"ruleId":"{{[A-Za-z0-9_]+}}","ruleIndex":6},{"level":"error","locations":[{"physicalLocation":{"artifactLocation":{"index":0,"uri":"file://
 // CHECK: 
{"endColumn":1,"startColumn":1,"startLine":23}}}],"message":{"text":"extraneous 
closing brace
-// CHECK: 
('}')"},"ruleId":"{{[0-9]+}}","ruleIndex":7},{"level":"error","locations":[{"physicalLocation":{"artifactLocation":{"index":0,"uri":"file://
+// CHECK: 
('}')"},"ruleId":"{{[A-Za-z0-9_]+}}","ruleIndex":7},{"level":"error","locations":[{"physicalLocation":{"artifactLocation":{"index":0,"uri":"file://
 // CHECK: 
{"endColumn":6,"endLine":27,"startColumn":5,"startLine":27}}},{"physicalLocation":{"artifactLocation":{"index":0,"uri":"file://
 // CHECK: 
{"endColumn":10,"endLine":27,"startColumn":9,"startLine":27}}},{"physicalLocation":{"artifactLocation":{"index":0,"uri":"file://
 // CHECK: 
{"endColumn":7,"startColumn":7,"startLine":27}}}],"message":{"text":"invalid 
operands to binary expression ('t1' and
-// CHECK: 
't1')"},"ruleId":"{{[0-9]+}}","ruleIndex":8}],"tool":{"driver":{"fullName":"","informationUri":"https://clang.llvm.org/docs/
+// CHECK: 
't1')"},"ruleId":"{{[A-Za-z0-9_]+}}","ruleIndex":8}],"tool":{"driver":{"fullName":"","informationUri":"https://clang.llvm.org/docs/
 // CHECK: 
UsersManual.html","language":"en-US","name":"clang","rules":[{"defaultConfiguration":
-// CHECK: 
{"enabled":true,"level":"error","rank":50},"fullDescription":{"text":""},"id":"{{[0-9]+}}","name":""},{"defaultConfiguration":
-// CHECK: 
{"enabled":true,"level":"error","rank":50},"fullDescription":{"text":""},"id":"{{[0-9]+}}","name":""},{"defaultConfiguration":
-// CHECK: 
{"enabled":true,"level":"error","rank":50},"fullDescription":{"text":""},"id":"{{[0-9]+}}","name":""},{"defaultConfiguration":
-// CHECK: 
{"enabled":true,"level":"warning","rank":-1},"fullDescription":{"text":""},"id":"{{[0-9]+}}","name":""},{"defaultConfiguration":
-// CHECK: 
{"enabled":true,"level":"note","rank":-1},"fullDescription":{"text":""},"id":"{{[0-9]+}}","name":""},{"defaultConfiguration":
-// CHECK: 
{"enabled":true,"level":"warning","rank":-1},"fullDescription":{"text":""},"id":"{{[0-9]+}}","name":""},{"defaultConfiguration":
-// CHECK: 
{"enabled":true,"level":"error","rank":50},"fullDescription":{"text":""},"id":"{{[0-9]+}}","name":""},{"defaultConfiguration":
-// CHECK: 
{"enabled":true,"level":"error","rank":50},"fullDescription":{"text":""},"id":"{{[0-9]+}}","name":""},{"defaultConfiguration":
+// CHECK: 
{"enabled":true,"level":"error","rank":50},"fullDescription":{"text":""},"id":"{{[A-Za-z0-9_]+}}","name":""},{"defaultConfiguration":
+// CHECK: 
{"enabled":true,"level":"error","rank":50},"fullDescription":{"text":""},"id":"{{[A-Za-z0-9_]+}}","name":""},{"defaultConfiguration":
+// CHECK: 
{"enabled":true,"level":"error","rank":50},"fullDescription":{"text":""},"id":"{{[A-Za-z0-9_]+}}","name":""},{"defaultConfiguration":
+// CHECK: 
{"enabled":true,"level":"warning","rank":-1},"fullDescription":{"text":""},"id":"{{[A-Za-z0-9_]+}}","name":""},{"defaultConfiguration":
+// CHECK: 
{"enabled":true,"level":"note","rank":-1},"fullDescription":{"text":""},"id":"{{[A-Za-z0-9_]+}}","name":""},{"defaultConfiguration":
+// CHECK: 
{"enabled":true,"level":"warning","rank":-1},"fullDescription":{"text":""},"id":"{{[A-Za-z0-9_]+}}","name":""},{"defaultConfiguration":
+// CHECK: 
{"enabled":true,"level":"error","rank":50},"fullDescription":{"text":""},"id":"{{[A-Za-z0-9_]+}}","name":""},{"defaultConfiguration":
+// CHECK: 
{"enabled":true,"level":"error","rank":50},"fullDescription":{"text":""},"id":"{{[A-Za-z0-9_]+}}","name":""},{"defaultConfiguration":
 // CHECK: {"enabled":true,"level":"error","rank":50},"fullDescription":
-// CHECK: 
{"text":""},"id":"{{[0-9]+}}","name":""}],"version":"{{[0-9]+\.[0-9]+\.[0-9]+[^"
 ]*}}"}}}],"version":"2.1.0"}
+// CHECK: 
{"text":""},"id":"{{[A-Za-z0-9_]+}}","name":""}],"version":"{{[0-9]+\.[0-9]+\.[0-9]+[^"
 ]*}}"}}}],"version":"2.1.0"}
 // CHECK: 2 warnings and 6 errors generated.

>From 402e6a80d69ee569d9399e964306598dbc9d1947 Mon Sep 17 00:00:00 2001
From: Dave Bartolomeo <[email protected]>
Date: Wed, 3 Dec 2025 18:11:50 -0800
Subject: [PATCH 2/2] [clang] [diagnostics] Use `normalize_sarif` for Clang
 SARIF testing

This change modifies the one existing Clang test for SARIF output to use the 
same `normalize_sarif` sed script that we use for diffing SARIF in the Clang 
Static Analyzer tests, rather than using a complicated set of `CHECK` 
statements. This did require changing the SARIF output to include line breaks.
---
 clang/lib/Frontend/SARIFDiagnosticPrinter.cpp |   2 +-
 clang/test/Analysis/lit.local.cfg             |  19 +-
 .../sarif-diagnostics.cpp.sarif               | 424 ++++++++++++++++++
 clang/test/Frontend/sarif-diagnostics.cpp     |  50 +--
 clang/test/lit.cfg.py                         |  17 +
 5 files changed, 448 insertions(+), 64 deletions(-)
 create mode 100644 
clang/test/Frontend/Inputs/expected-sarif/sarif-diagnostics.cpp.sarif

diff --git a/clang/lib/Frontend/SARIFDiagnosticPrinter.cpp 
b/clang/lib/Frontend/SARIFDiagnosticPrinter.cpp
index 988159693389b..72b796f8db798 100644
--- a/clang/lib/Frontend/SARIFDiagnosticPrinter.cpp
+++ b/clang/lib/Frontend/SARIFDiagnosticPrinter.cpp
@@ -40,7 +40,7 @@ void SARIFDiagnosticPrinter::EndSourceFile() {
   assert(SARIFDiag && "SARIFDiagnostic has not been set.");
   Writer->endRun();
   llvm::json::Value Value(Writer->createDocument());
-  OS << "\n" << Value << "\n\n";
+  OS << llvm::formatv("\n{0:2}\n\n", Value);
   OS.flush();
   SARIFDiag.reset();
 }
diff --git a/clang/test/Analysis/lit.local.cfg 
b/clang/test/Analysis/lit.local.cfg
index 03ab418a5a4f7..3bc2f94809c85 100644
--- a/clang/test/Analysis/lit.local.cfg
+++ b/clang/test/Analysis/lit.local.cfg
@@ -17,24 +17,7 @@ config.substitutions.append(
     )
 )
 
-sed_cmd = "/opt/freeware/bin/sed" if "system-aix" in config.available_features 
else "sed"
-
-# Filtering command for testing SARIF output against reference output.
-config.substitutions.append(
-    (
-        "%normalize_sarif",
-        f"{sed_cmd} -r '%s;%s;%s;%s'"
-        % (
-            # Replace version strings that are likely to change.
-            r's/"version": ".* version .*"/"version": "[clang version]"/',
-            r's/"version": "2.1.0"/"version": "[SARIF version]"/',
-            # Strip directories from file URIs
-            r's/"file:(\/+)([^"\/]+\/)*([^"]+)"/"file:\1[...]\/\3"/',
-            # Set "length" to -1
-            r's/"length": [[:digit:]]+/"length": -1/'
-        ),
-    )
-)
+# SARIF filtering is now shared with the rest of Clang in ../lit.cfg.py
 
 if not config.root.clang_staticanalyzer:
     config.unsupported = True
diff --git 
a/clang/test/Frontend/Inputs/expected-sarif/sarif-diagnostics.cpp.sarif 
b/clang/test/Frontend/Inputs/expected-sarif/sarif-diagnostics.cpp.sarif
new file mode 100644
index 0000000000000..21f06bf0a1b23
--- /dev/null
+++ b/clang/test/Frontend/Inputs/expected-sarif/sarif-diagnostics.cpp.sarif
@@ -0,0 +1,424 @@
+clang: warning: diagnostic formatting in SARIF mode is currently unstable 
[-Wsarif-format-unstable]
+
+{
+  "$schema": 
"https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json";,
+  "runs": [
+    {
+      "artifacts": [
+        {
+          "length": -1,
+          "location": {
+            "index": 0,
+            "uri": "file:///[...]/sarif-diagnostics.cpp"
+          },
+          "mimeType": "text/plain",
+          "roles": [
+            "resultFile"
+          ]
+        }
+      ],
+      "columnKind": "unicodeCodePoints",
+      "results": [
+        {
+          "level": "error",
+          "locations": [
+            {
+              "physicalLocation": {
+                "artifactLocation": {
+                  "index": 0,
+                  "uri": "file:///[...]/sarif-diagnostics.cpp"
+                },
+                "region": {
+                  "endColumn": 1,
+                  "startColumn": 1,
+                  "startLine": 12
+                }
+              }
+            }
+          ],
+          "message": {
+            "text": "'main' must return 'int'"
+          },
+          "ruleId": "err_main_returns_nonint",
+          "ruleIndex": 0
+        },
+        {
+          "level": "error",
+          "locations": [
+            {
+              "physicalLocation": {
+                "artifactLocation": {
+                  "index": 0,
+                  "uri": "file:///[...]/sarif-diagnostics.cpp"
+                },
+                "region": {
+                  "endColumn": 16,
+                  "endLine": 13,
+                  "startColumn": 11,
+                  "startLine": 13
+                }
+              }
+            },
+            {
+              "physicalLocation": {
+                "artifactLocation": {
+                  "index": 0,
+                  "uri": "file:///[...]/sarif-diagnostics.cpp"
+                },
+                "region": {
+                  "endColumn": 11,
+                  "startColumn": 11,
+                  "startLine": 13
+                }
+              }
+            }
+          ],
+          "message": {
+            "text": "use of undeclared identifier 'hello'"
+          },
+          "ruleId": "err_undeclared_var_use",
+          "ruleIndex": 1
+        },
+        {
+          "level": "error",
+          "locations": [
+            {
+              "physicalLocation": {
+                "artifactLocation": {
+                  "index": 0,
+                  "uri": "file:///[...]/sarif-diagnostics.cpp"
+                },
+                "region": {
+                  "endColumn": 17,
+                  "startColumn": 17,
+                  "startLine": 15
+                }
+              }
+            }
+          ],
+          "message": {
+            "text": "invalid digit 'a' in decimal constant"
+          },
+          "ruleId": "err_invalid_digit",
+          "ruleIndex": 2
+        },
+        {
+          "level": "warning",
+          "locations": [
+            {
+              "physicalLocation": {
+                "artifactLocation": {
+                  "index": 0,
+                  "uri": "file:///[...]/sarif-diagnostics.cpp"
+                },
+                "region": {
+                  "endColumn": 5,
+                  "startColumn": 5,
+                  "startLine": 19
+                }
+              }
+            }
+          ],
+          "message": {
+            "text": "misleading indentation; statement is not part of the 
previous 'if'"
+          },
+          "ruleId": "warn_misleading_indentation",
+          "ruleIndex": 3
+        },
+        {
+          "level": "note",
+          "locations": [
+            {
+              "physicalLocation": {
+                "artifactLocation": {
+                  "index": 0,
+                  "uri": "file:///[...]/sarif-diagnostics.cpp"
+                },
+                "region": {
+                  "endColumn": 3,
+                  "startColumn": 3,
+                  "startLine": 17
+                }
+              }
+            }
+          ],
+          "message": {
+            "text": "previous statement is here"
+          },
+          "ruleId": "note_previous_statement",
+          "ruleIndex": 4
+        },
+        {
+          "level": "warning",
+          "locations": [
+            {
+              "physicalLocation": {
+                "artifactLocation": {
+                  "index": 0,
+                  "uri": "file:///[...]/sarif-diagnostics.cpp"
+                },
+                "region": {
+                  "endColumn": 13,
+                  "endLine": 18,
+                  "startColumn": 10,
+                  "startLine": 18
+                }
+              }
+            },
+            {
+              "physicalLocation": {
+                "artifactLocation": {
+                  "index": 0,
+                  "uri": "file:///[...]/sarif-diagnostics.cpp"
+                },
+                "region": {
+                  "endColumn": 10,
+                  "startColumn": 10,
+                  "startLine": 18
+                }
+              }
+            }
+          ],
+          "message": {
+            "text": "unused variable 'Yes'"
+          },
+          "ruleId": "warn_unused_variable",
+          "ruleIndex": 5
+        },
+        {
+          "level": "error",
+          "locations": [
+            {
+              "physicalLocation": {
+                "artifactLocation": {
+                  "index": 0,
+                  "uri": "file:///[...]/sarif-diagnostics.cpp"
+                },
+                "region": {
+                  "endColumn": 14,
+                  "endLine": 21,
+                  "startColumn": 12,
+                  "startLine": 21
+                }
+              }
+            },
+            {
+              "physicalLocation": {
+                "artifactLocation": {
+                  "index": 0,
+                  "uri": "file:///[...]/sarif-diagnostics.cpp"
+                },
+                "region": {
+                  "endColumn": 12,
+                  "startColumn": 12,
+                  "startLine": 21
+                }
+              }
+            }
+          ],
+          "message": {
+            "text": "use of undeclared identifier 'hi'"
+          },
+          "ruleId": "err_undeclared_var_use",
+          "ruleIndex": 6
+        },
+        {
+          "level": "error",
+          "locations": [
+            {
+              "physicalLocation": {
+                "artifactLocation": {
+                  "index": 0,
+                  "uri": "file:///[...]/sarif-diagnostics.cpp"
+                },
+                "region": {
+                  "endColumn": 1,
+                  "startColumn": 1,
+                  "startLine": 23
+                }
+              }
+            }
+          ],
+          "message": {
+            "text": "extraneous closing brace ('}')"
+          },
+          "ruleId": "err_extraneous_closing_brace",
+          "ruleIndex": 7
+        },
+        {
+          "level": "error",
+          "locations": [
+            {
+              "physicalLocation": {
+                "artifactLocation": {
+                  "index": 0,
+                  "uri": "file:///[...]/sarif-diagnostics.cpp"
+                },
+                "region": {
+                  "endColumn": 6,
+                  "endLine": 27,
+                  "startColumn": 5,
+                  "startLine": 27
+                }
+              }
+            },
+            {
+              "physicalLocation": {
+                "artifactLocation": {
+                  "index": 0,
+                  "uri": "file:///[...]/sarif-diagnostics.cpp"
+                },
+                "region": {
+                  "endColumn": 10,
+                  "endLine": 27,
+                  "startColumn": 9,
+                  "startLine": 27
+                }
+              }
+            },
+            {
+              "physicalLocation": {
+                "artifactLocation": {
+                  "index": 0,
+                  "uri": "file:///[...]/sarif-diagnostics.cpp"
+                },
+                "region": {
+                  "endColumn": 7,
+                  "startColumn": 7,
+                  "startLine": 27
+                }
+              }
+            }
+          ],
+          "message": {
+            "text": "invalid operands to binary expression ('t1' and 't1')"
+          },
+          "ruleId": "err_typecheck_invalid_operands",
+          "ruleIndex": 8
+        }
+      ],
+      "tool": {
+        "driver": {
+          "fullName": "",
+          "informationUri": "https://clang.llvm.org/docs/UsersManual.html";,
+          "language": "en-US",
+          "name": "clang",
+          "rules": [
+            {
+              "defaultConfiguration": {
+                "enabled": true,
+                "level": "error",
+                "rank": 50
+              },
+              "fullDescription": {
+                "text": ""
+              },
+              "id": "err_main_returns_nonint",
+              "name": ""
+            },
+            {
+              "defaultConfiguration": {
+                "enabled": true,
+                "level": "error",
+                "rank": 50
+              },
+              "fullDescription": {
+                "text": ""
+              },
+              "id": "err_undeclared_var_use",
+              "name": ""
+            },
+            {
+              "defaultConfiguration": {
+                "enabled": true,
+                "level": "error",
+                "rank": 50
+              },
+              "fullDescription": {
+                "text": ""
+              },
+              "id": "err_invalid_digit",
+              "name": ""
+            },
+            {
+              "defaultConfiguration": {
+                "enabled": true,
+                "level": "warning",
+                "rank": -1
+              },
+              "fullDescription": {
+                "text": ""
+              },
+              "id": "warn_misleading_indentation",
+              "name": ""
+            },
+            {
+              "defaultConfiguration": {
+                "enabled": true,
+                "level": "note",
+                "rank": -1
+              },
+              "fullDescription": {
+                "text": ""
+              },
+              "id": "note_previous_statement",
+              "name": ""
+            },
+            {
+              "defaultConfiguration": {
+                "enabled": true,
+                "level": "warning",
+                "rank": -1
+              },
+              "fullDescription": {
+                "text": ""
+              },
+              "id": "warn_unused_variable",
+              "name": ""
+            },
+            {
+              "defaultConfiguration": {
+                "enabled": true,
+                "level": "error",
+                "rank": 50
+              },
+              "fullDescription": {
+                "text": ""
+              },
+              "id": "err_undeclared_var_use",
+              "name": ""
+            },
+            {
+              "defaultConfiguration": {
+                "enabled": true,
+                "level": "error",
+                "rank": 50
+              },
+              "fullDescription": {
+                "text": ""
+              },
+              "id": "err_extraneous_closing_brace",
+              "name": ""
+            },
+            {
+              "defaultConfiguration": {
+                "enabled": true,
+                "level": "error",
+                "rank": 50
+              },
+              "fullDescription": {
+                "text": ""
+              },
+              "id": "err_typecheck_invalid_operands",
+              "name": ""
+            }
+          ],
+          "version": "[clang version]"
+        }
+      }
+    }
+  ],
+  "version": "[SARIF version]"
+}
+
+2 warnings and 6 errors generated.
\ No newline at end of file
diff --git a/clang/test/Frontend/sarif-diagnostics.cpp 
b/clang/test/Frontend/sarif-diagnostics.cpp
index 3f7adb80c67fd..04cd19516fc0a 100644
--- a/clang/test/Frontend/sarif-diagnostics.cpp
+++ b/clang/test/Frontend/sarif-diagnostics.cpp
@@ -1,14 +1,14 @@
 // RUN: %clang -fsyntax-only -Wall -Wextra -fdiagnostics-format=sarif %s > %t 
2>&1 || true
-// RUN: FileCheck -dump-input=always %s --input-file=%t
+// RUN: cat %t | %normalize_sarif | diff -U1 -b 
%S/Inputs/expected-sarif/sarif-diagnostics.cpp.sarif -
 
 // FIXME: this test is incredibly fragile because the `main()` function
-// must be on line 12 in order for the CHECK lines to get the correct line
-// number values.
+// must be on line 12 in order for the line numbers in the SARIF output
+// to match the expected values
 //
 // So these comment lines are being used to ensure the code below happens
 // to work properly for the test coverage, which as you can imagine, is not
-// the best way to structure the test. We really need to introduce a better
-// tool than FileCheck for diff'ing JSON output like SARIF.
+// the best way to structure the test. We should consider having a way to
+// tag line numbers in the test source to match in the SARIF output.
 void main() {
   int i = hello;
 
@@ -26,43 +26,3 @@ struct t1 { };
 void f1(t1 x, t1 y) {
     x + y;
 }
-
-// CHECK: warning: diagnostic formatting in SARIF mode is currently unstable 
[-Wsarif-format-unstable]
-// CHECK: 
{"$schema":"https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json","runs":[{"artifacts":[{"length":
-// Omit exact length of this file
-// CHECK: ,"location":{"index":0,"uri":"file://
-// Omit filepath to llvm project directory
-// CHECK: 
test/Frontend/sarif-diagnostics.cpp"},"mimeType":"text/plain","roles":["resultFile"]}],"columnKind":"unicodeCodePoints","results":
-// CHECK: 
[{"level":"error","locations":[{"physicalLocation":{"artifactLocation":{"index":0,"uri":"file://
-// CHECK: 
{"endColumn":1,"startColumn":1,"startLine":12}}}],"message":{"text":"'main' 
must return 'int'"},"ruleId":"{{[A-Za-z0-9_]+}}","ruleIndex":0},
-// CHECK: 
{"level":"error","locations":[{"physicalLocation":{"artifactLocation":{"index":0,"uri":"file://
-// CHECK: 
{"endColumn":11,"startColumn":11,"startLine":13}}}],"message":{"text":"use of 
undeclared identifier
-// CHECK: 
'hello'"},"ruleId":"{{[A-Za-z0-9_]+}}","ruleIndex":1},{"level":"error","locations":[{"physicalLocation":{"artifactLocation":
-// CHECK: 
{"index":0,"uri":"file://{{.+}}"},"region":{"endColumn":17,"startColumn":17,"startLine":15}}}],"message":{"text":"invalid
 digit 'a' in decimal
-// CHECK: 
constant"},"ruleId":"{{[A-Za-z0-9_]+}}","ruleIndex":2},{"level":"warning","locations":[{"physicalLocation":{"artifactLocation":
-// CHECK: 
{"index":0,"uri":"file://{{.+}}"},"region":{"endColumn":5,"startColumn":5,"startLine":19}}}],"message":{"text":"misleading
 indentation; statement is not part
-// CHECK: of the previous 
'if'"},"ruleId":"{{[A-Za-z0-9_]+}}","ruleIndex":3},{"level":"note","locations":[{"physicalLocation":{"artifactLocation":
-// CHECK: 
{"index":0,"uri":"file://{{.+}}"},"region":{"endColumn":3,"startColumn":3,"startLine":17}}}],"message":{"text":"previous
 statement is
-// CHECK: 
here"},"ruleId":"{{[A-Za-z0-9_]+}}","ruleIndex":4},{"level":"warning","locations":[{"physicalLocation":{"artifactLocation":
-// CHECK: 
{"index":0,"uri":"file://{{.+}}"},"region":{"endColumn":10,"startColumn":10,"startLine":18}}}],"message":{"text":"unused
 variable
-// CHECK: 
'Yes'"},"ruleId":"{{[A-Za-z0-9_]+}}","ruleIndex":5},{"level":"error","locations":[{"physicalLocation":{"artifactLocation":{"index":0,"uri":"file://
-// CHECK: 
{"endColumn":12,"startColumn":12,"startLine":21}}}],"message":{"text":"use of 
undeclared identifier
-// CHECK: 
'hi'"},"ruleId":"{{[A-Za-z0-9_]+}}","ruleIndex":6},{"level":"error","locations":[{"physicalLocation":{"artifactLocation":{"index":0,"uri":"file://
-// CHECK: 
{"endColumn":1,"startColumn":1,"startLine":23}}}],"message":{"text":"extraneous 
closing brace
-// CHECK: 
('}')"},"ruleId":"{{[A-Za-z0-9_]+}}","ruleIndex":7},{"level":"error","locations":[{"physicalLocation":{"artifactLocation":{"index":0,"uri":"file://
-// CHECK: 
{"endColumn":6,"endLine":27,"startColumn":5,"startLine":27}}},{"physicalLocation":{"artifactLocation":{"index":0,"uri":"file://
-// CHECK: 
{"endColumn":10,"endLine":27,"startColumn":9,"startLine":27}}},{"physicalLocation":{"artifactLocation":{"index":0,"uri":"file://
-// CHECK: 
{"endColumn":7,"startColumn":7,"startLine":27}}}],"message":{"text":"invalid 
operands to binary expression ('t1' and
-// CHECK: 
't1')"},"ruleId":"{{[A-Za-z0-9_]+}}","ruleIndex":8}],"tool":{"driver":{"fullName":"","informationUri":"https://clang.llvm.org/docs/
-// CHECK: 
UsersManual.html","language":"en-US","name":"clang","rules":[{"defaultConfiguration":
-// CHECK: 
{"enabled":true,"level":"error","rank":50},"fullDescription":{"text":""},"id":"{{[A-Za-z0-9_]+}}","name":""},{"defaultConfiguration":
-// CHECK: 
{"enabled":true,"level":"error","rank":50},"fullDescription":{"text":""},"id":"{{[A-Za-z0-9_]+}}","name":""},{"defaultConfiguration":
-// CHECK: 
{"enabled":true,"level":"error","rank":50},"fullDescription":{"text":""},"id":"{{[A-Za-z0-9_]+}}","name":""},{"defaultConfiguration":
-// CHECK: 
{"enabled":true,"level":"warning","rank":-1},"fullDescription":{"text":""},"id":"{{[A-Za-z0-9_]+}}","name":""},{"defaultConfiguration":
-// CHECK: 
{"enabled":true,"level":"note","rank":-1},"fullDescription":{"text":""},"id":"{{[A-Za-z0-9_]+}}","name":""},{"defaultConfiguration":
-// CHECK: 
{"enabled":true,"level":"warning","rank":-1},"fullDescription":{"text":""},"id":"{{[A-Za-z0-9_]+}}","name":""},{"defaultConfiguration":
-// CHECK: 
{"enabled":true,"level":"error","rank":50},"fullDescription":{"text":""},"id":"{{[A-Za-z0-9_]+}}","name":""},{"defaultConfiguration":
-// CHECK: 
{"enabled":true,"level":"error","rank":50},"fullDescription":{"text":""},"id":"{{[A-Za-z0-9_]+}}","name":""},{"defaultConfiguration":
-// CHECK: {"enabled":true,"level":"error","rank":50},"fullDescription":
-// CHECK: 
{"text":""},"id":"{{[A-Za-z0-9_]+}}","name":""}],"version":"{{[0-9]+\.[0-9]+\.[0-9]+[^"
 ]*}}"}}}],"version":"2.1.0"}
-// CHECK: 2 warnings and 6 errors generated.
diff --git a/clang/test/lit.cfg.py b/clang/test/lit.cfg.py
index 52b275c095475..58e0eb8b9597b 100644
--- a/clang/test/lit.cfg.py
+++ b/clang/test/lit.cfg.py
@@ -89,7 +89,24 @@
 
 config.substitutions.append(("%PATH%", config.environment["PATH"]))
 
+sed_cmd = "/opt/freeware/bin/sed" if "system-aix" in config.available_features 
else "sed"
 
+# Filtering command for testing SARIF output against reference output.
+config.substitutions.append(
+    (
+        "%normalize_sarif",
+        f"{sed_cmd} -r '%s;%s;%s;%s'"
+        % (
+            # Replace version strings that are likely to change.
+            r's/"version": "2.1.0"/"version": "[SARIF version]"/',
+            r's/"version": ".*[0-9]+\.[0-9]+\.[0-9]+.*"/"version": "[clang 
version]"/',
+            # Strip directories from file URIs
+            r's/"file:(\/+)([^"\/]+\/)*([^"]+)"/"file:\1[...]\/\3"/',
+            # Set "length" to -1
+            r's/"length": [[:digit:]]+/"length": -1/'
+        ),
+    )
+)
 # For each occurrence of a clang tool name, replace it with the full path to
 # the build directory holding that tool.  We explicitly specify the directories
 # to search to ensure that we get the tools just built and not some random

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to