xref: /freebsd-src/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Logger.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric //===-- Logger.h ------------------------------------------------*- C++ -*-===//
206c3fb27SDimitry Andric //
306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606c3fb27SDimitry Andric //
706c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
806c3fb27SDimitry Andric 
906c3fb27SDimitry Andric #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_LOGGER_H
1006c3fb27SDimitry Andric #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_LOGGER_H
1106c3fb27SDimitry Andric 
1206c3fb27SDimitry Andric #include "clang/Analysis/CFG.h"
1306c3fb27SDimitry Andric #include "llvm/Support/raw_ostream.h"
1406c3fb27SDimitry Andric #include <memory>
1506c3fb27SDimitry Andric 
1606c3fb27SDimitry Andric namespace clang::dataflow {
1706c3fb27SDimitry Andric // Forward declarations so we can use Logger anywhere in the framework.
18*0fca6ea1SDimitry Andric class AdornedCFG;
1906c3fb27SDimitry Andric class TypeErasedDataflowAnalysis;
2006c3fb27SDimitry Andric struct TypeErasedDataflowAnalysisState;
2106c3fb27SDimitry Andric 
2206c3fb27SDimitry Andric /// A logger is notified as the analysis progresses.
2306c3fb27SDimitry Andric /// It can produce a report of the analysis's findings and how it came to them.
2406c3fb27SDimitry Andric ///
2506c3fb27SDimitry Andric /// The framework reports key structural events (e.g. traversal of blocks).
2606c3fb27SDimitry Andric /// The specific analysis can add extra details to be presented in context.
2706c3fb27SDimitry Andric class Logger {
2806c3fb27SDimitry Andric public:
2906c3fb27SDimitry Andric   /// Returns a dummy logger that does nothing.
3006c3fb27SDimitry Andric   static Logger &null();
3106c3fb27SDimitry Andric   /// A logger that simply writes messages to the specified ostream in real
3206c3fb27SDimitry Andric   /// time.
3306c3fb27SDimitry Andric   static std::unique_ptr<Logger> textual(llvm::raw_ostream &);
3406c3fb27SDimitry Andric   /// A logger that builds an HTML UI to inspect the analysis results.
3506c3fb27SDimitry Andric   /// Each function's analysis is written to a stream obtained from the factory.
3606c3fb27SDimitry Andric   static std::unique_ptr<Logger>
3706c3fb27SDimitry Andric       html(std::function<std::unique_ptr<llvm::raw_ostream>()>);
3806c3fb27SDimitry Andric 
3906c3fb27SDimitry Andric   virtual ~Logger() = default;
4006c3fb27SDimitry Andric 
4106c3fb27SDimitry Andric   /// Called by the framework as we start analyzing a new function or statement.
4206c3fb27SDimitry Andric   /// Forms a pair with endAnalysis().
43*0fca6ea1SDimitry Andric   virtual void beginAnalysis(const AdornedCFG &, TypeErasedDataflowAnalysis &) {
44*0fca6ea1SDimitry Andric   }
4506c3fb27SDimitry Andric   virtual void endAnalysis() {}
4606c3fb27SDimitry Andric 
4706c3fb27SDimitry Andric   // At any time during the analysis, we're computing the state for some target
4806c3fb27SDimitry Andric   // program point.
4906c3fb27SDimitry Andric 
5006c3fb27SDimitry Andric   /// Called when we start (re-)processing a block in the CFG.
5106c3fb27SDimitry Andric   /// The target program point is the entry to the specified block.
5206c3fb27SDimitry Andric   /// Calls to log() describe transferBranch(), join() etc.
535f757f3fSDimitry Andric   /// `PostVisit` specifies whether we're processing the block for the
545f757f3fSDimitry Andric   /// post-visit callback.
555f757f3fSDimitry Andric   virtual void enterBlock(const CFGBlock &, bool PostVisit) {}
5606c3fb27SDimitry Andric   /// Called when we start processing an element in the current CFG block.
5706c3fb27SDimitry Andric   /// The target program point is after the specified element.
5806c3fb27SDimitry Andric   /// Calls to log() describe the transfer() function.
5906c3fb27SDimitry Andric   virtual void enterElement(const CFGElement &) {}
6006c3fb27SDimitry Andric 
6106c3fb27SDimitry Andric   /// Records the analysis state computed for the current program point.
6206c3fb27SDimitry Andric   virtual void recordState(TypeErasedDataflowAnalysisState &) {}
6306c3fb27SDimitry Andric   /// Records that the analysis state for the current block is now final.
6406c3fb27SDimitry Andric   virtual void blockConverged() {}
6506c3fb27SDimitry Andric 
6606c3fb27SDimitry Andric   /// Called by the framework or user code to report some event.
6706c3fb27SDimitry Andric   /// The event is associated with the current context (program point).
6806c3fb27SDimitry Andric   /// The Emit function produces the log message. It may or may not be called,
6906c3fb27SDimitry Andric   /// depending on if the logger is interested; it should have no side effects.
7006c3fb27SDimitry Andric   void log(llvm::function_ref<void(llvm::raw_ostream &)> Emit) {
7106c3fb27SDimitry Andric     if (!ShouldLogText)
7206c3fb27SDimitry Andric       return;
7306c3fb27SDimitry Andric     std::string S;
7406c3fb27SDimitry Andric     llvm::raw_string_ostream OS(S);
7506c3fb27SDimitry Andric     Emit(OS);
7606c3fb27SDimitry Andric     logText(S);
7706c3fb27SDimitry Andric   }
7806c3fb27SDimitry Andric 
7906c3fb27SDimitry Andric protected:
8006c3fb27SDimitry Andric   /// ShouldLogText should be false for trivial loggers that ignore logText().
8106c3fb27SDimitry Andric   /// This allows log() to skip evaluating its Emit function.
8206c3fb27SDimitry Andric   Logger(bool ShouldLogText = true) : ShouldLogText(ShouldLogText) {}
8306c3fb27SDimitry Andric 
8406c3fb27SDimitry Andric private:
8506c3fb27SDimitry Andric   bool ShouldLogText;
8606c3fb27SDimitry Andric   virtual void logText(llvm::StringRef) {}
8706c3fb27SDimitry Andric };
8806c3fb27SDimitry Andric 
8906c3fb27SDimitry Andric } // namespace clang::dataflow
9006c3fb27SDimitry Andric 
9106c3fb27SDimitry Andric #endif
92