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