clang  15.0.0git
TypeErasedDataflowAnalysis.cpp
Go to the documentation of this file.
1 //===- TypeErasedDataflowAnalysis.cpp -------------------------------------===//
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 // This file defines type-erased base types and functions for building dataflow
10 // analyses that run over Control-Flow Graphs (CFGs).
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include <memory>
15 #include <system_error>
16 #include <utility>
17 #include <vector>
18 
19 #include "clang/AST/DeclCXX.h"
21 #include "clang/AST/StmtVisitor.h"
23 #include "clang/Analysis/CFG.h"
29 #include "llvm/ADT/ArrayRef.h"
30 #include "llvm/ADT/DenseSet.h"
31 #include "llvm/ADT/None.h"
32 #include "llvm/ADT/Optional.h"
33 #include "llvm/ADT/STLExtras.h"
34 #include "llvm/Support/Error.h"
35 #include "llvm/Support/ErrorHandling.h"
36 
37 namespace clang {
38 namespace dataflow {
39 
41 public:
43  const ControlFlowContext &CFCtx,
45  BlockToState)
46  : CFCtx(CFCtx), BlockToState(BlockToState) {}
47 
48  const Environment *getEnvironment(const Stmt &S) const override {
49  auto BlockIT = CFCtx.getStmtToBlock().find(&ignoreCFGOmittedNodes(S));
50  assert(BlockIT != CFCtx.getStmtToBlock().end());
51  const auto &State = BlockToState[BlockIT->getSecond()->getBlockID()];
52  assert(State.hasValue());
53  return &State.getValue().Env;
54  }
55 
56 private:
57  const ControlFlowContext &CFCtx;
59 };
60 
61 /// Returns the index of `Block` in the successors of `Pred`.
62 static int blockIndexInPredecessor(const CFGBlock &Pred,
63  const CFGBlock &Block) {
64  auto BlockPos = llvm::find_if(
65  Pred.succs(), [&Block](const CFGBlock::AdjacentBlock &Succ) {
66  return Succ && Succ->getBlockID() == Block.getBlockID();
67  });
68  return BlockPos - Pred.succ_begin();
69 }
70 
71 /// Extends the flow condition of an environment based on a terminator
72 /// statement.
73 class TerminatorVisitor : public ConstStmtVisitor<TerminatorVisitor> {
74 public:
75  TerminatorVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env,
76  int BlockSuccIdx)
77  : StmtToEnv(StmtToEnv), Env(Env), BlockSuccIdx(BlockSuccIdx) {}
78 
79  void VisitIfStmt(const IfStmt *S) {
80  auto *Cond = S->getCond();
81  assert(Cond != nullptr);
82  extendFlowCondition(*Cond);
83  }
84 
85  void VisitWhileStmt(const WhileStmt *S) {
86  auto *Cond = S->getCond();
87  assert(Cond != nullptr);
88  extendFlowCondition(*Cond);
89  }
90 
92  assert(S->getOpcode() == BO_LAnd || S->getOpcode() == BO_LOr);
93  auto *LHS = S->getLHS();
94  assert(LHS != nullptr);
95  extendFlowCondition(*LHS);
96  }
97 
99  auto *Cond = S->getCond();
100  assert(Cond != nullptr);
101  extendFlowCondition(*Cond);
102  }
103 
104 private:
105  void extendFlowCondition(const Expr &Cond) {
106  // The terminator sub-expression might not be evaluated.
107  if (Env.getValue(Cond, SkipPast::None) == nullptr)
108  transfer(StmtToEnv, Cond, Env);
109 
110  // FIXME: The flow condition must be an r-value, so `SkipPast::None` should
111  // suffice.
112  auto *Val =
113  cast_or_null<BoolValue>(Env.getValue(Cond, SkipPast::Reference));
114  // Value merging depends on flow conditions from different environments
115  // being mutually exclusive -- that is, they cannot both be true in their
116  // entirety (even if they may share some clauses). So, we need *some* value
117  // for the condition expression, even if just an atom.
118  if (Val == nullptr) {
119  // FIXME: Consider introducing a helper for this get-or-create pattern.
120  auto *Loc = Env.getStorageLocation(Cond, SkipPast::None);
121  if (Loc == nullptr) {
122  Loc = &Env.createStorageLocation(Cond);
123  Env.setStorageLocation(Cond, *Loc);
124  }
125  Val = &Env.makeAtomicBoolValue();
126  Env.setValue(*Loc, *Val);
127  }
128 
129  // The condition must be inverted for the successor that encompasses the
130  // "else" branch, if such exists.
131  if (BlockSuccIdx == 1)
132  Val = &Env.makeNot(*Val);
133 
134  Env.addToFlowCondition(*Val);
135  }
136 
137  const StmtToEnvMap &StmtToEnv;
138  Environment &Env;
139  int BlockSuccIdx;
140 };
141 
142 /// Computes the input state for a given basic block by joining the output
143 /// states of its predecessors.
144 ///
145 /// Requirements:
146 ///
147 /// All predecessors of `Block` except those with loop back edges must have
148 /// already been transferred. States in `BlockStates` that are set to
149 /// `llvm::None` represent basic blocks that are not evaluated yet.
151  const ControlFlowContext &CFCtx,
152  std::vector<llvm::Optional<TypeErasedDataflowAnalysisState>> &BlockStates,
153  const CFGBlock &Block, const Environment &InitEnv,
154  TypeErasedDataflowAnalysis &Analysis) {
156  Preds.insert(Block.pred_begin(), Block.pred_end());
157  if (Block.getTerminator().isTemporaryDtorsBranch()) {
158  // This handles a special case where the code that produced the CFG includes
159  // a conditional operator with a branch that constructs a temporary and
160  // calls a destructor annotated as noreturn. The CFG models this as follows:
161  //
162  // B1 (contains the condition of the conditional operator) - succs: B2, B3
163  // B2 (contains code that does not call a noreturn destructor) - succs: B4
164  // B3 (contains code that calls a noreturn destructor) - succs: B4
165  // B4 (has temporary destructor terminator) - succs: B5, B6
166  // B5 (noreturn block that is associated with the noreturn destructor call)
167  // B6 (contains code that follows the conditional operator statement)
168  //
169  // The first successor (B5 above) of a basic block with a temporary
170  // destructor terminator (B4 above) is the block that evaluates the
171  // destructor. If that block has a noreturn element then the predecessor
172  // block that constructed the temporary object (B3 above) is effectively a
173  // noreturn block and its state should not be used as input for the state
174  // of the block that has a temporary destructor terminator (B4 above). This
175  // holds regardless of which branch of the ternary operator calls the
176  // noreturn destructor. However, it doesn't cases where a nested ternary
177  // operator includes a branch that contains a noreturn destructor call.
178  //
179  // See `NoreturnDestructorTest` for concrete examples.
180  if (Block.succ_begin()->getReachableBlock()->hasNoReturnElement()) {
181  auto StmtBlock = CFCtx.getStmtToBlock().find(Block.getTerminatorStmt());
182  assert(StmtBlock != CFCtx.getStmtToBlock().end());
183  Preds.erase(StmtBlock->getSecond());
184  }
185  }
186 
188  bool ApplyBuiltinTransfer = Analysis.applyBuiltinTransfer();
189 
190  for (const CFGBlock *Pred : Preds) {
191  // Skip if the `Block` is unreachable or control flow cannot get past it.
192  if (!Pred || Pred->hasNoReturnElement())
193  continue;
194 
195  // Skip if `Pred` was not evaluated yet. This could happen if `Pred` has a
196  // loop back edge to `Block`.
198  BlockStates[Pred->getBlockID()];
199  if (!MaybePredState.hasValue())
200  continue;
201 
202  TypeErasedDataflowAnalysisState PredState = MaybePredState.getValue();
203  if (ApplyBuiltinTransfer) {
204  if (const Stmt *PredTerminatorStmt = Pred->getTerminatorStmt()) {
205  const StmtToEnvMapImpl StmtToEnv(CFCtx, BlockStates);
206  TerminatorVisitor(StmtToEnv, PredState.Env,
208  .Visit(PredTerminatorStmt);
209  }
210  }
211 
212  if (MaybeState.hasValue()) {
213  Analysis.joinTypeErased(MaybeState->Lattice, PredState.Lattice);
214  MaybeState->Env.join(PredState.Env, Analysis);
215  } else {
216  MaybeState = std::move(PredState);
217  }
218  }
219  if (!MaybeState.hasValue()) {
220  // FIXME: Consider passing `Block` to `Analysis.typeErasedInitialElement()`
221  // to enable building analyses like computation of dominators that
222  // initialize the state of each basic block differently.
223  MaybeState.emplace(Analysis.typeErasedInitialElement(), InitEnv);
224  }
225  return *MaybeState;
226 }
227 
228 /// Transfers `State` by evaluating `CfgStmt` in the context of `Analysis`.
229 /// `HandleTransferredStmt` (if provided) will be applied to `CfgStmt`, after it
230 /// is evaluated.
231 static void transferCFGStmt(
232  const ControlFlowContext &CFCtx,
234  const CFGStmt &CfgStmt, TypeErasedDataflowAnalysis &Analysis,
236  std::function<void(const CFGStmt &,
238  HandleTransferredStmt) {
239  const Stmt *S = CfgStmt.getStmt();
240  assert(S != nullptr);
241 
242  if (Analysis.applyBuiltinTransfer())
243  transfer(StmtToEnvMapImpl(CFCtx, BlockStates), *S, State.Env);
244  Analysis.transferTypeErased(S, State.Lattice, State.Env);
245 
246  if (HandleTransferredStmt != nullptr)
247  HandleTransferredStmt(CfgStmt, State);
248 }
249 
250 /// Transfers `State` by evaluating `CfgInit`.
251 static void transferCFGInitializer(const CFGInitializer &CfgInit,
253  const auto &ThisLoc = *cast<AggregateStorageLocation>(
254  State.Env.getThisPointeeStorageLocation());
255 
256  const CXXCtorInitializer *Initializer = CfgInit.getInitializer();
257  assert(Initializer != nullptr);
258 
259  auto *InitStmt = Initializer->getInit();
260  assert(InitStmt != nullptr);
261 
262  auto *InitStmtLoc =
263  State.Env.getStorageLocation(*InitStmt, SkipPast::Reference);
264  if (InitStmtLoc == nullptr)
265  return;
266 
267  auto *InitStmtVal = State.Env.getValue(*InitStmtLoc);
268  if (InitStmtVal == nullptr)
269  return;
270 
271  const FieldDecl *Member = Initializer->getMember();
272  assert(Member != nullptr);
273 
274  if (Member->getType()->isReferenceType()) {
275  auto &MemberLoc = ThisLoc.getChild(*Member);
276  State.Env.setValue(MemberLoc,
277  State.Env.takeOwnership(
278  std::make_unique<ReferenceValue>(*InitStmtLoc)));
279  } else {
280  auto &MemberLoc = ThisLoc.getChild(*Member);
281  State.Env.setValue(MemberLoc, *InitStmtVal);
282  }
283 }
284 
286  const ControlFlowContext &CFCtx,
287  std::vector<llvm::Optional<TypeErasedDataflowAnalysisState>> &BlockStates,
288  const CFGBlock &Block, const Environment &InitEnv,
289  TypeErasedDataflowAnalysis &Analysis,
290  std::function<void(const CFGStmt &,
292  HandleTransferredStmt) {
294  computeBlockInputState(CFCtx, BlockStates, Block, InitEnv, Analysis);
295  for (const CFGElement &Element : Block) {
296  switch (Element.getKind()) {
298  transferCFGStmt(CFCtx, BlockStates, *Element.getAs<CFGStmt>(), Analysis,
299  State, HandleTransferredStmt);
300  break;
302  if (Analysis.applyBuiltinTransfer())
303  transferCFGInitializer(*Element.getAs<CFGInitializer>(), State);
304  break;
305  default:
306  // FIXME: Evaluate other kinds of `CFGElement`.
307  break;
308  }
309  }
310  return State;
311 }
312 
315  TypeErasedDataflowAnalysis &Analysis,
316  const Environment &InitEnv) {
317  PostOrderCFGView POV(&CFCtx.getCFG());
318  ForwardDataflowWorklist Worklist(CFCtx.getCFG(), &POV);
319 
320  std::vector<llvm::Optional<TypeErasedDataflowAnalysisState>> BlockStates;
321  BlockStates.resize(CFCtx.getCFG().size(), llvm::None);
322 
323  // The entry basic block doesn't contain statements so it can be skipped.
324  const CFGBlock &Entry = CFCtx.getCFG().getEntry();
325  BlockStates[Entry.getBlockID()] = {Analysis.typeErasedInitialElement(),
326  InitEnv};
327  Worklist.enqueueSuccessors(&Entry);
328 
329  // Bugs in lattices and transfer functions can prevent the analysis from
330  // converging. To limit the damage (infinite loops) that these bugs can cause,
331  // limit the number of iterations.
332  // FIXME: Consider making the maximum number of iterations configurable.
333  // FIXME: Set up statistics (see llvm/ADT/Statistic.h) to count average number
334  // of iterations, number of functions that time out, etc.
335  uint32_t Iterations = 0;
336  static constexpr uint32_t MaxIterations = 1 << 16;
337  while (const CFGBlock *Block = Worklist.dequeue()) {
338  if (++Iterations > MaxIterations) {
339  return llvm::createStringError(std::errc::timed_out,
340  "maximum number of iterations reached");
341  }
342 
344  BlockStates[Block->getBlockID()];
345  TypeErasedDataflowAnalysisState NewBlockState =
346  transferBlock(CFCtx, BlockStates, *Block, InitEnv, Analysis);
347 
348  if (OldBlockState.hasValue() &&
349  Analysis.isEqualTypeErased(OldBlockState.getValue().Lattice,
350  NewBlockState.Lattice) &&
351  OldBlockState->Env.equivalentTo(NewBlockState.Env, Analysis)) {
352  // The state of `Block` didn't change after transfer so there's no need to
353  // revisit its successors.
354  continue;
355  }
356 
357  BlockStates[Block->getBlockID()] = std::move(NewBlockState);
358 
359  // Do not add unreachable successor blocks to `Worklist`.
360  if (Block->hasNoReturnElement())
361  continue;
362 
363  Worklist.enqueueSuccessors(Block);
364  }
365  // FIXME: Consider evaluating unreachable basic blocks (those that have a
366  // state set to `llvm::None` at this point) to also analyze dead code.
367 
368  return BlockStates;
369 }
370 
371 } // namespace dataflow
372 } // namespace clang
TypeErasedDataflowAnalysis.h
clang::dataflow::StmtToEnvMapImpl::getEnvironment
const Environment * getEnvironment(const Stmt &S) const override
Returns the environment of the basic block that contains S or nullptr if there isn't one.
Definition: TypeErasedDataflowAnalysis.cpp:48
clang::WhileStmt
WhileStmt - This represents a 'while' stmt.
Definition: Stmt.h:2346
clang::CFGBlock::succ_begin
succ_iterator succ_begin()
Definition: CFG.h:955
clang::CFGBlock::getBlockID
unsigned getBlockID() const
Definition: CFG.h:1074
clang::dataflow::transfer
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env)
Evaluates S and updates Env accordingly.
Definition: Transfer.cpp:593
clang::dataflow::blockIndexInPredecessor
static int blockIndexInPredecessor(const CFGBlock &Pred, const CFGBlock &Block)
Returns the index of Block in the successors of Pred.
Definition: TypeErasedDataflowAnalysis.cpp:62
clang::DynamicInitKind::Initializer
@ Initializer
clang::FieldDecl
Represents a member of a struct/union/class.
Definition: Decl.h:2855
DeclCXX.h
clang::dataflow::StmtToEnvMapImpl::StmtToEnvMapImpl
StmtToEnvMapImpl(const ControlFlowContext &CFCtx, llvm::ArrayRef< llvm::Optional< TypeErasedDataflowAnalysisState >> BlockToState)
Definition: TypeErasedDataflowAnalysis.cpp:42
clang::dataflow::Environment::createStorageLocation
StorageLocation & createStorageLocation(QualType Type)
Creates a storage location appropriate for Type.
Definition: DataflowEnvironment.cpp:319
clang::dataflow::TypeErasedDataflowAnalysisState::Lattice
TypeErasedLattice Lattice
Type-erased model of a program property.
Definition: TypeErasedDataflowAnalysis.h:89
clang::IfStmt
IfStmt - This represents an if/then/else.
Definition: Stmt.h:1909
PostOrderCFGView.h
clang::dataflow::SkipPast::Reference
@ Reference
An optional reference should be skipped past.
llvm::Optional
Definition: LLVM.h:40
clang::dataflow::ControlFlowContext::getStmtToBlock
const llvm::DenseMap< const Stmt *, const CFGBlock * > & getStmtToBlock() const
Returns a mapping from statements to basic blocks that contain them.
Definition: ControlFlowContext.h:41
clang::dataflow::TerminatorVisitor::TerminatorVisitor
TerminatorVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env, int BlockSuccIdx)
Definition: TypeErasedDataflowAnalysis.cpp:75
clang::dataflow::TerminatorVisitor::VisitWhileStmt
void VisitWhileStmt(const WhileStmt *S)
Definition: TypeErasedDataflowAnalysis.cpp:85
llvm::Expected
Definition: LLVM.h:41
clang::CFG::size
unsigned size() const
Return the total number of CFGBlocks within the CFG This is simply a renaming of the getNumBlockIDs()...
Definition: CFG.h:1416
clang::dataflow::TerminatorVisitor::VisitBinaryOperator
void VisitBinaryOperator(const BinaryOperator *S)
Definition: TypeErasedDataflowAnalysis.cpp:91
clang::dataflow::Environment::addToFlowCondition
void addToFlowCondition(BoolValue &Val)
Adds Val to the set of clauses that constitute the flow condition.
Definition: DataflowEnvironment.cpp:554
clang::dataflow::Environment::setStorageLocation
void setStorageLocation(const ValueDecl &D, StorageLocation &Loc)
Assigns Loc as the storage location of D in the environment.
Definition: DataflowEnvironment.cpp:356
clang::ConditionalOperator
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:4145
clang::CFGBlock
Represents a single basic block in a source-level CFG.
Definition: CFG.h:576
clang::CFGBlock::succs
succ_range succs()
Definition: CFG.h:965
clang::dataflow::TypeErasedDataflowAnalysis::transferTypeErased
virtual void transferTypeErased(const Stmt *, TypeErasedLattice &, Environment &)=0
Applies the analysis transfer function for a given statement and type-erased lattice element.
clang::dataflow::StmtToEnvMapImpl
Definition: TypeErasedDataflowAnalysis.cpp:40
clang::dataflow::TerminatorVisitor
Extends the flow condition of an environment based on a terminator statement.
Definition: TypeErasedDataflowAnalysis.cpp:73
clang::BinaryOperator
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3807
clang::dataflow::StmtToEnvMap
Maps statements to the environments of basic blocks that contain them.
Definition: Transfer.h:24
clang::DeclaratorContext::Member
@ Member
clang::dataflow::SkipPast::None
@ None
No indirections should be skipped past.
clang::CFGInitializer::getInitializer
CXXCtorInitializer * getInitializer() const
Definition: CFG.h:230
clang::dataflow::Environment::setValue
void setValue(const StorageLocation &Loc, Value &Val)
Assigns Val as the value of Loc in the environment.
Definition: DataflowEnvironment.cpp:384
clang::dataflow::ignoreCFGOmittedNodes
const Expr & ignoreCFGOmittedNodes(const Expr &E)
Skip past nodes that the CFG does not emit.
Definition: DataflowAnalysisContext.cpp:162
clang::StmtVisitorBase::Visit
RetTy Visit(PTR(Stmt) S, ParamTys... P)
Definition: StmtVisitor.h:43
clang::CFGElement::Initializer
@ Initializer
Definition: CFG.h:59
llvm::DenseSet
Definition: Sema.h:77
OperationKinds.h
clang::dataflow::transferBlock
TypeErasedDataflowAnalysisState transferBlock(const ControlFlowContext &CFCtx, std::vector< llvm::Optional< TypeErasedDataflowAnalysisState >> &BlockStates, const CFGBlock &Block, const Environment &InitEnv, TypeErasedDataflowAnalysis &Analysis, std::function< void(const CFGStmt &, const TypeErasedDataflowAnalysisState &)> HandleTransferredStmt=nullptr)
Transfers the state of a basic block by evaluating each of its statements in the context of Analysis ...
Definition: TypeErasedDataflowAnalysis.cpp:285
DataflowWorklist.h
clang::dataflow::transferCFGInitializer
static void transferCFGInitializer(const CFGInitializer &CfgInit, TypeErasedDataflowAnalysisState &State)
Transfers State by evaluating CfgInit.
Definition: TypeErasedDataflowAnalysis.cpp:251
clang::PostOrderCFGView
Definition: PostOrderCFGView.h:28
clang::CFGElement::Statement
@ Statement
Definition: CFG.h:66
clang::dataflow::TypeErasedDataflowAnalysis::typeErasedInitialElement
virtual TypeErasedLattice typeErasedInitialElement()=0
Returns a type-erased lattice element that models the initial state of a basic block.
clang::CFGStmt
Definition: CFG.h:132
clang::ForwardDataflowWorklist
A worklist implementation for forward dataflow analysis.
Definition: DataflowWorklist.h:62
clang::dataflow::Environment::getValue
Value * getValue(const StorageLocation &Loc) const
Returns the value assigned to Loc in the environment or null if Loc isn't assigned a value in the env...
Definition: DataflowEnvironment.cpp:417
clang::CFGInitializer
Represents C++ base or member initializer from constructor's initialization list.
Definition: CFG.h:225
clang::dataflow::TerminatorVisitor::VisitConditionalOperator
void VisitConditionalOperator(const ConditionalOperator *S)
Definition: TypeErasedDataflowAnalysis.cpp:98
llvm::ArrayRef
Definition: LLVM.h:34
clang::dataflow::ControlFlowContext
Holds CFG and other derived context that is needed to perform dataflow analysis.
Definition: ControlFlowContext.h:31
StmtVisitor.h
clang::DataflowWorklistBase::dequeue
const CFGBlock * dequeue()
Definition: DataflowWorklist.h:42
clang::CFGStmt::getStmt
const Stmt * getStmt() const
Definition: CFG.h:138
State
LineState State
Definition: UnwrappedLineFormatter.cpp:1089
clang::CFG::getEntry
CFGBlock & getEntry()
Definition: CFG.h:1331
clang::dataflow::computeBlockInputState
static TypeErasedDataflowAnalysisState computeBlockInputState(const ControlFlowContext &CFCtx, std::vector< llvm::Optional< TypeErasedDataflowAnalysisState >> &BlockStates, const CFGBlock &Block, const Environment &InitEnv, TypeErasedDataflowAnalysis &Analysis)
Computes the input state for a given basic block by joining the output states of its predecessors.
Definition: TypeErasedDataflowAnalysis.cpp:150
DataflowEnvironment.h
clang::ConstStmtVisitor
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
Definition: StmtVisitor.h:193
clang::CFGBlock::AdjacentBlock
This class represents a potential adjacent block in the CFG.
Definition: CFG.h:791
clang::dataflow::Environment::makeAtomicBoolValue
BoolValue & makeAtomicBoolValue() const
Returns an atomic boolean value.
Definition: DataflowEnvironment.h:262
clang::ForwardDataflowWorklist::enqueueSuccessors
void enqueueSuccessors(const CFGBlock *Block)
Definition: DataflowWorklist.h:71
clang::dataflow::TypeErasedDataflowAnalysis
Type-erased base class for dataflow analyses built on a single lattice type.
Definition: TypeErasedDataflowAnalysis.h:44
clang::CFGElement
Represents a top-level expression in a basic block.
Definition: CFG.h:55
Transfer.h
clang
Definition: CalledOnceCheck.h:17
CFG.h
clang::DeclaratorContext::Block
@ Block
clang::Stmt
Stmt - This represents one statement.
Definition: Stmt.h:69
clang::dataflow::TypeErasedDataflowAnalysis::isEqualTypeErased
virtual bool isEqualTypeErased(const TypeErasedLattice &, const TypeErasedLattice &)=0
Returns true if and only if the two given type-erased lattice elements are equal.
clang::dataflow::runTypeErasedDataflowAnalysis
llvm::Expected< std::vector< llvm::Optional< TypeErasedDataflowAnalysisState > > > runTypeErasedDataflowAnalysis(const ControlFlowContext &CFCtx, TypeErasedDataflowAnalysis &Analysis, const Environment &InitEnv)
Performs dataflow analysis and returns a mapping from basic block IDs to dataflow analysis states tha...
Definition: TypeErasedDataflowAnalysis.cpp:314
clang::dataflow::TypeErasedDataflowAnalysis::joinTypeErased
virtual LatticeJoinEffect joinTypeErased(TypeErasedLattice &, const TypeErasedLattice &)=0
Joins two type-erased lattice elements by computing their least upper bound.
clang::dataflow::Environment::getStorageLocation
StorageLocation * getStorageLocation(const ValueDecl &D, SkipPast SP) const
Returns the storage location assigned to D in the environment, applying the SP policy for skipping pa...
Definition: DataflowEnvironment.cpp:361
clang::dataflow::TerminatorVisitor::VisitIfStmt
void VisitIfStmt(const IfStmt *S)
Definition: TypeErasedDataflowAnalysis.cpp:79
clang::dataflow::Environment
Holds the state of the program (store and heap) at a given program point.
Definition: DataflowEnvironment.h:57
clang::dataflow::TypeErasedDataflowAnalysis::applyBuiltinTransfer
bool applyBuiltinTransfer() const
Determines whether to apply the built-in transfer functions, which model the heap and stack in the En...
Definition: TypeErasedDataflowAnalysis.h:83
clang::Expr
This represents one expression.
Definition: Expr.h:109
clang::dataflow::TypeErasedDataflowAnalysisState
Type-erased model of the program at a given program point.
Definition: TypeErasedDataflowAnalysis.h:87
clang::CXXCtorInitializer
Represents a C++ base or member initializer.
Definition: DeclCXX.h:2192
clang::dataflow::TypeErasedDataflowAnalysisState::Env
Environment Env
Model of the state of the program (store and heap).
Definition: TypeErasedDataflowAnalysis.h:92
clang::dataflow::transferCFGStmt
static void transferCFGStmt(const ControlFlowContext &CFCtx, llvm::ArrayRef< llvm::Optional< TypeErasedDataflowAnalysisState >> BlockStates, const CFGStmt &CfgStmt, TypeErasedDataflowAnalysis &Analysis, TypeErasedDataflowAnalysisState &State, std::function< void(const CFGStmt &, const TypeErasedDataflowAnalysisState &)> HandleTransferredStmt)
Transfers State by evaluating CfgStmt in the context of Analysis.
Definition: TypeErasedDataflowAnalysis.cpp:231
Value.h
clang::dataflow::Environment::makeNot
BoolValue & makeNot(BoolValue &Val) const
Returns a boolean value that represents the negation of Val.
Definition: DataflowEnvironment.h:284
clang::dataflow::ControlFlowContext::getCFG
const CFG & getCFG() const
Returns the CFG that is stored in this context.
Definition: ControlFlowContext.h:38