njames93 updated this revision to Diff 404350.
njames93 marked 5 inline comments as done.
njames93 added a comment.

Refactored implementation to not store state in ClangTidyContext. This will let 
external consumers of clang-tidy opt into the behaviour. As well as integrate 
the reporting to any signal handlers they may be using.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D118520/new/

https://reviews.llvm.org/D118520

Files:
  clang-tools-extra/clang-tidy/ClangTidyCheck.cpp
  clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
  clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
  clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp

Index: clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
===================================================================
--- clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
+++ clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
@@ -20,6 +20,7 @@
 #include "../GlobList.h"
 #include "clang/Tooling/CommonOptionsParser.h"
 #include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/Process.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/TargetSelect.h"
@@ -384,6 +385,12 @@
   return FS;
 }
 
+class ClangTidyCrashTraceReporter : public llvm::PrettyStackTraceEntry,
+                                    public CurProcessingCheckState {
+public:
+  void print(raw_ostream &OS) const override { return dump(OS); }
+};
+
 int clangTidyMain(int argc, const char **argv) {
   llvm::InitLLVM X(argc, argv);
   llvm::Expected<CommonOptionsParser> OptionsParser =
@@ -488,8 +495,11 @@
   llvm::InitializeAllTargetMCs();
   llvm::InitializeAllAsmParsers();
 
+  ClangTidyCrashTraceReporter Trace;
+
   ClangTidyContext Context(std::move(OwningOptionsProvider),
                            AllowEnablingAnalyzerAlphaCheckers);
+  Context.setCrashTraceEngine(&Trace);
   std::vector<ClangTidyError> Errors =
       runClangTidy(Context, OptionsParser->getCompilations(), PathList, BaseFS,
                    FixNotes, EnableCheckProfile, ProfilePrefix);
Index: clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
+++ clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -23,6 +23,7 @@
 class CompilerInstance;
 class SourceManager;
 namespace ast_matchers {
+class BoundNodes;
 class MatchFinder;
 } // namespace ast_matchers
 namespace tooling {
@@ -61,6 +62,31 @@
   }
 };
 
+class CurProcessingCheckState {
+public:
+  void dump(raw_ostream &OS) const;
+  void onProcessingCheckStart(StringRef CheckName,
+                              const ast_matchers::BoundNodes &BoundNodes) {
+    assert(CurContext && "ASTContext not set");
+    CurrentCheckName = CheckName;
+    CurNodes = &BoundNodes;
+  }
+
+  void onProcessingCheckEnd() {
+    CurrentCheckName = "";
+    CurNodes = nullptr;
+  }
+
+  void setContext(const ASTContext &Ctx) { CurContext = &Ctx; }
+
+  void clearContext() { CurContext = nullptr; }
+
+private:
+  mutable StringRef CurrentCheckName;
+  const ast_matchers::BoundNodes *CurNodes;
+  const ASTContext *CurContext;
+};
+
 /// Every \c ClangTidyCheck reports errors through a \c DiagnosticsEngine
 /// provided by this context.
 ///
@@ -82,6 +108,10 @@
     this->DiagEngine = DiagEngine;
   }
 
+  void setCrashTraceEngine(CurProcessingCheckState *State) {
+    this->CurrentlyProcessing = State;
+  }
+
   ~ClangTidyContext();
 
   /// Report any errors detected using this method.
@@ -204,12 +234,24 @@
             DiagEngine->getDiagnosticIDs()->getDescription(DiagnosticID)));
   }
 
+  void onProcessingCheckStart(StringRef CheckName,
+                              const ast_matchers::BoundNodes &Result) const {
+    if (CurrentlyProcessing)
+      CurrentlyProcessing->onProcessingCheckStart(CheckName, Result);
+  }
+
+  void onProcessingCheckEnd() const {
+    if (CurrentlyProcessing)
+      CurrentlyProcessing->onProcessingCheckEnd();
+  }
+
 private:
   // Writes to Stats.
   friend class ClangTidyDiagnosticConsumer;
 
   DiagnosticsEngine *DiagEngine;
   std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider;
+  CurProcessingCheckState *CurrentlyProcessing;
 
   std::string CurrentFile;
   ClangTidyOptions CurrentOptions;
Index: clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -22,6 +22,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ASTDiagnostic.h"
 #include "clang/AST/Attr.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/FileManager.h"
@@ -161,7 +162,7 @@
     std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider,
     bool AllowEnablingAnalyzerAlphaCheckers)
     : DiagEngine(nullptr), OptionsProvider(std::move(OptionsProvider)),
-      Profile(false),
+      CurrentlyProcessing(nullptr), Profile(false),
       AllowEnablingAnalyzerAlphaCheckers(AllowEnablingAnalyzerAlphaCheckers) {
   // Before the first translation unit we can get errors related to command-line
   // parsing, use empty string for the file name in this case.
@@ -231,6 +232,8 @@
 void ClangTidyContext::setASTContext(ASTContext *Context) {
   DiagEngine->SetArgToStringFn(&FormatASTNodeDiagnosticArgument, Context);
   LangOpts = Context->getLangOpts();
+  if (CurrentlyProcessing)
+    CurrentlyProcessing->setContext(*Context);
 }
 
 const ClangTidyGlobalOptions &ClangTidyContext::getGlobalOptions() const {
@@ -337,10 +340,30 @@
   }
   return Result;
 }
-
 } // namespace tidy
 } // namespace clang
 
+void CurProcessingCheckState::dump(raw_ostream &OS) const {
+  if (CurrentCheckName.empty())
+    return;
+  // This should be an assert, but asserts shouldn't be used in signal
+  // handlers
+  if (!CurContext)
+    return;
+  OS << "Processing check " << CurrentCheckName << '\n';
+  CurrentCheckName = "";
+  const clang::ast_matchers::BoundNodes::IDToNodeMap &Map = CurNodes->getMap();
+  if (Map.empty()) {
+    OS << "No bound nodes\n";
+    return;
+  }
+  for (const auto &Item : Map) {
+    OS << "Node '" << Item.first << "' - ";
+    Item.second.dump(OS, *CurContext);
+    OS << "\n";
+  }
+}
+
 void ClangTidyDiagnosticConsumer::HandleDiagnostic(
     DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) {
   if (LastErrorWasIgnored && DiagLevel == DiagnosticsEngine::Note)
Index: clang-tools-extra/clang-tidy/ClangTidyCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidyCheck.cpp
+++ clang-tools-extra/clang-tidy/ClangTidyCheck.cpp
@@ -39,10 +39,12 @@
 }
 
 void ClangTidyCheck::run(const ast_matchers::MatchFinder::MatchResult &Result) {
+  Context->onProcessingCheckStart(CheckName, Result.Nodes);
   // For historical reasons, checks don't implement the MatchFinder run()
   // callback directly. We keep the run()/check() distinction to avoid interface
   // churn, and to allow us to add cross-cutting logic in the future.
   check(Result);
+  Context->onProcessingCheckEnd();
 }
 
 ClangTidyCheck::OptionsView::OptionsView(
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to