<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Jan 7, 2021 at 12:29 AM Artem Dergachev via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Author: Artem Dergachev<br>
Date: 2021-01-07T00:28:22-08:00<br>
New Revision: d2ddc694ff94743d9735aaf07edcaf6db8aaca04<br>
<br>
URL: <a href="https://github.com/llvm/llvm-project/commit/d2ddc694ff94743d9735aaf07edcaf6db8aaca04" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/d2ddc694ff94743d9735aaf07edcaf6db8aaca04</a><br>
DIFF: <a href="https://github.com/llvm/llvm-project/commit/d2ddc694ff94743d9735aaf07edcaf6db8aaca04.diff" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/d2ddc694ff94743d9735aaf07edcaf6db8aaca04.diff</a><br>
<br>
LOG: Revert "Revert "[analyzer] NFC: Move path diagnostic consumer implementations to libAnalysis.""<br>
<br>
This reverts commit 5663bf201f5c444d6fb56fb1bd471bc53c17d837.<br>
<br>
The cyclic dependency problem is addressed now.<br></blockquote><div><br>Looks like this still has a circular dependency, unfortunately:<br><br>





<p class="gmail-p1" style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,0,0)"><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures">$ grep -r include.*Analysis clang/include/clang/CrossTU</span></p>
<p class="gmail-p2" style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(219,39,218)"><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures">clang/include/clang/CrossTU/CrossTranslationUnit.h</span><span class="gmail-s2" style="font-variant-ligatures:no-common-ligatures;color:rgb(56,185,199)">:</span><span class="gmail-s3" style="font-variant-ligatures:no-common-ligatures;color:rgb(0,0,0)">#</span><span class="gmail-s4" style="font-variant-ligatures:no-common-ligatures;color:rgb(202,51,35)"><b>include "clang/Analysis/CrossTUAnalysis</b></span><span class="gmail-s3" style="font-variant-ligatures:no-common-ligatures;color:rgb(0,0,0)">Helper.h"</span></p>
<p class="gmail-p1" style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,0,0)"><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures">$ grep -r include.*CrossTU clang/lib/Analysis</span></p>
<p class="gmail-p2" style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(219,39,218)"><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures">clang/lib/Analysis/PlistHTMLPathDiagnosticConsumer.cpp</span><span class="gmail-s2" style="font-variant-ligatures:no-common-ligatures;color:rgb(56,185,199)">:</span><span class="gmail-s3" style="font-variant-ligatures:no-common-ligatures;color:rgb(0,0,0)">#</span><span class="gmail-s4" style="font-variant-ligatures:no-common-ligatures;color:rgb(202,51,35)"><b>include "clang/CrossTU</b></span><span class="gmail-s3" style="font-variant-ligatures:no-common-ligatures;color:rgb(0,0,0)">/CrossTranslationUnit.h"</span></p>
<p class="gmail-p2" style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(219,39,218)"><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures">clang/lib/Analysis/PlistPathDiagnosticConsumer.cpp</span><span class="gmail-s2" style="font-variant-ligatures:no-common-ligatures;color:rgb(56,185,199)">:</span><span class="gmail-s3" style="font-variant-ligatures:no-common-ligatures;color:rgb(0,0,0)">#</span><span class="gmail-s4" style="font-variant-ligatures:no-common-ligatures;color:rgb(202,51,35)"><b>include "clang/Analysis/CrossTU</b></span><span class="gmail-s3" style="font-variant-ligatures:no-common-ligatures;color:rgb(0,0,0)">AnalysisHelper.h"</span></p> <br>Could you revert this if it's not fairly simple to fix forward?<br><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
This is the ~fifth attempt to land this change.<br>
<br>
Added: <br>
    clang/include/clang/Analysis/CrossTUAnalysisHelper.h<br>
    clang/include/clang/Analysis/PathDiagnosticConsumers.def<br>
    clang/include/clang/Analysis/PathDiagnosticConsumers.h<br>
    clang/lib/Analysis/HTMLPathDiagnosticConsumer.cpp<br>
    clang/lib/Analysis/PlistHTMLPathDiagnosticConsumer.cpp<br>
    clang/lib/Analysis/PlistPathDiagnosticConsumer.cpp<br>
    clang/lib/Analysis/SarifPathDiagnosticConsumer.cpp<br>
    clang/lib/Analysis/TextPathDiagnosticConsumer.cpp<br>
<br>
Modified: <br>
    clang/include/clang/CrossTU/CrossTranslationUnit.h<br>
    clang/include/clang/StaticAnalyzer/Core/Analyses.def<br>
    clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h<br>
    clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h<br>
    clang/include/clang/module.modulemap<br>
    clang/lib/Analysis/CMakeLists.txt<br>
    clang/lib/CrossTU/CrossTranslationUnit.cpp<br>
    clang/lib/Frontend/CompilerInvocation.cpp<br>
    clang/lib/StaticAnalyzer/Core/CMakeLists.txt<br>
    clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp<br>
<br>
Removed: <br>
    clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h<br>
    clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp<br>
    clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp<br>
    clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp<br>
    clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp<br>
<br>
<br>
################################################################################<br>
diff  --git a/clang/include/clang/Analysis/CrossTUAnalysisHelper.h b/clang/include/clang/Analysis/CrossTUAnalysisHelper.h<br>
new file mode 100644<br>
index 000000000000..500e78ddedcf<br>
--- /dev/null<br>
+++ b/clang/include/clang/Analysis/CrossTUAnalysisHelper.h<br>
@@ -0,0 +1,41 @@<br>
+//===- CrossTUAnalysisHelper.h - Abstraction layer for CTU ------*- C++ -*-===//<br>
+//<br>
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.<br>
+// See <a href="https://llvm.org/LICENSE.txt" rel="noreferrer" target="_blank">https://llvm.org/LICENSE.txt</a> for license information.<br>
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+#ifndef LLVM_CLANG_ANALYSIS_CROSS_TU_HELPER_H<br>
+#define LLVM_CLANG_ANALYSIS_CROSS_TU_HELPER_H<br>
+<br>
+#include "llvm/ADT/Optional.h"<br>
+#include "clang/Basic/SourceManager.h"<br>
+<br>
+namespace clang {<br>
+<br>
+class ASTUnit;<br>
+<br>
+/// This class is an abstract interface acting as a bridge between<br>
+/// an analysis that requires lookups across translation units (a user<br>
+/// of that interface) and the facility that implements such lookups<br>
+/// (an implementation of that interface). This is useful to break direct<br>
+/// link-time dependencies between the (possibly shared) libraries in which<br>
+/// the user and the implementation live.<br>
+class CrossTUAnalysisHelper {<br>
+public:<br>
+  /// Determine the original source location in the original TU for an<br>
+  /// imported source location.<br>
+  /// \p ToLoc Source location in the imported-to AST.<br>
+  /// \return Source location in the imported-from AST and the corresponding<br>
+  /// ASTUnit object (the AST was loaded from a file using an internal ASTUnit<br>
+  /// object that is returned here).<br>
+  /// If any error happens (ToLoc is a non-imported source location) empty is<br>
+  /// returned.<br>
+  virtual llvm::Optional<std::pair<SourceLocation /*FromLoc*/, Preprocessor *>><br>
+  getImportedFromSourceLocationWithPreprocessor(SourceLocation ToLoc) const = 0;<br>
+<br>
+  virtual ~CrossTUAnalysisHelper() {}<br>
+};<br>
+} // namespace clang<br>
+<br>
+#endif // LLVM_CLANG_ANALYSIS_CROSS_TU_HELPER_H<br>
<br>
diff  --git a/clang/include/clang/Analysis/PathDiagnosticConsumers.def b/clang/include/clang/Analysis/PathDiagnosticConsumers.def<br>
new file mode 100644<br>
index 000000000000..33d2072fcf31<br>
--- /dev/null<br>
+++ b/clang/include/clang/Analysis/PathDiagnosticConsumers.def<br>
@@ -0,0 +1,50 @@<br>
+//===-- PathDiagnosticConsumers.def - Visualizing warnings ------*- C++ -*-===//<br>
+//<br>
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.<br>
+// See <a href="https://llvm.org/LICENSE.txt" rel="noreferrer" target="_blank">https://llvm.org/LICENSE.txt</a> for license information.<br>
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This file defines the set of path diagnostic consumers - objects that<br>
+// implement <br>
diff erent representations of static analysis results.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef ANALYSIS_DIAGNOSTICS<br>
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)<br>
+#endif<br>
+<br>
+ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML",<br>
+                     createHTMLDiagnosticConsumer)<br>
+<br>
+ANALYSIS_DIAGNOSTICS(<br>
+    HTML_SINGLE_FILE, "html-single-file",<br>
+    "Output analysis results using HTML (not allowing for multi-file bugs)",<br>
+    createHTMLSingleFileDiagnosticConsumer)<br>
+<br>
+ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists",<br>
+                     createPlistDiagnosticConsumer)<br>
+<br>
+ANALYSIS_DIAGNOSTICS(<br>
+    PLIST_MULTI_FILE, "plist-multi-file",<br>
+    "Output analysis results using Plists (allowing for multi-file bugs)",<br>
+    createPlistMultiFileDiagnosticConsumer)<br>
+<br>
+ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html",<br>
+                     "Output analysis results using HTML wrapped with Plists",<br>
+                     createPlistHTMLDiagnosticConsumer)<br>
+<br>
+ANALYSIS_DIAGNOSTICS(SARIF, "sarif", "Output analysis results in a SARIF file",<br>
+                     createSarifDiagnosticConsumer)<br>
+<br>
+ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results to stderr",<br>
+                     createTextPathDiagnosticConsumer)<br>
+<br>
+ANALYSIS_DIAGNOSTICS(TEXT_MINIMAL, "text-minimal",<br>
+                     "Emits minimal diagnostics to stderr, stating only the "<br>
+                     "warning message and the associated notes. Usually "<br>
+                     "used in addition to other analysis types",<br>
+                     createTextMinimalPathDiagnosticConsumer)<br>
+<br>
+#undef ANALYSIS_DIAGNOSTICS<br>
<br>
diff  --git a/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h b/clang/include/clang/Analysis/PathDiagnosticConsumers.h<br>
similarity index 78%<br>
rename from clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h<br>
rename to clang/include/clang/Analysis/PathDiagnosticConsumers.h<br>
index f40f88eb32ff..fde2e3498216 100644<br>
--- a/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h<br>
+++ b/clang/include/clang/Analysis/PathDiagnosticConsumers.h<br>
@@ -18,25 +18,24 @@<br>
 #include <string><br>
 #include <vector><br>
