Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:25

0001 //===- TypeErasedDataflowAnalysis.h -----------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 //  This file defines type-erased base types and functions for building dataflow
0010 //  analyses that run over Control-Flow Graphs (CFGs).
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_TYPEERASEDDATAFLOWANALYSIS_H
0015 #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_TYPEERASEDDATAFLOWANALYSIS_H
0016 
0017 #include <optional>
0018 #include <utility>
0019 #include <vector>
0020 
0021 #include "clang/AST/ASTContext.h"
0022 #include "clang/AST/Stmt.h"
0023 #include "clang/Analysis/CFG.h"
0024 #include "clang/Analysis/FlowSensitive/AdornedCFG.h"
0025 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
0026 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
0027 #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
0028 #include "llvm/ADT/Any.h"
0029 #include "llvm/Support/Error.h"
0030 
0031 namespace clang {
0032 namespace dataflow {
0033 
0034 struct DataflowAnalysisOptions {
0035   /// Options for the built-in model, or empty to not apply them.
0036   // FIXME: Remove this option once the framework supports composing analyses
0037   // (at which point the built-in transfer functions can be simply a standalone
0038   // analysis).
0039   std::optional<DataflowAnalysisContext::Options> BuiltinOpts =
0040       DataflowAnalysisContext::Options{};
0041 };
0042 
0043 /// Type-erased lattice element container.
0044 ///
0045 /// Requirements:
0046 ///
0047 ///  The type of the object stored in the container must be a bounded
0048 ///  join-semilattice.
0049 struct TypeErasedLattice {
0050   llvm::Any Value;
0051 };
0052 
0053 /// Type-erased base class for dataflow analyses built on a single lattice type.
0054 class TypeErasedDataflowAnalysis : public Environment::ValueModel {
0055   DataflowAnalysisOptions Options;
0056 
0057 public:
0058   TypeErasedDataflowAnalysis() : Options({}) {}
0059 
0060   TypeErasedDataflowAnalysis(DataflowAnalysisOptions Options)
0061       : Options(Options) {}
0062 
0063   virtual ~TypeErasedDataflowAnalysis() {}
0064 
0065   /// Returns the `ASTContext` that is used by the analysis.
0066   virtual ASTContext &getASTContext() = 0;
0067 
0068   /// Returns a type-erased lattice element that models the initial state of a
0069   /// basic block.
0070   virtual TypeErasedLattice typeErasedInitialElement() = 0;
0071 
0072   /// Joins two type-erased lattice elements by computing their least upper
0073   /// bound. Places the join result in the left element and returns an effect
0074   /// indicating whether any changes were made to it.
0075   virtual TypeErasedLattice joinTypeErased(const TypeErasedLattice &,
0076                                            const TypeErasedLattice &) = 0;
0077 
0078   /// Chooses a lattice element that approximates the current element at a
0079   /// program point, given the previous element at that point. Places the
0080   /// widened result in the current element (`Current`). Widening is optional --
0081   /// it is only needed to either accelerate convergence (for lattices with
0082   /// non-trivial height) or guarantee convergence (for lattices with infinite
0083   /// height).
0084   ///
0085   /// Returns an indication of whether any changes were made to `Current` in
0086   /// order to widen. This saves a separate call to `isEqualTypeErased` after
0087   /// the widening.
0088   virtual LatticeJoinEffect
0089   widenTypeErased(TypeErasedLattice &Current,
0090                   const TypeErasedLattice &Previous) = 0;
0091 
0092   /// Returns true if and only if the two given type-erased lattice elements are
0093   /// equal.
0094   virtual bool isEqualTypeErased(const TypeErasedLattice &,
0095                                  const TypeErasedLattice &) = 0;
0096 
0097   /// Applies the analysis transfer function for a given control flow graph
0098   /// element and type-erased lattice element.
0099   virtual void transferTypeErased(const CFGElement &, TypeErasedLattice &,
0100                                   Environment &) = 0;
0101 
0102   /// Applies the analysis transfer function for a given edge from a CFG block
0103   /// of a conditional statement.
0104   /// @param Stmt The condition which is responsible for the split in the CFG.
0105   /// @param Branch True if the edge goes to the basic block where the
0106   /// condition is true.
0107   // FIXME: Change `Stmt` argument to a reference.
0108   virtual void transferBranchTypeErased(bool Branch, const Stmt *,
0109                                         TypeErasedLattice &, Environment &) = 0;
0110 
0111   /// If the built-in model is enabled, returns the options to be passed to
0112   /// them. Otherwise returns empty.
0113   const std::optional<DataflowAnalysisContext::Options> &
0114   builtinOptions() const {
0115     return Options.BuiltinOpts;
0116   }
0117 };
0118 
0119 /// Type-erased model of the program at a given program point.
0120 struct TypeErasedDataflowAnalysisState {
0121   /// Type-erased model of a program property.
0122   TypeErasedLattice Lattice;
0123 
0124   /// Model of the state of the program (store and heap).
0125   Environment Env;
0126 
0127   TypeErasedDataflowAnalysisState(TypeErasedLattice Lattice, Environment Env)
0128       : Lattice(std::move(Lattice)), Env(std::move(Env)) {}
0129 
0130   TypeErasedDataflowAnalysisState fork() const {
0131     return TypeErasedDataflowAnalysisState(Lattice, Env.fork());
0132   }
0133 };
0134 
0135 /// A callback to be called with the state before or after visiting a CFG
0136 /// element.
0137 using CFGEltCallbackTypeErased = std::function<void(
0138     const CFGElement &, const TypeErasedDataflowAnalysisState &)>;
0139 
0140 /// A pair of callbacks to be called with the state before and after visiting a
0141 /// CFG element.
0142 /// Either or both of the callbacks may be null.
0143 struct CFGEltCallbacksTypeErased {
0144   CFGEltCallbackTypeErased Before;
0145   CFGEltCallbackTypeErased After;
0146 };
0147 
0148 /// Performs dataflow analysis and returns a mapping from basic block IDs to
0149 /// dataflow analysis states that model the respective basic blocks. Indices of
0150 /// the returned vector correspond to basic block IDs. Returns an error if the
0151 /// dataflow analysis cannot be performed successfully. Otherwise, calls
0152 /// `PostAnalysisCallbacks` on each CFG element with the final analysis results
0153 /// before and after that program point.
0154 ///
0155 /// `MaxBlockVisits` caps the number of block visits during analysis. It doesn't
0156 /// distinguish between repeat visits to the same block and visits to distinct
0157 /// blocks. This parameter is a backstop to prevent infinite loops, in the case
0158 /// of bugs in the lattice and/or transfer functions that prevent the analysis
0159 /// from converging.
0160 llvm::Expected<std::vector<std::optional<TypeErasedDataflowAnalysisState>>>
0161 runTypeErasedDataflowAnalysis(
0162     const AdornedCFG &ACFG, TypeErasedDataflowAnalysis &Analysis,
0163     const Environment &InitEnv,
0164     const CFGEltCallbacksTypeErased &PostAnalysisCallbacks,
0165     std::int32_t MaxBlockVisits);
0166 
0167 } // namespace dataflow
0168 } // namespace clang
0169 
0170 #endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_TYPEERASEDDATAFLOWANALYSIS_H