clang  15.0.0git
DataflowEnvironment.cpp
Go to the documentation of this file.
1 //===-- DataflowEnvironment.cpp ---------------------------------*- 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 // This file defines an Environment class that is used by dataflow analyses
10 // that run over Control-Flow Graphs (CFGs) to keep track of the state of the
11 // program at given program points.
12 //
13 //===----------------------------------------------------------------------===//
14 
16 #include "clang/AST/Decl.h"
17 #include "clang/AST/DeclCXX.h"
18 #include "clang/AST/ExprCXX.h"
19 #include "clang/AST/Type.h"
23 #include "llvm/ADT/DenseMap.h"
24 #include "llvm/ADT/DenseSet.h"
25 #include "llvm/Support/Casting.h"
26 #include "llvm/Support/ErrorHandling.h"
27 #include <cassert>
28 #include <memory>
29 #include <utility>
30 
31 namespace clang {
32 namespace dataflow {
33 
34 // FIXME: convert these to parameters of the analysis or environment. Current
35 // settings have been experimentaly validated, but only for a particular
36 // analysis.
37 static constexpr int MaxCompositeValueDepth = 3;
38 static constexpr int MaxCompositeValueSize = 1000;
39 
40 /// Returns a map consisting of key-value entries that are present in both maps.
41 template <typename K, typename V>
42 llvm::DenseMap<K, V> intersectDenseMaps(const llvm::DenseMap<K, V> &Map1,
43  const llvm::DenseMap<K, V> &Map2) {
44  llvm::DenseMap<K, V> Result;
45  for (auto &Entry : Map1) {
46  auto It = Map2.find(Entry.first);
47  if (It != Map2.end() && Entry.second == It->second)
48  Result.insert({Entry.first, Entry.second});
49  }
50  return Result;
51 }
52 
53 static bool areEquivalentIndirectionValues(Value *Val1, Value *Val2) {
54  if (auto *IndVal1 = dyn_cast<ReferenceValue>(Val1)) {
55  auto *IndVal2 = cast<ReferenceValue>(Val2);
56  return &IndVal1->getReferentLoc() == &IndVal2->getReferentLoc();
57  }
58  if (auto *IndVal1 = dyn_cast<PointerValue>(Val1)) {
59  auto *IndVal2 = cast<PointerValue>(Val2);
60  return &IndVal1->getPointeeLoc() == &IndVal2->getPointeeLoc();
61  }
62  return false;
63 }
64 
65 /// Returns true if and only if `Val1` is equivalent to `Val2`.
66 static bool equivalentValues(QualType Type, Value *Val1,
67  const Environment &Env1, Value *Val2,
68  const Environment &Env2,
69  Environment::ValueModel &Model) {
70  return Val1 == Val2 || areEquivalentIndirectionValues(Val1, Val2) ||
71  Model.compareEquivalent(Type, *Val1, Env1, *Val2, Env2);
72 }
73 
74 /// Attempts to merge distinct values `Val1` and `Val2` in `Env1` and `Env2`,
75 /// respectively, of the same type `Type`. Merging generally produces a single
76 /// value that (soundly) approximates the two inputs, although the actual
77 /// meaning depends on `Model`.
79  const Environment &Env1, Value *Val2,
80  const Environment &Env2,
81  Environment &MergedEnv,
82  Environment::ValueModel &Model) {
83  // Join distinct boolean values preserving information about the constraints
84  // in the respective path conditions.
85  //
86  // FIXME: Does not work for backedges, since the two (or more) paths will not
87  // have mutually exclusive conditions.
88  if (auto *Expr1 = dyn_cast<BoolValue>(Val1)) {
89  auto *Expr2 = cast<BoolValue>(Val2);
90  auto &MergedVal = MergedEnv.makeAtomicBoolValue();
91  MergedEnv.addToFlowCondition(MergedEnv.makeOr(
92  MergedEnv.makeAnd(Env1.getFlowConditionToken(),
93  MergedEnv.makeIff(MergedVal, *Expr1)),
94  MergedEnv.makeAnd(Env2.getFlowConditionToken(),
95  MergedEnv.makeIff(MergedVal, *Expr2))));
96  return &MergedVal;
97  }
98 
99  // FIXME: add unit tests that cover this statement.
100  if (areEquivalentIndirectionValues(Val1, Val2)) {
101  return Val1;
102  }
103 
104  // FIXME: Consider destroying `MergedValue` immediately if `ValueModel::merge`
105  // returns false to avoid storing unneeded values in `DACtx`.
106  if (Value *MergedVal = MergedEnv.createValue(Type))
107  if (Model.merge(Type, *Val1, Env1, *Val2, Env2, *MergedVal, MergedEnv))
108  return MergedVal;
109 
110  return nullptr;
111 }
112 
113 /// Initializes a global storage value.
114 static void initGlobalVar(const VarDecl &D, Environment &Env) {
115  if (!D.hasGlobalStorage() ||
116  Env.getStorageLocation(D, SkipPast::None) != nullptr)
117  return;
118 
119  auto &Loc = Env.createStorageLocation(D);
120  Env.setStorageLocation(D, Loc);
121  if (auto *Val = Env.createValue(D.getType()))
122  Env.setValue(Loc, *Val);
123 }
124 
125 /// Initializes a global storage value.
126 static void initGlobalVar(const Decl &D, Environment &Env) {
127  if (auto *V = dyn_cast<VarDecl>(&D))
128  initGlobalVar(*V, Env);
129 }
130 
131 /// Initializes global storage values that are declared or referenced from
132 /// sub-statements of `S`.
133 // FIXME: Add support for resetting globals after function calls to enable
134 // the implementation of sound analyses.
135 static void initGlobalVars(const Stmt &S, Environment &Env) {
136  for (auto *Child : S.children()) {
137  if (Child != nullptr)
138  initGlobalVars(*Child, Env);
139  }
140 
141  if (auto *DS = dyn_cast<DeclStmt>(&S)) {
142  if (DS->isSingleDecl()) {
143  initGlobalVar(*DS->getSingleDecl(), Env);
144  } else {
145  for (auto *D : DS->getDeclGroup())
146  initGlobalVar(*D, Env);
147  }
148  } else if (auto *E = dyn_cast<DeclRefExpr>(&S)) {
149  initGlobalVar(*E->getDecl(), Env);
150  } else if (auto *E = dyn_cast<MemberExpr>(&S)) {
151  initGlobalVar(*E->getMemberDecl(), Env);
152  }
153 }
154 
156  : DACtx(&DACtx), FlowConditionToken(&DACtx.makeFlowConditionToken()) {}
157 
159  : DACtx(Other.DACtx), DeclToLoc(Other.DeclToLoc),
160  ExprToLoc(Other.ExprToLoc), LocToVal(Other.LocToVal),
161  MemberLocToStruct(Other.MemberLocToStruct),
162  FlowConditionToken(&DACtx->forkFlowCondition(*Other.FlowConditionToken)) {
163 }
164 
166  Environment Copy(Other);
167  *this = std::move(Copy);
168  return *this;
169 }
170 
172  const DeclContext &DeclCtx)
173  : Environment(DACtx) {
174  if (const auto *FuncDecl = dyn_cast<FunctionDecl>(&DeclCtx)) {
175  assert(FuncDecl->getBody() != nullptr);
176  initGlobalVars(*FuncDecl->getBody(), *this);
177  for (const auto *ParamDecl : FuncDecl->parameters()) {
178  assert(ParamDecl != nullptr);
179  auto &ParamLoc = createStorageLocation(*ParamDecl);
180  setStorageLocation(*ParamDecl, ParamLoc);
181  if (Value *ParamVal = createValue(ParamDecl->getType()))
182  setValue(ParamLoc, *ParamVal);
183  }
184  }
185 
186  if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(&DeclCtx)) {
187  auto *Parent = MethodDecl->getParent();
188  assert(Parent != nullptr);
189  if (Parent->isLambda())
190  MethodDecl = dyn_cast<CXXMethodDecl>(Parent->getDeclContext());
191 
192  if (MethodDecl && !MethodDecl->isStatic()) {
193  QualType ThisPointeeType = MethodDecl->getThisObjectType();
194  // FIXME: Add support for union types.
195  if (!ThisPointeeType->isUnionType()) {
196  auto &ThisPointeeLoc = createStorageLocation(ThisPointeeType);
197  DACtx.setThisPointeeStorageLocation(ThisPointeeLoc);
198  if (Value *ThisPointeeVal = createValue(ThisPointeeType))
199  setValue(ThisPointeeLoc, *ThisPointeeVal);
200  }
201  }
202  }
203 }
204 
206  Environment::ValueModel &Model) const {
207  assert(DACtx == Other.DACtx);
208 
209  if (DeclToLoc != Other.DeclToLoc)
210  return false;
211 
212  if (ExprToLoc != Other.ExprToLoc)
213  return false;
214 
215  // Compare the contents for the intersection of their domains.
216  for (auto &Entry : LocToVal) {
217  const StorageLocation *Loc = Entry.first;
218  assert(Loc != nullptr);
219 
220  Value *Val = Entry.second;
221  assert(Val != nullptr);
222 
223  auto It = Other.LocToVal.find(Loc);
224  if (It == Other.LocToVal.end())
225  continue;
226  assert(It->second != nullptr);
227 
228  if (!equivalentValues(Loc->getType(), Val, *this, It->second, Other, Model))
229  return false;
230  }
231 
232  return true;
233 }
234 
236  Environment::ValueModel &Model) {
237  assert(DACtx == Other.DACtx);
238 
239  auto Effect = LatticeJoinEffect::Unchanged;
240 
241  Environment JoinedEnv(*DACtx);
242 
243  JoinedEnv.DeclToLoc = intersectDenseMaps(DeclToLoc, Other.DeclToLoc);
244  if (DeclToLoc.size() != JoinedEnv.DeclToLoc.size())
246 
247  JoinedEnv.ExprToLoc = intersectDenseMaps(ExprToLoc, Other.ExprToLoc);
248  if (ExprToLoc.size() != JoinedEnv.ExprToLoc.size())
250 
251  JoinedEnv.MemberLocToStruct =
252  intersectDenseMaps(MemberLocToStruct, Other.MemberLocToStruct);
253  if (MemberLocToStruct.size() != JoinedEnv.MemberLocToStruct.size())
255 
256  // FIXME: set `Effect` as needed.
257  JoinedEnv.FlowConditionToken = &DACtx->joinFlowConditions(
258  *FlowConditionToken, *Other.FlowConditionToken);
259 
260  for (auto &Entry : LocToVal) {
261  const StorageLocation *Loc = Entry.first;
262  assert(Loc != nullptr);
263 
264  Value *Val = Entry.second;
265  assert(Val != nullptr);
266 
267  auto It = Other.LocToVal.find(Loc);
268  if (It == Other.LocToVal.end())
269  continue;
270  assert(It->second != nullptr);
271 
272  if (Val == It->second) {
273  JoinedEnv.LocToVal.insert({Loc, Val});
274  continue;
275  }
276 
277  if (Value *MergedVal = mergeDistinctValues(
278  Loc->getType(), Val, *this, It->second, Other, JoinedEnv, Model))
279  JoinedEnv.LocToVal.insert({Loc, MergedVal});
280  }
281  if (LocToVal.size() != JoinedEnv.LocToVal.size())
283 
284  *this = std::move(JoinedEnv);
285 
286  return Effect;
287 }
288 
290  return DACtx->getStableStorageLocation(Type);
291 }
292 
294  // Evaluated declarations are always assigned the same storage locations to
295  // ensure that the environment stabilizes across loop iterations. Storage
296  // locations for evaluated declarations are stored in the analysis context.
297  return DACtx->getStableStorageLocation(D);
298 }
299 
301  // Evaluated expressions are always assigned the same storage locations to
302  // ensure that the environment stabilizes across loop iterations. Storage
303  // locations for evaluated expressions are stored in the analysis context.
304  return DACtx->getStableStorageLocation(E);
305 }
306 
308  assert(DeclToLoc.find(&D) == DeclToLoc.end());
309  DeclToLoc[&D] = &Loc;
310 }
311 
313  SkipPast SP) const {
314  auto It = DeclToLoc.find(&D);
315  return It == DeclToLoc.end() ? nullptr : &skip(*It->second, SP);
316 }
317 
319  const Expr &CanonE = ignoreCFGOmittedNodes(E);
320  assert(ExprToLoc.find(&CanonE) == ExprToLoc.end());
321  ExprToLoc[&CanonE] = &Loc;
322 }
323 
325  SkipPast SP) const {
326  // FIXME: Add a test with parens.
327  auto It = ExprToLoc.find(&ignoreCFGOmittedNodes(E));
328  return It == ExprToLoc.end() ? nullptr : &skip(*It->second, SP);
329 }
330 
332  return DACtx->getThisPointeeStorageLocation();
333 }
334 
336  return DACtx->getOrCreateNullPointerValue(PointeeType);
337 }
338 
340  LocToVal[&Loc] = &Val;
341 
342  if (auto *StructVal = dyn_cast<StructValue>(&Val)) {
343  auto &AggregateLoc = *cast<AggregateStorageLocation>(&Loc);
344 
345  const QualType Type = AggregateLoc.getType();
346  assert(Type->isStructureOrClassType());
347 
348  for (const FieldDecl *Field : getObjectFields(Type)) {
349  assert(Field != nullptr);
350  StorageLocation &FieldLoc = AggregateLoc.getChild(*Field);
351  MemberLocToStruct[&FieldLoc] = std::make_pair(StructVal, Field);
352  if (auto *FieldVal = StructVal->getChild(*Field))
353  setValue(FieldLoc, *FieldVal);
354  }
355  }
356 
357  auto IT = MemberLocToStruct.find(&Loc);
358  if (IT != MemberLocToStruct.end()) {
359  // `Loc` is the location of a struct member so we need to also update the
360  // value of the member in the corresponding `StructValue`.
361 
362  assert(IT->second.first != nullptr);
363  StructValue &StructVal = *IT->second.first;
364 
365  assert(IT->second.second != nullptr);
366  const ValueDecl &Member = *IT->second.second;
367 
368  StructVal.setChild(Member, Val);
369  }
370 }
371 
373  auto It = LocToVal.find(&Loc);
374  return It == LocToVal.end() ? nullptr : It->second;
375 }
376 
378  auto *Loc = getStorageLocation(D, SP);
379  if (Loc == nullptr)
380  return nullptr;
381  return getValue(*Loc);
382 }
383 
384 Value *Environment::getValue(const Expr &E, SkipPast SP) const {
385  auto *Loc = getStorageLocation(E, SP);
386  if (Loc == nullptr)
387  return nullptr;
388  return getValue(*Loc);
389 }
390 
392  llvm::DenseSet<QualType> Visited;
393  int CreatedValuesCount = 0;
394  Value *Val = createValueUnlessSelfReferential(Type, Visited, /*Depth=*/0,
395  CreatedValuesCount);
396  if (CreatedValuesCount > MaxCompositeValueSize) {
397  llvm::errs() << "Attempting to initialize a huge value of type: " << Type
398  << '\n';
399  }
400  return Val;
401 }
402 
403 Value *Environment::createValueUnlessSelfReferential(
405  int &CreatedValuesCount) {
406  assert(!Type.isNull());
407 
408  // Allow unlimited fields at depth 1; only cap at deeper nesting levels.
409  if ((Depth > 1 && CreatedValuesCount > MaxCompositeValueSize) ||
411  return nullptr;
412 
413  if (Type->isBooleanType()) {
414  CreatedValuesCount++;
415  return &makeAtomicBoolValue();
416  }
417 
418  if (Type->isIntegerType()) {
419  CreatedValuesCount++;
420  return &takeOwnership(std::make_unique<IntegerValue>());
421  }
422 
423  if (Type->isReferenceType()) {
424  CreatedValuesCount++;
425  QualType PointeeType = Type->castAs<ReferenceType>()->getPointeeType();
426  auto &PointeeLoc = createStorageLocation(PointeeType);
427 
428  if (Visited.insert(PointeeType.getCanonicalType()).second) {
429  Value *PointeeVal = createValueUnlessSelfReferential(
430  PointeeType, Visited, Depth, CreatedValuesCount);
431  Visited.erase(PointeeType.getCanonicalType());
432 
433  if (PointeeVal != nullptr)
434  setValue(PointeeLoc, *PointeeVal);
435  }
436 
437  return &takeOwnership(std::make_unique<ReferenceValue>(PointeeLoc));
438  }
439 
440  if (Type->isPointerType()) {
441  CreatedValuesCount++;
442  QualType PointeeType = Type->castAs<PointerType>()->getPointeeType();
443  auto &PointeeLoc = createStorageLocation(PointeeType);
444 
445  if (Visited.insert(PointeeType.getCanonicalType()).second) {
446  Value *PointeeVal = createValueUnlessSelfReferential(
447  PointeeType, Visited, Depth, CreatedValuesCount);
448  Visited.erase(PointeeType.getCanonicalType());
449 
450  if (PointeeVal != nullptr)
451  setValue(PointeeLoc, *PointeeVal);
452  }
453 
454  return &takeOwnership(std::make_unique<PointerValue>(PointeeLoc));
455  }
456 
457  if (Type->isStructureOrClassType()) {
458  CreatedValuesCount++;
459  // FIXME: Initialize only fields that are accessed in the context that is
460  // being analyzed.
461  llvm::DenseMap<const ValueDecl *, Value *> FieldValues;
462  for (const FieldDecl *Field : getObjectFields(Type)) {
463  assert(Field != nullptr);
464 
465  QualType FieldType = Field->getType();
466  if (Visited.contains(FieldType.getCanonicalType()))
467  continue;
468 
469  Visited.insert(FieldType.getCanonicalType());
470  if (auto *FieldValue = createValueUnlessSelfReferential(
471  FieldType, Visited, Depth + 1, CreatedValuesCount))
472  FieldValues.insert({Field, FieldValue});
473  Visited.erase(FieldType.getCanonicalType());
474  }
475 
476  return &takeOwnership(
477  std::make_unique<StructValue>(std::move(FieldValues)));
478  }
479 
480  return nullptr;
481 }
482 
483 StorageLocation &Environment::skip(StorageLocation &Loc, SkipPast SP) const {
484  switch (SP) {
485  case SkipPast::None:
486  return Loc;
487  case SkipPast::Reference:
488  // References cannot be chained so we only need to skip past one level of
489  // indirection.
490  if (auto *Val = dyn_cast_or_null<ReferenceValue>(getValue(Loc)))
491  return Val->getReferentLoc();
492  return Loc;
494  StorageLocation &LocPastRef = skip(Loc, SkipPast::Reference);
495  if (auto *Val = dyn_cast_or_null<PointerValue>(getValue(LocPastRef)))
496  return Val->getPointeeLoc();
497  return LocPastRef;
498  }
499  llvm_unreachable("bad SkipPast kind");
500 }
501 
502 const StorageLocation &Environment::skip(const StorageLocation &Loc,
503  SkipPast SP) const {
504  return skip(*const_cast<StorageLocation *>(&Loc), SP);
505 }
506 
508  DACtx->addFlowConditionConstraint(*FlowConditionToken, Val);
509 }
510 
512  return DACtx->flowConditionImplies(*FlowConditionToken, Val);
513 }
514 
515 } // namespace dataflow
516 } // namespace clang
clang::dataflow::Environment::getOrCreateNullPointerValue
PointerValue & getOrCreateNullPointerValue(QualType PointeeType)
Returns a pointer value that represents a null pointer.
Definition: DataflowEnvironment.cpp:335
clang::dataflow::MaxCompositeValueSize
static constexpr int MaxCompositeValueSize
Definition: DataflowEnvironment.cpp:38
clang::DeclContext
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1376
clang::VarDecl::hasGlobalStorage
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition: Decl.h:1141
clang::QualType
A (possibly-)qualified type.
Definition: Type.h:731
clang::dataflow::StorageLocation
Base class for elements of the local variable store and of the heap.
Definition: StorageLocation.h:28
clang::FieldDecl
Represents a member of a struct/union/class.
Definition: Decl.h:2862
DeclCXX.h
clang::dataflow::getObjectFields
llvm::DenseSet< const FieldDecl * > getObjectFields(QualType Type)
Returns the set of all fields in the type.
Definition: DataflowAnalysisContext.cpp:336
clang::dataflow::Environment::createStorageLocation
StorageLocation & createStorageLocation(QualType Type)
Creates a storage location appropriate for Type.
Definition: DataflowEnvironment.cpp:289
clang::dataflow::SkipPast::Reference
@ Reference
An optional reference should be skipped past.
clang::dataflow::Environment::ValueModel::merge
virtual bool merge(QualType Type, const Value &Val1, const Environment &Env1, const Value &Val2, const Environment &Env2, Value &MergedVal, Environment &MergedEnv)
Modifies MergedVal to approximate both Val1 and Val2.
Definition: DataflowEnvironment.h:104
clang::dataflow::Environment::createValue
Value * createValue(QualType Type)
Creates a value appropriate for Type, if Type is supported, otherwise return null.
Definition: DataflowEnvironment.cpp:391
clang::dataflow::Environment::flowConditionImplies
bool flowConditionImplies(BoolValue &Val) const
Returns true if and only if the clauses that constitute the flow condition imply that Val is true.
Definition: DataflowEnvironment.cpp:511
clang::dataflow::DataflowAnalysisContext::flowConditionImplies
bool flowConditionImplies(AtomicBoolValue &Token, BoolValue &Val)
Returns true if and only if the constraints of the flow condition identified by Token imply that Val ...
Definition: DataflowAnalysisContext.cpp:164
clang::dataflow::Environment::equivalentTo
bool equivalentTo(const Environment &Other, Environment::ValueModel &Model) const
Returns true if and only if the environment is equivalent to Other, i.e the two environments:
Definition: DataflowEnvironment.cpp:205
clang::dataflow::LatticeJoinEffect
LatticeJoinEffect
Effect indicating whether a lattice join operation resulted in a new value.
Definition: DataflowLattice.h:21
clang::dataflow::Environment::addToFlowCondition
void addToFlowCondition(BoolValue &Val)
Adds Val to the set of clauses that constitute the flow condition.
Definition: DataflowEnvironment.cpp:507
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:307
clang::Type
The base class of the type hierarchy.
Definition: Type.h:1556
Decl.h
clang::dataflow::DataflowAnalysisContext::getStableStorageLocation
StorageLocation & getStableStorageLocation(QualType Type)
Returns a stable storage location appropriate for Type.
Definition: DataflowAnalysisContext.cpp:26
V
#define V(N, I)
Definition: ASTContext.h:3184
clang::dataflow::DataflowAnalysisContext
Owns objects that encompass the state of a program and stores context that is used during dataflow an...
Definition: DataflowAnalysisContext.h:53
clang::dataflow::Environment::getFlowConditionToken
AtomicBoolValue & getFlowConditionToken() const
Returns the token that identifies the flow condition of the environment.
Definition: DataflowEnvironment.h:309
clang::dataflow::Environment::makeOr
BoolValue & makeOr(BoolValue &LHS, BoolValue &RHS) const
Returns a boolean value that represents the disjunction of LHS and RHS.
Definition: DataflowEnvironment.h:282
clang::DeclaratorContext::Member
@ Member
clang::dataflow::SkipPast::None
@ None
No indirections should be skipped past.
clang::dataflow::LatticeJoinEffect::Changed
@ Changed
Depth
int Depth
Definition: ASTDiff.cpp:191
clang::dataflow::intersectDenseMaps
llvm::DenseMap< K, V > intersectDenseMaps(const llvm::DenseMap< K, V > &Map1, const llvm::DenseMap< K, V > &Map2)
Returns a map consisting of key-value entries that are present in both maps.
Definition: DataflowEnvironment.cpp:42
clang::dataflow::Environment::setValue
void setValue(const StorageLocation &Loc, Value &Val)
Assigns Val as the value of Loc in the environment.
Definition: DataflowEnvironment.cpp:339
clang::dataflow::equivalentValues
static bool equivalentValues(QualType Type, Value *Val1, const Environment &Env1, Value *Val2, const Environment &Env2, Environment::ValueModel &Model)
Returns true if and only if Val1 is equivalent to Val2.
Definition: DataflowEnvironment.cpp:66
clang::dataflow::ignoreCFGOmittedNodes
const Expr & ignoreCFGOmittedNodes(const Expr &E)
Skip past nodes that the CFG does not emit.
Definition: DataflowAnalysisContext.cpp:301
clang::dataflow::mergeDistinctValues
static Value * mergeDistinctValues(QualType Type, Value *Val1, const Environment &Env1, Value *Val2, const Environment &Env2, Environment &MergedEnv, Environment::ValueModel &Model)
Attempts to merge distinct values Val1 and Val2 in Env1 and Env2, respectively, of the same type Type...
Definition: DataflowEnvironment.cpp:78
clang::index::SymbolKind::Field
@ Field
clang::dataflow::DataflowAnalysisContext::setThisPointeeStorageLocation
void setThisPointeeStorageLocation(StorageLocation &Loc)
Assigns Loc as the storage location of the this pointee.
Definition: DataflowAnalysisContext.h:145
Type.h
clang::dataflow::DataflowAnalysisContext::addFlowConditionConstraint
void addFlowConditionConstraint(AtomicBoolValue &Token, BoolValue &Constraint)
Adds Constraint to the flow condition identified by Token.
Definition: DataflowAnalysisContext.cpp:130
clang::VarDecl
Represents a variable declaration or definition.
Definition: Decl.h:874
llvm::DenseSet
Definition: Sema.h:77
ExprCXX.h
clang::dataflow::StructValue::setChild
void setChild(const ValueDecl &D, Value &Val)
Assigns Val as the child value for D.
Definition: Value.h:232
clang::dataflow::StorageLocation::getType
QualType getType() const
Definition: StorageLocation.h:44
clang::dataflow::Environment::getThisPointeeStorageLocation
StorageLocation * getThisPointeeStorageLocation() const
Returns the storage location assigned to the this pointee in the environment or null if the this poin...
Definition: DataflowEnvironment.cpp:331
clang::dataflow::Environment::ValueModel
Supplements Environment with non-standard comparison and join operations.
Definition: DataflowEnvironment.h:61
clang::dataflow::DataflowAnalysisContext::joinFlowConditions
AtomicBoolValue & joinFlowConditions(AtomicBoolValue &FirstToken, AtomicBoolValue &SecondToken)
Creates a new flow condition that represents the disjunction of the flow conditions identified by Fir...
Definition: DataflowAnalysisContext.cpp:147
clang::dataflow::BoolValue
Models a boolean.
Definition: Value.h:79
clang::dataflow::MaxCompositeValueDepth
static constexpr int MaxCompositeValueDepth
Definition: DataflowEnvironment.cpp:37
clang::Type::isUnionType
bool isUnionType() const
Definition: Type.cpp:595
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:372
clang::dataflow::DataflowAnalysisContext::getOrCreateNullPointerValue
PointerValue & getOrCreateNullPointerValue(QualType PointeeType)
Returns a pointer value that represents a null pointer.
Definition: DataflowAnalysisContext.cpp:59
DataflowLattice.h
clang::dataflow::initGlobalVar
static void initGlobalVar(const VarDecl &D, Environment &Env)
Initializes a global storage value.
Definition: DataflowEnvironment.cpp:114
clang::ValueDecl
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:674
clang::dataflow::Environment::operator=
Environment & operator=(const Environment &Other)
Definition: DataflowEnvironment.cpp:165
Value
Value
Definition: UninitializedValues.cpp:102
clang::Decl
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:83
clang::dataflow::SkipPast::ReferenceThenPointer
@ ReferenceThenPointer
An optional reference should be skipped past, then an optional pointer should be skipped past.
DataflowEnvironment.h
clang::dataflow::Environment::makeAtomicBoolValue
BoolValue & makeAtomicBoolValue() const
Returns an atomic boolean value.
Definition: DataflowEnvironment.h:266
clang::Type::isStructureOrClassType
bool isStructureOrClassType() const
Definition: Type.cpp:581
clang::Type::isBooleanType
bool isBooleanType() const
Definition: Type.h:7212
clang::dataflow::Environment::ValueModel::compareEquivalent
virtual bool compareEquivalent(QualType Type, const Value &Val1, const Environment &Env1, const Value &Val2, const Environment &Env2)
Returns true if and only if Val1 is equivalent to Val2.
Definition: DataflowEnvironment.h:75
clang::dataflow::StructValue
Models a value of struct or class type, with a flat map of fields to child storage locations,...
Definition: Value.h:211
clang
Definition: CalledOnceCheck.h:17
clang::dataflow::initGlobalVars
static void initGlobalVars(const Stmt &S, Environment &Env)
Initializes global storage values that are declared or referenced from sub-statements of S.
Definition: DataflowEnvironment.cpp:135
clang::Stmt
Stmt - This represents one statement.
Definition: Stmt.h:70
clang::dataflow::SkipPast
SkipPast
Indicates what kind of indirections should be skipped past when retrieving storage locations or value...
Definition: DataflowEnvironment.h:41
clang::dataflow::DataflowAnalysisContext::getThisPointeeStorageLocation
StorageLocation * getThisPointeeStorageLocation() const
Returns the storage location assigned to the this pointee or null if the this pointee has no assigned...
Definition: DataflowAnalysisContext.h:152
clang::dataflow::LatticeJoinEffect::Unchanged
@ Unchanged
clang::dataflow::Environment::makeAnd
BoolValue & makeAnd(BoolValue &LHS, BoolValue &RHS) const
Returns a boolean value that represents the conjunction of LHS and RHS.
Definition: DataflowEnvironment.h:274
clang::dataflow::Environment::takeOwnership
std::enable_if< std::is_base_of< StorageLocation, T >::value, T & >::type takeOwnership(std::unique_ptr< T > Loc)
Transfers ownership of Loc to the analysis context and returns a reference to it.
Definition: DataflowEnvironment.h:243
clang::dataflow::Value
Base class for all values computed by abstract interpretation.
Definition: Value.h:32
clang::dataflow::Environment::makeIff
BoolValue & makeIff(BoolValue &LHS, BoolValue &RHS) const
Returns a boolean value represents LHS <=> RHS.
Definition: DataflowEnvironment.h:304
StorageLocation.h
Parent
NodeId Parent
Definition: ASTDiff.cpp:192
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:312
clang::dataflow::Environment
Holds the state of the program (store and heap) at a given program point.
Definition: DataflowEnvironment.h:57
clang::dataflow::PointerValue
Models a symbolic pointer. Specifically, any value of type T*.
Definition: Value.h:193
clang::ValueDecl::getType
QualType getType() const
Definition: Decl.h:685
clang::Type::isIntegerType
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:7128
clang::Expr
This represents one expression.
Definition: Expr.h:109
clang::dataflow::Environment::Environment
Environment(DataflowAnalysisContext &DACtx)
Creates an environment that uses DACtx to store objects that encompass the state of a program.
Definition: DataflowEnvironment.cpp:155
clang::dataflow::Environment::join
LatticeJoinEffect join(const Environment &Other, Environment::ValueModel &Model)
Joins the environment with Other by taking the intersection of storage locations and values that are ...
Definition: DataflowEnvironment.cpp:235
Value.h
clang::dataflow::areEquivalentIndirectionValues
static bool areEquivalentIndirectionValues(Value *Val1, Value *Val2)
Definition: DataflowEnvironment.cpp:53
Type
MatchType Type
Definition: ASTMatchFinder.cpp:71