<br>
+#include "clang/Analysis/PathDiagnostic.h"<br>
+<br>
 namespace clang {<br>
<br>
 class AnalyzerOptions;<br>
 class Preprocessor;<br>
-namespace cross_tu {<br>
-class CrossTranslationUnitContext;<br>
-}<br>
+class CrossTUAnalysisHelper;<br>
<br>
 namespace ento {<br>
<br>
 class PathDiagnosticConsumer;<br>
-typedef std::vector<PathDiagnosticConsumer*> PathDiagnosticConsumers;<br>
+typedef std::vector<PathDiagnosticConsumer *> PathDiagnosticConsumers;<br>
<br>
 #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)                    \<br>
   void CREATEFN(PathDiagnosticConsumerOptions Diagopts,                        \<br>
                 PathDiagnosticConsumers &C, const std::string &Prefix,         \<br>
-                const Preprocessor &PP,                                        \<br>
-                const cross_tu::CrossTranslationUnitContext &CTU);<br>
-#include "clang/StaticAnalyzer/Core/Analyses.def"<br>
+                const Preprocessor &PP, const CrossTUAnalysisHelper &CTU);<br>
+#include "clang/Analysis/PathDiagnosticConsumers.def"<br>
<br>
 } // end 'ento' namespace<br>
 } // end 'clang' namespace<br>
<br>
diff  --git a/clang/include/clang/CrossTU/CrossTranslationUnit.h b/clang/include/clang/CrossTU/CrossTranslationUnit.h<br>
index 027c6f16430b..21201f637833 100644<br>
--- a/clang/include/clang/CrossTU/CrossTranslationUnit.h<br>
+++ b/clang/include/clang/CrossTU/CrossTranslationUnit.h<br>
@@ -14,6 +14,7 @@<br>
 #ifndef LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H<br>
 #define LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H<br>
<br>
+#include "clang/Analysis/CrossTUAnalysisHelper.h"<br>
 #include "clang/AST/ASTImporterSharedState.h"<br>
 #include "clang/Basic/LLVM.h"<br>
 #include "llvm/ADT/DenseMap.h"<br>
@@ -120,10 +121,10 @@ bool containsConst(const VarDecl *VD, const ASTContext &ACtx);<br>
 /// the locations of the AST files for each definition.<br>
 ///<br>
 /// Note that this class also implements caching.<br>
-class CrossTranslationUnitContext {<br>
+class CrossTranslationUnitContext : public CrossTUAnalysisHelper {<br>
 public:<br>
   CrossTranslationUnitContext(CompilerInstance &CI);<br>
-  ~CrossTranslationUnitContext();<br>
+  ~CrossTranslationUnitContext() override;<br>
<br>
   /// This function loads a function or variable definition from an<br>
   ///        external AST file and merges it into the original AST.<br>
@@ -186,12 +187,24 @@ class CrossTranslationUnitContext {<br>
   /// imported source location.<br>
   /// \p ToLoc Source location in the imported-to AST.<br>
   /// \return Source location in the imported-from AST and the corresponding<br>
-  /// ASTUnit object (the AST was loaded from a file using an internal ASTUnit<br>
+  /// ASTUnit object (the AST was loaded from a file using an internal ASTUni<br>
   /// object that is returned here).<br>
   /// If any error happens (ToLoc is a non-imported source location) empty is<br>
   /// returned.<br>
   llvm::Optional<std::pair<SourceLocation /*FromLoc*/, ASTUnit *>><br>
-  getImportedFromSourceLocation(const clang::SourceLocation &ToLoc) const;<br>
+  getImportedFromSourceLocation(SourceLocation ToLoc) const;<br>
+<br>
+  /// Determine the original source location in the original TU for an<br>
+  /// imported source location.<br>
+  /// \p ToLoc Source location in the imported-to AST.<br>
+  /// \return Source location in the imported-from AST and the Preprocessor<br>
+  /// corresponding to the AST unit that originally contained the imported-from<br>
+  /// source location.<br>
+  /// If any error happens (ToLoc is a non-imported source location) empty is<br>
+  /// returned.<br>
+  llvm::Optional<std::pair<SourceLocation /*FromLoc*/, Preprocessor *>><br>
+  getImportedFromSourceLocationWithPreprocessor(<br>
+      SourceLocation ToLoc) const override;<br>
<br>
 private:<br>
   using ImportedFileIDMap =<br>
<br>
diff  --git a/clang/include/clang/StaticAnalyzer/Core/Analyses.def b/clang/include/clang/StaticAnalyzer/Core/Analyses.def<br>
index c4e5f5be6fd7..2e98cbba4c9e 100644<br>
--- a/clang/include/clang/StaticAnalyzer/Core/Analyses.def<br>
+++ b/clang/include/clang/StaticAnalyzer/Core/Analyses.def<br>
@@ -28,42 +28,6 @@ ANALYSIS_CONSTRAINTS(RangeConstraints, "range",<br>
 ANALYSIS_CONSTRAINTS(Z3Constraints, "z3", "Use Z3 contraint solver",<br>
                      CreateZ3ConstraintManager)<br>
<br>
-#ifndef ANALYSIS_DIAGNOSTICS<br>
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)<br>
-#endif<br>
-<br>
-ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML",<br>
-                     createHTMLDiagnosticConsumer)<br>
-<br>
-ANALYSIS_DIAGNOSTICS(<br>
-    HTML_SINGLE_FILE, "html-single-file",<br>
-    "Output analysis results using HTML (not allowing for multi-file bugs)",<br>
-    createHTMLSingleFileDiagnosticConsumer)<br>
-<br>
-ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists",<br>
-                     createPlistDiagnosticConsumer)<br>
-<br>
-ANALYSIS_DIAGNOSTICS(<br>
-    PLIST_MULTI_FILE, "plist-multi-file",<br>
-    "Output analysis results using Plists (allowing for multi-file bugs)",<br>
-    createPlistMultiFileDiagnosticConsumer)<br>
-<br>
-ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html",<br>
-                     "Output analysis results using HTML wrapped with Plists",<br>
-                     createPlistHTMLDiagnosticConsumer)<br>
-<br>
-ANALYSIS_DIAGNOSTICS(SARIF, "sarif", "Output analysis results in a SARIF file",<br>
-                     createSarifDiagnosticConsumer)<br>
-<br>
-ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results to stderr",<br>
-                     createTextPathDiagnosticConsumer)<br>
-<br>
-ANALYSIS_DIAGNOSTICS(TEXT_MINIMAL, "text-minimal",<br>
-                     "Emits minimal diagnostics to stderr, stating only the "<br>
-                     "warning message and the associated notes. Usually "<br>
-                     "used in addition to other analysis types",<br>
-                     createTextMinimalPathDiagnosticConsumer)<br>
-<br>
 #ifndef ANALYSIS_PURGE<br>
 #define ANALYSIS_PURGE(NAME, CMDFLAG, DESC)<br>
 #endif<br>
