xref: /freebsd-src/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Logger.h (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1*06c3fb27SDimitry Andric //===-- Logger.h ------------------------------------------------*- C++ -*-===//
2*06c3fb27SDimitry Andric //
3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*06c3fb27SDimitry Andric //
7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
8*06c3fb27SDimitry Andric 
9*06c3fb27SDimitry Andric #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_LOGGER_H
10*06c3fb27SDimitry Andric #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_LOGGER_H
11*06c3fb27SDimitry Andric 
12*06c3fb27SDimitry Andric #include "clang/Analysis/CFG.h"
13*06c3fb27SDimitry Andric #include "llvm/Support/raw_ostream.h"
14*06c3fb27SDimitry Andric #include <memory>
15*06c3fb27SDimitry Andric 
16*06c3fb27SDimitry Andric namespace clang::dataflow {
17*06c3fb27SDimitry Andric // Forward declarations so we can use Logger anywhere in the framework.
18*06c3fb27SDimitry Andric class ControlFlowContext;
19*06c3fb27SDimitry Andric class TypeErasedDataflowAnalysis;
20*06c3fb27SDimitry Andric struct TypeErasedDataflowAnalysisState;
21*06c3fb27SDimitry Andric 
22*06c3fb27SDimitry Andric /// A logger is notified as the analysis progresses.
23*06c3fb27SDimitry Andric /// It can produce a report of the analysis's findings and how it came to them.
24*06c3fb27SDimitry Andric ///
25*06c3fb27SDimitry Andric /// The framework reports key structural events (e.g. traversal of blocks).
26*06c3fb27SDimitry Andric /// The specific analysis can add extra details to be presented in context.
27*06c3fb27SDimitry Andric class Logger {
28*06c3fb27SDimitry Andric public:
29*06c3fb27SDimitry Andric   /// Returns a dummy logger that does nothing.
30*06c3fb27SDimitry Andric   static Logger &null();
31*06c3fb27SDimitry Andric   /// A logger that simply writes messages to the specified ostream in real
32*06c3fb27SDimitry Andric   /// time.
33*06c3fb27SDimitry Andric   static std::unique_ptr<Logger> textual(llvm::raw_ostream &);
34*06c3fb27SDimitry Andric   /// A logger that builds an HTML UI to inspect the analysis results.
35*06c3fb27SDimitry Andric   /// Each function's analysis is written to a stream obtained from the factory.
36*06c3fb27SDimitry Andric   static std::unique_ptr<Logger>
37*06c3fb27SDimitry Andric       html(std::function<std::unique_ptr<llvm::raw_ostream>()>);
38*06c3fb27SDimitry Andric 
39*06c3fb27SDimitry Andric   virtual ~Logger() = default;
40*06c3fb27SDimitry Andric 
41*06c3fb27SDimitry Andric   /// Called by the framework as we start analyzing a new function or statement.
42*06c3fb27SDimitry Andric   /// Forms a pair with endAnalysis().
43*06c3fb27SDimitry Andric   virtual void beginAnalysis(const ControlFlowContext &,
44*06c3fb27SDimitry Andric                              TypeErasedDataflowAnalysis &) {}
45*06c3fb27SDimitry Andric   virtual void endAnalysis() {}
46*06c3fb27SDimitry Andric 
47*06c3fb27SDimitry Andric   // At any time during the analysis, we're computing the state for some target
48*06c3fb27SDimitry Andric   // program point.
49*06c3fb27SDimitry Andric 
50*06c3fb27SDimitry Andric   /// Called when we start (re-)processing a block in the CFG.
51*06c3fb27SDimitry Andric   /// The target program point is the entry to the specified block.
52*06c3fb27SDimitry Andric   /// Calls to log() describe transferBranch(), join() etc.
53*06c3fb27SDimitry Andric   virtual void enterBlock(const CFGBlock &) {}
54*06c3fb27SDimitry Andric   /// Called when we start processing an element in the current CFG block.
55*06c3fb27SDimitry Andric   /// The target program point is after the specified element.
56*06c3fb27SDimitry Andric   /// Calls to log() describe the transfer() function.
57*06c3fb27SDimitry Andric   virtual void enterElement(const CFGElement &) {}
58*06c3fb27SDimitry Andric 
59*06c3fb27SDimitry Andric   /// Records the analysis state computed for the current program point.
60*06c3fb27SDimitry Andric   virtual void recordState(TypeErasedDataflowAnalysisState &) {}
61*06c3fb27SDimitry Andric   /// Records that the analysis state for the current block is now final.
62*06c3fb27SDimitry Andric   virtual void blockConverged() {}
63*06c3fb27SDimitry Andric 
64*06c3fb27SDimitry Andric   /// Called by the framework or user code to report some event.
65*06c3fb27SDimitry Andric   /// The event is associated with the current context (program point).
66*06c3fb27SDimitry Andric   /// The Emit function produces the log message. It may or may not be called,
67*06c3fb27SDimitry Andric   /// depending on if the logger is interested; it should have no side effects.
68*06c3fb27SDimitry Andric   void log(llvm::function_ref<void(llvm::raw_ostream &)> Emit) {
69*06c3fb27SDimitry Andric     if (!ShouldLogText)
70*06c3fb27SDimitry Andric       return;
71*06c3fb27SDimitry Andric     std::string S;
72*06c3fb27SDimitry Andric     llvm::raw_string_ostream OS(S);
73*06c3fb27SDimitry Andric     Emit(OS);
74*06c3fb27SDimitry Andric     logText(S);
75*06c3fb27SDimitry Andric   }
76*06c3fb27SDimitry Andric 
77*06c3fb27SDimitry Andric protected:
78*06c3fb27SDimitry Andric   /// ShouldLogText should be false for trivial loggers that ignore logText().
79*06c3fb27SDimitry Andric   /// This allows log() to skip evaluating its Emit function.
80*06c3fb27SDimitry Andric   Logger(bool ShouldLogText = true) : ShouldLogText(ShouldLogText) {}
81*06c3fb27SDimitry Andric 
82*06c3fb27SDimitry Andric private:
83*06c3fb27SDimitry Andric   bool ShouldLogText;
84*06c3fb27SDimitry Andric   virtual void logText(llvm::StringRef) {}
85*06c3fb27SDimitry Andric };
86*06c3fb27SDimitry Andric 
87*06c3fb27SDimitry Andric } // namespace clang::dataflow
88*06c3fb27SDimitry Andric 
89*06c3fb27SDimitry Andric #endif
90