xref: /llvm-project/clang/include/clang/Analysis/FlowSensitive/Logger.h (revision 59ff3adcc1310e22ab31163767e49b4edb20c6b4)
148f97e57SSam McCall //===-- Logger.h ------------------------------------------------*- C++ -*-===//
248f97e57SSam McCall //
348f97e57SSam McCall // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
448f97e57SSam McCall // See https://llvm.org/LICENSE.txt for license information.
548f97e57SSam McCall // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
648f97e57SSam McCall //
748f97e57SSam McCall //===----------------------------------------------------------------------===//
848f97e57SSam McCall 
948f97e57SSam McCall #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_LOGGER_H
1048f97e57SSam McCall #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_LOGGER_H
1148f97e57SSam McCall 
1248f97e57SSam McCall #include "clang/Analysis/CFG.h"
1348f97e57SSam McCall #include "llvm/Support/raw_ostream.h"
1448f97e57SSam McCall #include <memory>
1548f97e57SSam McCall 
1648f97e57SSam McCall namespace clang::dataflow {
1748f97e57SSam McCall // Forward declarations so we can use Logger anywhere in the framework.
18*59ff3adcSmartinboehme class AdornedCFG;
1948f97e57SSam McCall class TypeErasedDataflowAnalysis;
2048f97e57SSam McCall struct TypeErasedDataflowAnalysisState;
2148f97e57SSam McCall 
2248f97e57SSam McCall /// A logger is notified as the analysis progresses.
2348f97e57SSam McCall /// It can produce a report of the analysis's findings and how it came to them.
2448f97e57SSam McCall ///
2548f97e57SSam McCall /// The framework reports key structural events (e.g. traversal of blocks).
2648f97e57SSam McCall /// The specific analysis can add extra details to be presented in context.
2748f97e57SSam McCall class Logger {
2848f97e57SSam McCall public:
2948f97e57SSam McCall   /// Returns a dummy logger that does nothing.
3048f97e57SSam McCall   static Logger &null();
3148f97e57SSam McCall   /// A logger that simply writes messages to the specified ostream in real
3248f97e57SSam McCall   /// time.
3348f97e57SSam McCall   static std::unique_ptr<Logger> textual(llvm::raw_ostream &);
34a443b3d1SSam McCall   /// A logger that builds an HTML UI to inspect the analysis results.
35a443b3d1SSam McCall   /// Each function's analysis is written to a stream obtained from the factory.
36a443b3d1SSam McCall   static std::unique_ptr<Logger>
37a443b3d1SSam McCall       html(std::function<std::unique_ptr<llvm::raw_ostream>()>);
3848f97e57SSam McCall 
3948f97e57SSam McCall   virtual ~Logger() = default;
4048f97e57SSam McCall 
4148f97e57SSam McCall   /// Called by the framework as we start analyzing a new function or statement.
4248f97e57SSam McCall   /// Forms a pair with endAnalysis().
beginAnalysis(const AdornedCFG &,TypeErasedDataflowAnalysis &)43*59ff3adcSmartinboehme   virtual void beginAnalysis(const AdornedCFG &, TypeErasedDataflowAnalysis &) {
44*59ff3adcSmartinboehme   }
endAnalysis()4548f97e57SSam McCall   virtual void endAnalysis() {}
4648f97e57SSam McCall 
4748f97e57SSam McCall   // At any time during the analysis, we're computing the state for some target
4848f97e57SSam McCall   // program point.
4948f97e57SSam McCall 
5048f97e57SSam McCall   /// Called when we start (re-)processing a block in the CFG.
5148f97e57SSam McCall   /// The target program point is the entry to the specified block.
5248f97e57SSam McCall   /// Calls to log() describe transferBranch(), join() etc.
53ed65ced2Smartinboehme   /// `PostVisit` specifies whether we're processing the block for the
54ed65ced2Smartinboehme   /// post-visit callback.
enterBlock(const CFGBlock &,bool PostVisit)55ed65ced2Smartinboehme   virtual void enterBlock(const CFGBlock &, bool PostVisit) {}
5648f97e57SSam McCall   /// Called when we start processing an element in the current CFG block.
5748f97e57SSam McCall   /// The target program point is after the specified element.
5848f97e57SSam McCall   /// Calls to log() describe the transfer() function.
enterElement(const CFGElement &)5948f97e57SSam McCall   virtual void enterElement(const CFGElement &) {}
6048f97e57SSam McCall 
6148f97e57SSam McCall   /// Records the analysis state computed for the current program point.
recordState(TypeErasedDataflowAnalysisState &)6248f97e57SSam McCall   virtual void recordState(TypeErasedDataflowAnalysisState &) {}
6348f97e57SSam McCall   /// Records that the analysis state for the current block is now final.
blockConverged()6448f97e57SSam McCall   virtual void blockConverged() {}
6548f97e57SSam McCall 
6648f97e57SSam McCall   /// Called by the framework or user code to report some event.
6748f97e57SSam McCall   /// The event is associated with the current context (program point).
6848f97e57SSam McCall   /// The Emit function produces the log message. It may or may not be called,
6948f97e57SSam McCall   /// depending on if the logger is interested; it should have no side effects.
log(llvm::function_ref<void (llvm::raw_ostream &)> Emit)7048f97e57SSam McCall   void log(llvm::function_ref<void(llvm::raw_ostream &)> Emit) {
7148f97e57SSam McCall     if (!ShouldLogText)
7248f97e57SSam McCall       return;
7348f97e57SSam McCall     std::string S;
7448f97e57SSam McCall     llvm::raw_string_ostream OS(S);
7548f97e57SSam McCall     Emit(OS);
7648f97e57SSam McCall     logText(S);
7748f97e57SSam McCall   }
7848f97e57SSam McCall 
7948f97e57SSam McCall protected:
8048f97e57SSam McCall   /// ShouldLogText should be false for trivial loggers that ignore logText().
8148f97e57SSam McCall   /// This allows log() to skip evaluating its Emit function.
ShouldLogText(ShouldLogText)8248f97e57SSam McCall   Logger(bool ShouldLogText = true) : ShouldLogText(ShouldLogText) {}
8348f97e57SSam McCall 
8448f97e57SSam McCall private:
8548f97e57SSam McCall   bool ShouldLogText;
logText(llvm::StringRef)8648f97e57SSam McCall   virtual void logText(llvm::StringRef) {}
8748f97e57SSam McCall };
8848f97e57SSam McCall 
8948f97e57SSam McCall } // namespace clang::dataflow
9048f97e57SSam McCall 
9148f97e57SSam McCall #endif
92