@@ -91,7 +55,6 @@ ANALYSIS_INLINING_MODE(<br>
<br>
 #undef ANALYSIS_STORE<br>
 #undef ANALYSIS_CONSTRAINTS<br>
-#undef ANALYSIS_DIAGNOSTICS<br>
 #undef ANALYSIS_PURGE<br>
 #undef ANALYSIS_INLINING_MODE<br>
 #undef ANALYSIS_IPA<br>
<br>
diff  --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h<br>
index ccf35e0a81ec..0dd2c86c5ca9 100644<br>
--- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h<br>
+++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h<br>
@@ -58,7 +58,7 @@ NumConstraints<br>
 ///  analysis results.<br>
 enum AnalysisDiagClients {<br>
 #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) PD_##NAME,<br>
-#include "clang/StaticAnalyzer/Core/Analyses.def"<br>
+#include "clang/Analysis/PathDiagnosticConsumers.def"<br>
 PD_NONE,<br>
 NUM_ANALYSIS_DIAG_CLIENTS<br>
 };<br>
<br>
diff  --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h<br>
index c76e9c0326af..7e8b9de3a942 100644<br>
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h<br>
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h<br>
@@ -16,10 +16,10 @@<br>
<br>
 #include "clang/Analysis/AnalysisDeclContext.h"<br>
 #include "clang/Analysis/PathDiagnostic.h"<br>
+#include "clang/Analysis/PathDiagnosticConsumers.h"<br>
 #include "clang/Lex/Preprocessor.h"<br>
 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"<br>
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"<br>
-#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"<br>
<br>
 namespace clang {<br>
<br>
<br>
diff  --git a/clang/include/clang/module.modulemap b/clang/include/clang/module.modulemap<br>
index 332e533f0347..ec396e1532e0 100644<br>
--- a/clang/include/clang/module.modulemap<br>
+++ b/clang/include/clang/module.modulemap<br>
@@ -3,6 +3,7 @@ module Clang_Analysis {<br>
   umbrella "Analysis"<br>
<br>
   textual header "Analysis/Analyses/ThreadSafetyOps.def"<br>
+  textual header "Analysis/PathDiagnosticConsumers.def"<br>
<br>
   module * { export * }<br>
<br>
<br>
diff  --git a/clang/lib/Analysis/CMakeLists.txt b/clang/lib/Analysis/CMakeLists.txt<br>
index ed626a6e130c..94c6e322e02b 100644<br>
--- a/clang/lib/Analysis/CMakeLists.txt<br>
+++ b/clang/lib/Analysis/CMakeLists.txt<br>
@@ -18,14 +18,19 @@ add_clang_library(clangAnalysis<br>
   CodeInjector.cpp<br>
   Dominators.cpp<br>
   ExprMutationAnalyzer.cpp<br>
+  HTMLPathDiagnosticConsumer.cpp<br>
   IssueHash.cpp<br>
   LiveVariables.cpp<br>
   ObjCNoReturn.cpp<br>
   PathDiagnostic.cpp<br>
+  PlistPathDiagnosticConsumer.cpp<br>
+  PlistHTMLPathDiagnosticConsumer.cpp<br>
   PostOrderCFGView.cpp<br>
   ProgramPoint.cpp<br>
   ReachableCode.cpp<br>
   RetainSummaryManager.cpp<br>
+  SarifPathDiagnosticConsumer.cpp<br>
+  TextPathDiagnosticConsumer.cpp<br>
   ThreadSafety.cpp<br>
   ThreadSafetyCommon.cpp<br>
   ThreadSafetyLogical.cpp<br>
@@ -37,6 +42,8 @@ add_clang_library(clangAnalysis<br>
   clangASTMatchers<br>
   clangBasic<br>
   clangLex<br>
+  clangRewrite<br>
+  clangToolingCore<br>
<br>
   DEPENDS<br>
   omp_gen<br>
<br>
diff  --git a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/clang/lib/Analysis/HTMLPathDiagnosticConsumer.cpp<br>
similarity index 91%<br>
rename from clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp<br>
rename to clang/lib/Analysis/HTMLPathDiagnosticConsumer.cpp<br>
index 149459cf986a..fb60819b1c15 100644<br>
--- a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp<br>
+++ b/clang/lib/Analysis/HTMLPathDiagnosticConsumer.cpp<br>
@@ -1,4 +1,4 @@<br>
-//===- HTMLDiagnostics.cpp - HTML Diagnostics for Paths -------------------===//<br>
+//===- HTMLPathDiagnosticConsumer.cpp - HTML Diagnostics for Paths --------===//<br>
 //<br>
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.<br>
 // See <a href="https://llvm.org/LICENSE.txt" rel="noreferrer" target="_blank">https://llvm.org/LICENSE.txt</a> for license information.<br>
@@ -6,12 +6,13 @@<br>
 //<br>
 //===----------------------------------------------------------------------===//<br>
 //<br>
-//  This file defines the HTMLDiagnostics object.<br>
+//  This file defines the HTMLPathDiagnosticConsumer object.<br>
 //<br>
 //===----------------------------------------------------------------------===//<br>
<br>
 #include "clang/Analysis/IssueHash.h"<br>
 #include "clang/Analysis/PathDiagnostic.h"<br>
+#include "clang/Analysis/PathDiagnosticConsumers.h"<br>
 #include "clang/AST/Decl.h"<br>
 #include "clang/AST/DeclBase.h"<br>
 #include "clang/AST/Stmt.h"<br>
@@ -24,7 +25,6 @@<br>
 #include "clang/Lex/Token.h"<br>
 #include "clang/Rewrite/Core/HTMLRewrite.h"<br>
 #include "clang/Rewrite/Core/Rewriter.h"<br>
-#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"<br>
 #include "llvm/ADT/ArrayRef.h"<br>
 #include "llvm/ADT/SmallString.h"<br>
 #include "llvm/ADT/StringRef.h"<br>
@@ -50,13 +50,17 @@<br>
 using namespace clang;<br>
 using namespace ento;<br>
<br>
+namespace clang {<br>
+class CrossTUAnalysisHelper;<br>
+}<br>
+<br>
 //===----------------------------------------------------------------------===//<br>
 // Boilerplate.<br>
 //===----------------------------------------------------------------------===//<br>
<br>
 namespace {<br>
<br>
-class HTMLDiagnostics : public PathDiagnosticConsumer {<br>
+class HTMLPathDiagnosticConsumer : public PathDiagnosticConsumer {<br>
   PathDiagnosticConsumerOptions DiagOpts;<br>
   std::string Directory;<br>
   bool createdDir = false;<br>
@@ -65,20 +69,18 @@ class HTMLDiagnostics : public PathDiagnosticConsumer {<br>
   const bool SupportsCrossFileDiagnostics;<br>
<br>
 public:<br>
-  HTMLDiagnostics(PathDiagnosticConsumerOptions DiagOpts,<br>
-                  const std::string &OutputDir, const Preprocessor &pp,<br>
-                  bool supportsMultipleFiles)<br>
-      : DiagOpts(std::move(DiagOpts)), Directory(OutputDir), PP(pp),<br>
-        SupportsCrossFileDiagnostics(supportsMultipleFiles) {}<br>
+  HTMLPathDiagnosticConsumer(PathDiagnosticConsumerOptions DiagOpts,<br>
+                             const std::string &OutputDir,<br>
+                             const Preprocessor &PP, bool SupportsMultipleFiles)<br>
+      : DiagOpts(std::move(DiagOpts)), Directory(OutputDir), PP(PP),<br>
+        SupportsCrossFileDiagnostics(SupportsMultipleFiles) {}<br>
<br>
-  ~HTMLDiagnostics() override { FlushDiagnostics(nullptr); }<br>
+  ~HTMLPathDiagnosticConsumer() override { FlushDiagnostics(nullptr); }<br>
<br>
   void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,<br>
                             FilesMade *filesMade) override;<br>
<br>
-  StringRef getName() const override {<br>
-    return "HTMLDiagnostics";<br>
-  }<br>
+  StringRef getName() const override { return "HTMLPathDiagnosticConsumer"; }<br>
<br>
   bool supportsCrossFileDiagnostics() const override {<br>
     return SupportsCrossFileDiagnostics;<br>
@@ -135,7 +137,7 @@ class HTMLDiagnostics : public PathDiagnosticConsumer {<br>
 void ento::createHTMLDiagnosticConsumer(<br>
     PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,<br>
     const std::string &OutputDir, const Preprocessor &PP,<br>
-    const cross_tu::CrossTranslationUnitContext &CTU) {<br>
+    const CrossTUAnalysisHelper &CTU) {<br>
<br>
   // FIXME: HTML is currently our default output type, but if the output<br>
   // directory isn't specified, it acts like if it was in the minimal text<br>
@@ -148,47 +150,36 @@ void ento::createHTMLDiagnosticConsumer(<br>
   if (OutputDir.empty())<br>
     return;<br>
<br>
-  C.push_back(new HTMLDiagnostics(std::move(DiagOpts), OutputDir, PP, true));<br>
+  C.push_back(<br>
+      new HTMLPathDiagnosticConsumer(std::move(DiagOpts), OutputDir, PP, true));<br>
 }<br>
<br>
 void ento::createHTMLSingleFileDiagnosticConsumer(<br>
     PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,<br>
     const std::string &OutputDir, const Preprocessor &PP,<br>
-    const cross_tu::CrossTranslationUnitContext &CTU) {<br>
+    const CrossTUAnalysisHelper &CTU) {<br>
   createTextMinimalPathDiagnosticConsumer(DiagOpts, C, OutputDir, PP, CTU);<br>
<br>
   // TODO: Emit an error here.<br>
   if (OutputDir.empty())<br>
     return;<br>
<br>
-  C.push_back(new HTMLDiagnostics(std::move(DiagOpts), OutputDir, PP, false));<br>
-}<br>
-<br>
-void ento::createPlistHTMLDiagnosticConsumer(<br>
-    PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,<br>
-    const std::string &prefix, const Preprocessor &PP,<br>
-    const cross_tu::CrossTranslationUnitContext &CTU) {<br>
-  createHTMLDiagnosticConsumer(<br>
-      DiagOpts, C, std::string(llvm::sys::path::parent_path(prefix)), PP,<br>
-      CTU);<br>
-  createPlistMultiFileDiagnosticConsumer(DiagOpts, C, prefix, PP, CTU);<br>
-  createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, prefix, PP,<br>
-                                          CTU);<br>
+  C.push_back(new HTMLPathDiagnosticConsumer(std::move(DiagOpts), OutputDir, PP,<br>
+                                             false));<br>
 }<br>
<br>
 //===----------------------------------------------------------------------===//<br>
 // Report processing.<br>
 //===----------------------------------------------------------------------===//<br>
<br>
-void HTMLDiagnostics::FlushDiagnosticsImpl(<br>
-  std::vector<const PathDiagnostic *> &Diags,<br>
-  FilesMade *filesMade) {<br>
+void HTMLPathDiagnosticConsumer::FlushDiagnosticsImpl(<br>
+    std::vector<const PathDiagnostic *> &Diags, FilesMade *filesMade) {<br>
   for (const auto Diag : Diags)<br>
     ReportDiag(*Diag, filesMade);<br>
 }<br>
<br>
-void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,<br>
-                                 FilesMade *filesMade) {<br>
+void HTMLPathDiagnosticConsumer::ReportDiag(const PathDiagnostic &D,<br>
+                                            FilesMade *filesMade) {<br>
   // Create the HTML directory if it is missing.<br>
   if (!createdDir) {<br>
     createdDir = true;<br>
@@ -296,8 +287,11 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,<br>
   os << report;<br>
 }<br>
<br>
-std::string HTMLDiagnostics::GenerateHTML(const PathDiagnostic& D, Rewriter &R,<br>
-    const SourceManager& SMgr, const PathPieces& path, const char *declName) {<br>
+std::string HTMLPathDiagnosticConsumer::GenerateHTML(const PathDiagnostic &D,<br>
+                                                     Rewriter &R,<br>
+                                                     const SourceManager &SMgr,<br>
+                                                     const PathPieces &path,<br>
+                                                     const char *declName) {<br>
   // Rewrite source files as HTML for every new file the path crosses<br>
   std::vector<FileID> FileIDs;<br>
   for (auto I : path) {<br>
@@ -369,9 +363,8 @@ std::string HTMLDiagnostics::GenerateHTML(const PathDiagnostic& D, Rewriter &R,<br>
   return os.str();<br>
 }<br>
<br>
-void HTMLDiagnostics::dumpCoverageData(<br>
-    const PathDiagnostic &D,<br>
-    const PathPieces &path,<br>
+void HTMLPathDiagnosticConsumer::dumpCoverageData(<br>
+    const PathDiagnostic &D, const PathPieces &path,<br>
     llvm::raw_string_ostream &os) {<br>
<br>
   const FilesToLineNumsMap &ExecutedLines = D.getExecutedLines();<br>
@@ -395,8 +388,8 @@ void HTMLDiagnostics::dumpCoverageData(<br>
   os << "};";<br>
 }<br>
<br>
-std::string HTMLDiagnostics::showRelevantLinesJavascript(<br>
-      const PathDiagnostic &D, const PathPieces &path) {<br>
+std::string HTMLPathDiagnosticConsumer::showRelevantLinesJavascript(<br>
+    const PathDiagnostic &D, const PathPieces &path) {<br>
   std::string s;<br>
   llvm::raw_string_ostream os(s);<br>
   os << "<script type='text/javascript'>\n";<br>
@@ -460,9 +453,10 @@ document.addEventListener("DOMContentLoaded", function() {<br>
   return os.str();<br>
 }<br>
<br>
-void HTMLDiagnostics::FinalizeHTML(const PathDiagnostic& D, Rewriter &R,<br>
-    const SourceManager& SMgr, const PathPieces& path, FileID FID,<br>
-    const FileEntry *Entry, const char *declName) {<br>
+void HTMLPathDiagnosticConsumer::FinalizeHTML(<br>
+    const PathDiagnostic &D, Rewriter &R, const SourceManager &SMgr,<br>
+    const PathPieces &path, FileID FID, const FileEntry *Entry,<br>
+    const char *declName) {<br>
   // This is a cludge; basically we want to append either the full<br>
   // working directory if we have no directory information.  This is<br>
   // a work in progress.<br>
@@ -607,7 +601,7 @@ void HTMLDiagnostics::FinalizeHTML(const PathDiagnostic& D, Rewriter &R,<br>
   html::AddHeaderFooterInternalBuiltinCSS(R, FID, Entry->getName());<br>
 }<br>
<br>
-StringRef HTMLDiagnostics::showHelpJavascript() {<br>
+StringRef HTMLPathDiagnosticConsumer::showHelpJavascript() {<br>
   return R"<<<(<br>
 <script type='text/javascript'><br>
<br>
@@ -690,8 +684,9 @@ static void HandlePopUpPieceEndTag(Rewriter &R,<br>
   }<br>
 }<br>
<br>
-void HTMLDiagnostics::RewriteFile(Rewriter &R,<br>
-                                  const PathPieces& path, FileID FID) {<br>
+void HTMLPathDiagnosticConsumer::RewriteFile(Rewriter &R,<br>
+                                             const PathPieces &path,<br>
+                                             FileID FID) {<br>
   // Process the path.<br>
   // Maintain the counts of extra note pieces separately.<br>
   unsigned TotalPieces = path.size();<br>
@@ -769,10 +764,9 @@ void HTMLDiagnostics::RewriteFile(Rewriter &R,<br>
   html::HighlightMacros(R, FID, PP);<br>
 }<br>
<br>
-void HTMLDiagnostics::HandlePiece(Rewriter &R, FileID BugFileID,<br>
-                                  const PathDiagnosticPiece &P,<br>
-                                  const std::vector<SourceRange> &PopUpRanges,<br>
-                                  unsigned num, unsigned max) {<br>
+void HTMLPathDiagnosticConsumer::HandlePiece(<br>
+    Rewriter &R, FileID BugFileID, const PathDiagnosticPiece &P,<br>
+    const std::vector<SourceRange> &PopUpRanges, unsigned num, unsigned max) {<br>
   // For now, just draw a box above the line in question, and emit the<br>
   // warning.<br>
   FullSourceLoc Pos = P.getLocation().asLocation();<br>
@@ -1004,9 +998,8 @@ static void EmitAlphaCounter(raw_ostream &os, unsigned n) {<br>
   os << char('a' + x);<br>
 }<br>
<br>
-unsigned HTMLDiagnostics::ProcessMacroPiece(raw_ostream &os,<br>
-                                            const PathDiagnosticMacroPiece& P,<br>
-                                            unsigned num) {<br>
+unsigned HTMLPathDiagnosticConsumer::ProcessMacroPiece(<br>
+    raw_ostream &os, const PathDiagnosticMacroPiece &P, unsigned num) {<br>
   for (const auto &subPiece : P.subPieces) {<br>
     if (const auto *MP = dyn_cast<PathDiagnosticMacroPiece>(subPiece.get())) {<br>
       num = ProcessMacroPiece(os, *MP, num);<br>
@@ -1028,10 +1021,10 @@ unsigned HTMLDiagnostics::ProcessMacroPiece(raw_ostream &os,<br>
   return num;<br>
 }<br>
<br>
-void HTMLDiagnostics::HighlightRange(Rewriter& R, FileID BugFileID,<br>
-                                     SourceRange Range,<br>
-                                     const char *HighlightStart,<br>
-                                     const char *HighlightEnd) {<br>
+void HTMLPathDiagnosticConsumer::HighlightRange(Rewriter &R, FileID BugFileID,<br>
+                                                SourceRange Range,<br>
+                                                const char *HighlightStart,<br>
+                                                const char *HighlightEnd) {<br>
   SourceManager &SM = R.getSourceMgr();<br>
   const LangOptions &LangOpts = R.getLangOpts();<br>
<br>
@@ -1066,7 +1059,7 @@ void HTMLDiagnostics::HighlightRange(Rewriter& R, FileID BugFileID,<br>
   html::HighlightRange(R, InstantiationStart, E, HighlightStart, HighlightEnd);<br>
 }<br>
<br>
-StringRef HTMLDiagnostics::generateKeyboardNavigationJavascript() {<br>
+StringRef HTMLPathDiagnosticConsumer::generateKeyboardNavigationJavascript() {<br>
   return R"<<<(<br>
 <script type='text/javascript'><br>
 var digitMatcher = new RegExp("[0-9]+");<br>
<br>
diff  --git a/clang/lib/Analysis/PlistHTMLPathDiagnosticConsumer.cpp b/clang/lib/Analysis/PlistHTMLPathDiagnosticConsumer.cpp<br>
new file mode 100644<br>
index 000000000000..4a9d2fe84e38<br>
--- /dev/null<br>
+++ b/clang/lib/Analysis/PlistHTMLPathDiagnosticConsumer.cpp<br>
@@ -0,0 +1,35 @@<br>
+//===--- PlistHTMLDiagnostics.cpp - The Plist-HTML Diagnostic Consumer. ---===//<br>
+//<br>
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.<br>
+// See <a href="https://llvm.org/LICENSE.txt" rel="noreferrer" target="_blank">https://llvm.org/LICENSE.txt</a> for license information.<br>
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This diagnostic consumer produces both the HTML output and the Plist output.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "clang/Analysis/PathDiagnostic.h"<br>
+#include "clang/Analysis/PathDiagnosticConsumers.h"<br>
+#include "clang/Basic/SourceManager.h"<br>
+#include "clang/CrossTU/CrossTranslationUnit.h"<br>
+#include "clang/Lex/Preprocessor.h"<br>
+<br>
+using namespace clang;<br>
+using namespace ento;<br>
+<br>
+namespace clang {<br>
+class CrossTUAnalysisHelper;<br>
+}<br>
+<br>
+void ento::createPlistHTMLDiagnosticConsumer(<br>
+    PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,<br>
+    const std::string &Prefix, const Preprocessor &PP,<br>
+    const CrossTUAnalysisHelper &CTU) {<br>
+  createHTMLDiagnosticConsumer(<br>
+      DiagOpts, C, std::string(llvm::sys::path::parent_path(Prefix)), PP, CTU);<br>
+  createPlistMultiFileDiagnosticConsumer(DiagOpts, C, Prefix, PP, CTU);<br>
+  createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, Prefix, PP,<br>
+                                          CTU);<br>
+}<br>
<br>
diff  --git a/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/clang/lib/Analysis/PlistPathDiagnosticConsumer.cpp<br>
similarity index 96%<br>
rename from clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp<br>
rename to clang/lib/Analysis/PlistPathDiagnosticConsumer.cpp<br>
index 35e320c7755f..52a488162dba 100644<br>
--- a/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp<br>
+++ b/clang/lib/Analysis/PlistPathDiagnosticConsumer.cpp<br>
@@ -1,4 +1,4 @@<br>
-//===--- PlistDiagnostics.cpp - Plist Diagnostics for Paths -----*- C++ -*-===//<br>
+//===--- PlistPathDiagnosticConsumer.cpp - Plist Diagnostics ----*- C++ -*-===//<br>
 //<br>
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.<br>
 // See <a href="https://llvm.org/LICENSE.txt" rel="noreferrer" target="_blank">https://llvm.org/LICENSE.txt</a> for license information.<br>
@@ -6,22 +6,21 @@<br>
 //<br>
 //===----------------------------------------------------------------------===//<br>
 //<br>
-//  This file defines the PlistDiagnostics object.<br>
+//  This file defines the PlistPathDiagnosticConsumer object.<br>
 //<br>
 //===----------------------------------------------------------------------===//<br>
<br>
+#include "clang/Analysis/CrossTUAnalysisHelper.h"<br>
 #include "clang/Analysis/IssueHash.h"<br>
 #include "clang/Analysis/PathDiagnostic.h"<br>
+#include "clang/Analysis/PathDiagnosticConsumers.h"<br>
 #include "clang/Basic/FileManager.h"<br>
 #include "clang/Basic/PlistSupport.h"<br>
 #include "clang/Basic/SourceManager.h"<br>
 #include "clang/Basic/Version.h"<br>
-#include "clang/CrossTU/CrossTranslationUnit.h"<br>
-#include "clang/Frontend/ASTUnit.h"<br>
 #include "clang/Lex/Preprocessor.h"<br>
 #include "clang/Lex/TokenConcatenation.h"<br>
 #include "clang/Rewrite/Core/HTMLRewrite.h"<br>
-#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"<br>
 #include "llvm/ADT/SmallPtrSet.h"<br>
 #include "llvm/ADT/SmallVector.h"<br>
 #include "llvm/ADT/Statistic.h"<br>
@@ -38,29 +37,29 @@ using namespace markup;<br>
 //===----------------------------------------------------------------------===//<br>
<br>
 namespace {<br>
-  class PlistDiagnostics : public PathDiagnosticConsumer {<br>
+  class PlistPathDiagnosticConsumer : public PathDiagnosticConsumer {<br>
     PathDiagnosticConsumerOptions DiagOpts;<br>
     const std::string OutputFile;<br>
     const Preprocessor &PP;<br>
-    const cross_tu::CrossTranslationUnitContext &CTU;<br>
+    const CrossTUAnalysisHelper &CTU;<br>
     const bool SupportsCrossFileDiagnostics;<br>
<br>
     void printBugPath(llvm::raw_ostream &o, const FIDMap &FM,<br>
                       const PathPieces &Path);<br>
<br>
   public:<br>
-    PlistDiagnostics(PathDiagnosticConsumerOptions DiagOpts,<br>
+    PlistPathDiagnosticConsumer(PathDiagnosticConsumerOptions DiagOpts,<br>
                      const std::string &OutputFile, const Preprocessor &PP,<br>
-                     const cross_tu::CrossTranslationUnitContext &CTU,<br>
+                     const CrossTUAnalysisHelper &CTU,<br>
                      bool supportsMultipleFiles);<br>
<br>
-    ~PlistDiagnostics() override {}<br>
+    ~PlistPathDiagnosticConsumer() override {}<br>
<br>
     void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,<br>
                               FilesMade *filesMade) override;<br>
<br>
     StringRef getName() const override {<br>
-      return "PlistDiagnostics";<br>
+      return "PlistPathDiagnosticConsumer";<br>
     }<br>
<br>
     PathGenerationScheme getGenerationScheme() const override {<br>
@@ -79,13 +78,13 @@ namespace {<br>
 class PlistPrinter {<br>
   const FIDMap& FM;<br>
   const Preprocessor &PP;<br>
-  const cross_tu::CrossTranslationUnitContext &CTU;<br>
+  const CrossTUAnalysisHelper &CTU;<br>
   llvm::SmallVector<const PathDiagnosticMacroPiece *, 0> MacroPieces;<br>
<br>
 public:<br>
   PlistPrinter(const FIDMap& FM,<br>
                const Preprocessor &PP,<br>
-               const cross_tu::CrossTranslationUnitContext &CTU)<br>
+               const CrossTUAnalysisHelper &CTU)<br>
     : FM(FM), PP(PP), CTU(CTU) {<br>
   }<br>
<br>
@@ -175,7 +174,7 @@ static void printCoverage(const PathDiagnostic *D,<br>
<br>
 static ExpansionInfo<br>
 getExpandedMacro(SourceLocation MacroLoc, const Preprocessor &PP,<br>
-                 const cross_tu::CrossTranslationUnitContext &CTU);<br>
+                 const CrossTUAnalysisHelper &CTU);<br>
<br>
 //===----------------------------------------------------------------------===//<br>
 // Methods of PlistPrinter.<br>
@@ -516,12 +515,12 @@ static void printCoverage(const PathDiagnostic *D,<br>
 }<br>
<br>
 //===----------------------------------------------------------------------===//<br>
-// Methods of PlistDiagnostics.<br>
+// Methods of PlistPathDiagnosticConsumer.<br>
 //===----------------------------------------------------------------------===//<br>
<br>
-PlistDiagnostics::PlistDiagnostics(<br>
+PlistPathDiagnosticConsumer::PlistPathDiagnosticConsumer(<br>
     PathDiagnosticConsumerOptions DiagOpts, const std::string &output,<br>
-    const Preprocessor &PP, const cross_tu::CrossTranslationUnitContext &CTU,<br>
+    const Preprocessor &PP, const CrossTUAnalysisHelper &CTU,<br>
     bool supportsMultipleFiles)<br>
     : DiagOpts(std::move(DiagOpts)), OutputFile(output), PP(PP), CTU(CTU),<br>
       SupportsCrossFileDiagnostics(supportsMultipleFiles) {<br>
@@ -532,14 +531,14 @@ PlistDiagnostics::PlistDiagnostics(<br>
 void ento::createPlistDiagnosticConsumer(<br>
     PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,<br>
     const std::string &OutputFile, const Preprocessor &PP,<br>
-    const cross_tu::CrossTranslationUnitContext &CTU) {<br>
+    const CrossTUAnalysisHelper &CTU) {<br>
<br>
   // TODO: Emit an error here.<br>
   if (OutputFile.empty())<br>
     return;<br>
<br>
-  C.push_back(new PlistDiagnostics(DiagOpts, OutputFile, PP, CTU,<br>
-                                   /*supportsMultipleFiles=*/false));<br>
+  C.push_back(new PlistPathDiagnosticConsumer(DiagOpts, OutputFile, PP, CTU,<br>
+                                              /*supportsMultipleFiles=*/false));<br>
   createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, OutputFile,<br>
                                           PP, CTU);<br>
 }<br>
@@ -547,20 +546,21 @@ void ento::createPlistDiagnosticConsumer(<br>
 void ento::createPlistMultiFileDiagnosticConsumer(<br>
     PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,<br>
     const std::string &OutputFile, const Preprocessor &PP,<br>
-    const cross_tu::CrossTranslationUnitContext &CTU) {<br>
+    const CrossTUAnalysisHelper &CTU) {<br>
<br>
   // TODO: Emit an error here.<br>
   if (OutputFile.empty())<br>
     return;<br>
<br>
-  C.push_back(new PlistDiagnostics(DiagOpts, OutputFile, PP, CTU,<br>
-                                   /*supportsMultipleFiles=*/true));<br>
+  C.push_back(new PlistPathDiagnosticConsumer(DiagOpts, OutputFile, PP, CTU,<br>
+                                              /*supportsMultipleFiles=*/true));<br>
   createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, OutputFile,<br>
                                           PP, CTU);<br>
 }<br>
<br>
-void PlistDiagnostics::printBugPath(llvm::raw_ostream &o, const FIDMap &FM,<br>
-                                    const PathPieces &Path) {<br>
+void PlistPathDiagnosticConsumer::printBugPath(llvm::raw_ostream &o,<br>
+                                               const FIDMap &FM,<br>
+                                               const PathPieces &Path) {<br>
   PlistPrinter Printer(FM, PP, CTU);<br>
   assert(std::is_partitioned(Path.begin(), Path.end(),<br>
                              [](const PathDiagnosticPieceRef &E) {<br>
@@ -603,9 +603,8 @@ void PlistDiagnostics::printBugPath(llvm::raw_ostream &o, const FIDMap &FM,<br>
   o << "   </array>\n";<br>
 }<br>
<br>
-void PlistDiagnostics::FlushDiagnosticsImpl(<br>
-                                    std::vector<const PathDiagnostic *> &Diags,<br>
-                                    FilesMade *filesMade) {<br>
+void PlistPathDiagnosticConsumer::FlushDiagnosticsImpl(<br>
+    std::vector<const PathDiagnostic *> &Diags, FilesMade *filesMade) {<br>
   // Build up a set of FIDs that we use by scanning the locations and<br>
   // ranges of the diagnostics.<br>
   FIDMap FM;<br>
@@ -985,12 +984,13 @@ static const MacroInfo *getMacroInfoForLocation(const Preprocessor &PP,<br>
<br>
 static ExpansionInfo<br>
 getExpandedMacro(SourceLocation MacroLoc, const Preprocessor &PP,<br>
-                 const cross_tu::CrossTranslationUnitContext &CTU) {<br>
+                 const CrossTUAnalysisHelper &CTU) {<br>
<br>
   const Preprocessor *PPToUse = &PP;<br>
-  if (auto LocAndUnit = CTU.getImportedFromSourceLocation(MacroLoc)) {<br>
+  if (auto LocAndUnit =<br>
+      CTU.getImportedFromSourceLocationWithPreprocessor(MacroLoc)) {<br>
     MacroLoc = LocAndUnit->first;<br>
-    PPToUse = &LocAndUnit->second->getPreprocessor();<br>
+    PPToUse = LocAndUnit->second;<br>
   }<br>
<br>
   llvm::SmallString<200> ExpansionBuf;<br>
<br>
diff  --git a/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp b/clang/lib/Analysis/SarifPathDiagnosticConsumer.cpp<br>
similarity index 93%<br>
rename from clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp<br>
rename to clang/lib/Analysis/SarifPathDiagnosticConsumer.cpp<br>
index f93d04ccd61a..e2fcad5b8e15 100644<br>
--- a/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp<br>
+++ b/clang/lib/Analysis/SarifPathDiagnosticConsumer.cpp<br>
@@ -1,4 +1,4 @@<br>
-//===--- SarifDiagnostics.cpp - Sarif Diagnostics for Paths -----*- C++ -*-===//<br>
+//===--- SarifPathDiagnosticConsumer.cpp - Sarif Diagnostics  ---*- C++ -*-===//<br>
 //<br>
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.<br>
 // See <a href="https://llvm.org/LICENSE.txt" rel="noreferrer" target="_blank">https://llvm.org/LICENSE.txt</a> for license information.<br>
@@ -6,15 +6,15 @@<br>
 //<br>
 //===----------------------------------------------------------------------===//<br>
 //<br>
-//  This file defines the SarifDiagnostics object.<br>
+//  This file defines the SarifPathDiagnosticConsumer object.<br>
 //<br>
 //===----------------------------------------------------------------------===//<br>
<br>
 #include "clang/Analysis/PathDiagnostic.h"<br>
+#include "clang/Analysis/PathDiagnosticConsumers.h"<br>
 #include "clang/Basic/FileManager.h"<br>
 #include "clang/Basic/Version.h"<br>
 #include "clang/Lex/Preprocessor.h"<br>
-#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"<br>
 #include "llvm/ADT/STLExtras.h"<br>
 #include "llvm/ADT/StringMap.h"<br>
 #include "llvm/Support/ConvertUTF.h"<br>
@@ -25,20 +25,24 @@ using namespace llvm;<br>
 using namespace clang;<br>
 using namespace ento;<br>
<br>
+namespace clang {<br>
+class CrossTUAnalysisHelper;<br>
+}<br>
+<br>
 namespace {<br>
-class SarifDiagnostics : public PathDiagnosticConsumer {<br>
+class SarifPathDiagnosticConsumer : public PathDiagnosticConsumer {<br>
   std::string OutputFile;<br>
   const LangOptions &LO;<br>
<br>
 public:<br>
-  SarifDiagnostics(const std::string &Output, const LangOptions &LO)<br>
+  SarifPathDiagnosticConsumer(const std::string &Output, const LangOptions &LO)<br>
       : OutputFile(Output), LO(LO) {}<br>
-  ~SarifDiagnostics() override = default;<br>
+  ~SarifPathDiagnosticConsumer() override = default;<br>
<br>
   void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,<br>
                             FilesMade *FM) override;<br>
<br>
-  StringRef getName() const override { return "SarifDiagnostics"; }<br>
+  StringRef getName() const override { return "SarifPathDiagnosticConsumer"; }<br>
   PathGenerationScheme getGenerationScheme() const override { return Minimal; }<br>
   bool supportsLogicalOpControlFlow() const override { return true; }<br>
   bool supportsCrossFileDiagnostics() const override { return true; }<br>
@@ -48,13 +52,13 @@ class SarifDiagnostics : public PathDiagnosticConsumer {<br>
 void ento::createSarifDiagnosticConsumer(<br>
     PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,<br>
     const std::string &Output, const Preprocessor &PP,<br>
-    const cross_tu::CrossTranslationUnitContext &CTU) {<br>
+    const CrossTUAnalysisHelper &CTU) {<br>
<br>
   // TODO: Emit an error here.<br>
   if (Output.empty())<br>
     return;<br>
<br>
-  C.push_back(new SarifDiagnostics(Output, PP.getLangOpts()));<br>
+  C.push_back(new SarifPathDiagnosticConsumer(Output, PP.getLangOpts()));<br>
   createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, Output, PP,<br>
                                           CTU);<br>
 }<br>
@@ -299,6 +303,9 @@ static json::Object createResult(const LangOptions &LO,<br>
 }<br>
<br>
 static StringRef getRuleDescription(StringRef CheckName) {<br>
+  // FIXME: This is a layering violation; it only works for the particular<br>
+  // use-case of clang static analyzer. This info should be provided<br>
+  // as part of PathDiagnostic itself.<br>
   return llvm::StringSwitch<StringRef>(CheckName)<br>
 #define GET_CHECKERS<br>
 #define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN)                 \<br>
@@ -310,6 +317,9 @@ static StringRef getRuleDescription(StringRef CheckName) {<br>
 }<br>
<br>
 static StringRef getRuleHelpURIStr(StringRef CheckName) {<br>
+  // FIXME: This is a layering violation; it only works for the particular<br>
+  // use-case of clang static analyzer. This info should be provided<br>
+  // as part of PathDiagnostic itself.<br>
   return llvm::StringSwitch<StringRef>(CheckName)<br>
 #define GET_CHECKERS<br>
 #define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN)                 \<br>
@@ -377,7 +387,7 @@ static json::Object createRun(const LangOptions &LO,<br>
                       {"columnKind", "unicodeCodePoints"}};<br>
 }<br>
<br>
-void SarifDiagnostics::FlushDiagnosticsImpl(<br>
+void SarifPathDiagnosticConsumer::FlushDiagnosticsImpl(<br>
     std::vector<const PathDiagnostic *> &Diags, FilesMade *) {<br>
   // We currently overwrite the file if it already exists. However, it may be<br>
   // useful to add a feature someday that allows the user to append a run to an<br>
<br>
diff  --git a/clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp b/clang/lib/Analysis/TextPathDiagnosticConsumer.cpp<br>
similarity index 79%<br>
rename from clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp<br>
rename to clang/lib/Analysis/TextPathDiagnosticConsumer.cpp<br>
index ae2bad7ee77c..e9010d5c08aa 100644<br>
--- a/clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp<br>
+++ b/clang/lib/Analysis/TextPathDiagnosticConsumer.cpp<br>
@@ -1,4 +1,4 @@<br>
-//===--- TextDiagnostics.cpp - Text Diagnostics for Paths -------*- C++ -*-===//<br>
+//===--- TextPathDiagnosticConsumer.cpp - Text Diagnostics ------*- C++ -*-===//<br>
 //<br>
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.<br>
 // See <a href="https://llvm.org/LICENSE.txt" rel="noreferrer" target="_blank">https://llvm.org/LICENSE.txt</a> for license information.<br>
@@ -6,19 +6,17 @@<br>
 //<br>
 //===----------------------------------------------------------------------===//<br>
 //<br>
-//  This file defines the TextDiagnostics object.<br>
+//  This file defines the TextPathDiagnosticConsumer object.<br>
 //<br>
 //===----------------------------------------------------------------------===//<br>
<br>
 #include "clang/Analysis/PathDiagnostic.h"<br>
+#include "clang/Analysis/PathDiagnosticConsumers.h"<br>
 #include "clang/Basic/SourceManager.h"<br>
 #include "clang/Basic/Version.h"<br>
-#include "clang/CrossTU/CrossTranslationUnit.h"<br>
 #include "clang/Frontend/ASTUnit.h"<br>
 #include "clang/Lex/Preprocessor.h"<br>
 #include "clang/Rewrite/Core/Rewriter.h"<br>
-#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"<br>
-#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"<br>
 #include "clang/Tooling/Core/Replacement.h"<br>
 #include "clang/Tooling/Tooling.h"<br>
 #include "llvm/ADT/SmallPtrSet.h"<br>
@@ -29,25 +27,29 @@ using namespace clang;<br>
 using namespace ento;<br>
 using namespace tooling;<br>
<br>
+namespace clang {<br>
+class CrossTUAnalysisHelper;<br>
+}<br>
+<br>
 namespace {<br>
-/// Emitsd minimal diagnostics (report message + notes) for the 'none' output<br>
+/// Emits minimal diagnostics (report message + notes) for the 'none' output<br>
 /// type to the standard error, or to to compliment many others. Emits detailed<br>
 /// diagnostics in textual format for the 'text' output type.<br>
-class TextDiagnostics : public PathDiagnosticConsumer {<br>
+class TextPathDiagnosticConsumer : public PathDiagnosticConsumer {<br>
   PathDiagnosticConsumerOptions DiagOpts;<br>
   DiagnosticsEngine &DiagEng;<br>
   const LangOptions &LO;<br>
   bool ShouldDisplayPathNotes;<br>
<br>
 public:<br>
-  TextDiagnostics(PathDiagnosticConsumerOptions DiagOpts,<br>
-                  DiagnosticsEngine &DiagEng, const LangOptions &LO,<br>
-                  bool ShouldDisplayPathNotes)<br>
+  TextPathDiagnosticConsumer(PathDiagnosticConsumerOptions DiagOpts,<br>
+                             DiagnosticsEngine &DiagEng, const LangOptions &LO,<br>
+                             bool ShouldDisplayPathNotes)<br>
       : DiagOpts(std::move(DiagOpts)), DiagEng(DiagEng), LO(LO),<br>
         ShouldDisplayPathNotes(ShouldDisplayPathNotes) {}<br>
-  ~TextDiagnostics() override {}<br>
+  ~TextPathDiagnosticConsumer() override {}<br>
<br>
-  StringRef getName() const override { return "TextDiagnostics"; }<br>
+  StringRef getName() const override { return "TextPathDiagnosticConsumer"; }<br>
<br>
   bool supportsLogicalOpControlFlow() const override { return true; }<br>
   bool supportsCrossFileDiagnostics() const override { return true; }<br>
@@ -139,17 +141,17 @@ class TextDiagnostics : public PathDiagnosticConsumer {<br>
 void ento::createTextPathDiagnosticConsumer(<br>
     PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,<br>
     const std::string &Prefix, const clang::Preprocessor &PP,<br>
-    const cross_tu::CrossTranslationUnitContext &CTU) {<br>
-  C.emplace_back(new TextDiagnostics(std::move(DiagOpts), PP.getDiagnostics(),<br>
-                                     PP.getLangOpts(),<br>
-                                     /*ShouldDisplayPathNotes=*/true));<br>
+    const CrossTUAnalysisHelper &CTU) {<br>
+  C.emplace_back(new TextPathDiagnosticConsumer(<br>
+      std::move(DiagOpts), PP.getDiagnostics(), PP.getLangOpts(),<br>
+      /*ShouldDisplayPathNotes=*/true));<br>
 }<br>
<br>
 void ento::createTextMinimalPathDiagnosticConsumer(<br>
     PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,<br>
     const std::string &Prefix, const clang::Preprocessor &PP,<br>
-    const cross_tu::CrossTranslationUnitContext &CTU) {<br>
-  C.emplace_back(new TextDiagnostics(std::move(DiagOpts), PP.getDiagnostics(),<br>
-                                     PP.getLangOpts(),<br>
-                                     /*ShouldDisplayPathNotes=*/false));<br>
+    const CrossTUAnalysisHelper &CTU) {<br>
+  C.emplace_back(new TextPathDiagnosticConsumer(<br>
+      std::move(DiagOpts), PP.getDiagnostics(), PP.getLangOpts(),<br>
+      /*ShouldDisplayPathNotes=*/false));<br>
 }<br>
<br>
diff  --git a/clang/lib/CrossTU/CrossTranslationUnit.cpp b/clang/lib/CrossTU/CrossTranslationUnit.cpp<br>
index e27779f91abc..5ab5d6def2a2 100644<br>
--- a/clang/lib/CrossTU/CrossTranslationUnit.cpp<br>
+++ b/clang/lib/CrossTU/CrossTranslationUnit.cpp<br>
@@ -765,7 +765,7 @@ CrossTranslationUnitContext::getOrCreateASTImporter(ASTUnit *Unit) {<br>
<br>
 llvm::Optional<std::pair<SourceLocation, ASTUnit *>><br>
 CrossTranslationUnitContext::getImportedFromSourceLocation(<br>
-    const clang::SourceLocation &ToLoc) const {<br>
+    SourceLocation ToLoc) const {<br>
   const SourceManager &SM = Context.getSourceManager();<br>
   auto DecToLoc = SM.getDecomposedLoc(ToLoc);<br>
<br>
@@ -781,5 +781,16 @@ CrossTranslationUnitContext::getImportedFromSourceLocation(<br>
   return std::make_pair(FromLoc, Unit);<br>
 }<br>
<br>
+llvm::Optional<std::pair<SourceLocation, Preprocessor *>><br>
+CrossTranslationUnitContext::getImportedFromSourceLocationWithPreprocessor(<br>
+    SourceLocation ToLoc) const {<br>
+  if (llvm::Optional<std::pair<SourceLocation, ASTUnit *>> LocAndUnit =<br>
+      getImportedFromSourceLocation(ToLoc)) {<br>
+    return std::make_pair(LocAndUnit->first,<br>
+                          &LocAndUnit->second->getPreprocessor());<br>
+  }<br>
+  return None;<br>
+}<br>
+<br>
 } // namespace cross_tu<br>
 } // namespace clang<br>
<br>
diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp<br>
index f9bce6a3f7a2..57027cea5659 100644<br>
--- a/clang/lib/Frontend/CompilerInvocation.cpp<br>
+++ b/clang/lib/Frontend/CompilerInvocation.cpp<br>
@@ -547,7 +547,7 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,<br>
     AnalysisDiagClients Value = llvm::StringSwitch<AnalysisDiagClients>(Name)<br>
 #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \<br>
       .Case(CMDFLAG, PD_##NAME)<br>
-#include "clang/StaticAnalyzer/Core/Analyses.def"<br>
+#include "clang/Analysis/PathDiagnosticConsumers.def"<br>
       .Default(NUM_ANALYSIS_DIAG_CLIENTS);<br>
     if (Value == NUM_ANALYSIS_DIAG_CLIENTS) {<br>
       Diags.Report(diag::err_drv_invalid_value)<br>
<br>
diff  --git a/clang/lib/StaticAnalyzer/Core/CMakeLists.txt b/clang/lib/StaticAnalyzer/Core/CMakeLists.txt<br>
index d947d415ad6e..b1f527ed75d5 100644<br>
--- a/clang/lib/StaticAnalyzer/Core/CMakeLists.txt<br>
+++ b/clang/lib/StaticAnalyzer/Core/CMakeLists.txt<br>
@@ -30,16 +30,13 @@ add_clang_library(clangStaticAnalyzerCore<br>
   ExprEngineCallAndReturn.cpp<br>
   ExprEngineObjC.cpp<br>
   FunctionSummary.cpp<br>
-  HTMLDiagnostics.cpp<br>
   LoopUnrolling.cpp<br>
   LoopWidening.cpp<br>
   MemRegion.cpp<br>
-  PlistDiagnostics.cpp<br>
   ProgramState.cpp<br>
   RangeConstraintManager.cpp<br>
   RangedConstraintManager.cpp<br>
   RegionStore.cpp<br>
-  SarifDiagnostics.cpp<br>
   SimpleConstraintManager.cpp<br>
   SimpleSValBuilder.cpp<br>
   SMTConstraintManager.cpp<br>
@@ -47,7 +44,6 @@ add_clang_library(clangStaticAnalyzerCore<br>
   SValBuilder.cpp<br>
   SVals.cpp<br>
   SymbolManager.cpp<br>
-  TextDiagnostics.cpp<br>
   WorkList.cpp<br>
<br>
   LINK_LIBS<br>
<br>
diff  --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp<br>
index f2a19b2ccc90..1e94950ca097 100644<br>
--- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp<br>
+++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp<br>
@@ -21,6 +21,7 @@<br>
 #include "clang/Analysis/CallGraph.h"<br>
 #include "clang/Analysis/CodeInjector.h"<br>
 #include "clang/Analysis/PathDiagnostic.h"<br>
+#include "clang/Analysis/PathDiagnosticConsumers.h"<br>
 #include "clang/Basic/SourceManager.h"<br>
 #include "clang/CrossTU/CrossTranslationUnit.h"<br>
 #include "clang/Frontend/CompilerInstance.h"<br>
@@ -30,7 +31,6 @@<br>
 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"<br>
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"<br>
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"<br>
-#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"<br>
 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"<br>
 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"<br>
 #include "llvm/ADT/PostOrderIterator.h"<br>
@@ -152,7 +152,7 @@ class AnalysisConsumer : public AnalysisASTConsumer,<br>
   case PD_##NAME:                                                              \<br>
     CREATEFN(Opts->getDiagOpts(), PathConsumers, OutDir, PP, CTU);             \<br>
     break;<br>
-#include "clang/StaticAnalyzer/Core/Analyses.def"<br>
+#include "clang/Analysis/PathDiagnosticConsumers.def"<br>
     default:<br>
       llvm_unreachable("Unknown analyzer output type!");<br>
     }<br>
<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div></div>