clang 23.0.0git
ProgramState.h
Go to the documentation of this file.
1//== ProgramState.h - Path-sensitive "State" for tracking values -*- 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 the state of the program along the analysis path.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_H
14#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_H
15
16#include "clang/Basic/LLVM.h"
23#include "llvm/ADT/FoldingSet.h"
24#include "llvm/ADT/ImmutableMap.h"
25#include "llvm/Support/Allocator.h"
26#include <optional>
27#include <utility>
28
29namespace llvm {
30class APSInt;
31}
32
33namespace clang {
34class ASTContext;
35
36namespace ento {
37
38class AnalysisManager;
39class CallEvent;
41
42typedef std::unique_ptr<ConstraintManager>(*ConstraintManagerCreator)(
44typedef std::unique_ptr<StoreManager>(*StoreManagerCreator)(
46
47//===----------------------------------------------------------------------===//
48// ProgramStateTrait - Traits used by the Generic Data Map of a ProgramState.
49//===----------------------------------------------------------------------===//
50
51template <typename T> struct ProgramStateTrait {
52 typedef typename T::data_type data_type;
53 static inline void *MakeVoidPtr(data_type D) { return (void*) D; }
54 static inline data_type MakeData(void *const* P) {
55 return P ? (data_type) *P : (data_type) 0;
56 }
57};
58
59/// \class ProgramState
60/// ProgramState - This class encapsulates:
61///
62/// 1. A mapping from expressions to values (Environment)
63/// 2. A mapping from locations to values (Store)
64/// 3. Constraints on symbolic values (GenericDataMap)
65///
66/// Together these represent the "abstract state" of a program.
67///
68/// ProgramState is intended to be used as a functional object; that is,
69/// once it is created and made "persistent" in a FoldingSet, its
70/// values will never change.
71class ProgramState : public llvm::FoldingSetNode {
72public:
73 typedef llvm::ImmutableMap<const void *, void *> GenericDataMap;
74
75private:
76 void operator=(const ProgramState& R) = delete;
77
78 friend class ProgramStateManager;
79 friend class ExplodedGraph;
80 friend class ExplodedNode;
81
82 ProgramStateManager *stateMgr;
83 Environment Env; // Maps a Stmt to its current SVal.
84 Store store; // Maps a location to its current value.
85 GenericDataMap GDM; // Custom data stored by a client of this class.
86
87 // A state is infeasible if there is a contradiction among the constraints.
88 // An infeasible state is represented by a `nullptr`.
89 // In the sense of `assumeDual`, a state can have two children by adding a
90 // new constraint and the negation of that new constraint. A parent state is
91 // over-constrained if both of its children are infeasible. In the
92 // mathematical sense, it means that the parent is infeasible and we should
93 // have realized that at the moment when we have created it. However, we
94 // could not recognize that because of the imperfection of the underlying
95 // constraint solver. We say it is posteriorly over-constrained because we
96 // recognize that a parent is infeasible only *after* a new and more specific
97 // constraint and its negation are evaluated.
98 //
99 // Example:
100 //
101 // x * x = 4 and x is in the range [0, 1]
102 // This is an already infeasible state, but the constraint solver is not
103 // capable of handling sqrt, thus we don't know it yet.
104 //
105 // Then a new constraint `x = 0` is added. At this moment the constraint
106 // solver re-evaluates the existing constraints and realizes the
107 // contradiction `0 * 0 = 4`.
108 // We also evaluate the negated constraint `x != 0`; the constraint solver
109 // deduces `x = 1` and then realizes the contradiction `1 * 1 = 4`.
110 // Both children are infeasible, thus the parent state is marked as
111 // posteriorly over-constrained. These parents are handled with special care:
112 // we do not allow transitions to exploded nodes with such states.
113 bool PosteriorlyOverconstrained = false;
114 // Make internal constraint solver entities friends so they can access the
115 // overconstrained-related functions. We want to keep this API inaccessible
116 // for Checkers.
117 friend class ConstraintManager;
118 // The CoreEngine also needs to be a friend to mark nodes as sinks if they
119 // are generated with a PosteriorlyOverconstrained state.
120 // FIXME: Perform this check in the relevant methods of `ExplodedGraph` and
121 // remove this `friend` declaration.
122 friend class CoreEngine;
123 bool isPosteriorlyOverconstrained() const {
124 return PosteriorlyOverconstrained;
125 }
126 ProgramStateRef cloneAsPosteriorlyOverconstrained() const;
127
128 unsigned refCount;
129
130 /// makeWithStore - Return a ProgramState with the same values as the current
131 /// state with the exception of using the specified Store.
132 ProgramStateRef makeWithStore(const StoreRef &store) const;
133 ProgramStateRef makeWithStore(const BindResult &BindRes) const;
134
135 void setStore(const StoreRef &storeRef);
136
137public:
138 /// This ctor is used when creating the first ProgramState object.
140 StoreRef st, GenericDataMap gdm);
141
142 /// Copy ctor - We must explicitly define this or else the "Next" ptr
143 /// in FoldingSetNode will also get copied.
144 ProgramState(const ProgramState &RHS);
145
147
148 int64_t getID() const;
149
150 /// Return the ProgramStateManager associated with this state.
152 return *stateMgr;
153 }
154
156
157 /// Return the ConstraintManager.
159
160 /// getEnvironment - Return the environment associated with this state.
161 /// The environment is the mapping from expressions to values.
162 const Environment& getEnvironment() const { return Env; }
163
164 /// Return the store associated with this state. The store
165 /// is a mapping from locations to values.
166 Store getStore() const { return store; }
167
168 /// getGDM - Return the generic data map associated with this state.
169 GenericDataMap getGDM() const { return GDM; }
170
171 void setGDM(GenericDataMap gdm) { GDM = gdm; }
172
173 /// Profile - Profile the contents of a ProgramState object for use in a
174 /// FoldingSet. Two ProgramState objects are considered equal if they
175 /// have the same Environment, Store, and GenericDataMap.
176 static void Profile(llvm::FoldingSetNodeID& ID, const ProgramState *V) {
177 V->Env.Profile(ID);
178 ID.AddPointer(V->store);
179 V->GDM.Profile(ID);
180 ID.AddBoolean(V->PosteriorlyOverconstrained);
181 }
182
183 /// Profile - Used to profile the contents of this object for inclusion
184 /// in a FoldingSet.
185 void Profile(llvm::FoldingSetNodeID& ID) const {
186 Profile(ID, this);
187 }
188
191
192 //==---------------------------------------------------------------------==//
193 // Constraints on values.
194 //==---------------------------------------------------------------------==//
195 //
196 // Each ProgramState records constraints on symbolic values. These constraints
197 // are managed using the ConstraintManager associated with a ProgramStateManager.
198 // As constraints gradually accrue on symbolic values, added constraints
199 // may conflict and indicate that a state is infeasible (as no real values
200 // could satisfy all the constraints). This is the principal mechanism
201 // for modeling path-sensitivity in ExprEngine/ProgramState.
202 //
203 // Various "assume" methods form the interface for adding constraints to
204 // symbolic values. A call to 'assume' indicates an assumption being placed
205 // on one or symbolic values. 'assume' methods take the following inputs:
206 //
207 // (1) A ProgramState object representing the current state.
208 //
209 // (2) The assumed constraint (which is specific to a given "assume" method).
210 //
211 // (3) A binary value "Assumption" that indicates whether the constraint is
212 // assumed to be true or false.
213 //
214 // The output of "assume*" is a new ProgramState object with the added constraints.
215 // If no new state is feasible, NULL is returned.
216 //
217
218 /// Assumes that the value of \p cond is zero (if \p assumption is "false")
219 /// or non-zero (if \p assumption is "true").
220 ///
221 /// This returns a new state with the added constraint on \p cond.
222 /// If no new state is feasible, NULL is returned.
224 bool assumption) const;
225
226 /// Assumes both "true" and "false" for \p cond, and returns both
227 /// corresponding states (respectively).
228 ///
229 /// This is more efficient than calling assume() twice. Note that one (but not
230 /// both) of the returned states may be NULL.
231 [[nodiscard]] std::pair<ProgramStateRef, ProgramStateRef>
232 assume(DefinedOrUnknownSVal cond) const;
233
234 [[nodiscard]] std::pair<ProgramStateRef, ProgramStateRef>
236 QualType IndexType = QualType()) const;
237
238 [[nodiscard]] ProgramStateRef
240 bool assumption, QualType IndexType = QualType()) const;
241
242 /// Assumes that the value of \p Val is bounded with [\p From; \p To]
243 /// (if \p assumption is "true") or it is fully out of this range
244 /// (if \p assumption is "false").
245 ///
246 /// This returns a new state with the added constraint on \p cond.
247 /// If no new state is feasible, NULL is returned.
249 const llvm::APSInt &From,
250 const llvm::APSInt &To,
251 bool assumption) const;
252
253 /// Assumes given range both "true" and "false" for \p Val, and returns both
254 /// corresponding states (respectively).
255 ///
256 /// This is more efficient than calling assume() twice. Note that one (but not
257 /// both) of the returned states may be NULL.
258 [[nodiscard]] std::pair<ProgramStateRef, ProgramStateRef>
259 assumeInclusiveRange(DefinedOrUnknownSVal Val, const llvm::APSInt &From,
260 const llvm::APSInt &To) const;
261
262 /// Check if the given SVal is not constrained to zero and is not
263 /// a zero constant.
265
266 /// Check if the given SVal is constrained to zero or is a zero
267 /// constant.
269
270 /// \return Whether values \p Lhs and \p Rhs are equal.
271 ConditionTruthVal areEqual(SVal Lhs, SVal Rhs) const;
272
273 /// Utility method for getting regions.
274 LLVM_ATTRIBUTE_RETURNS_NONNULL
275 const VarRegion *getRegion(const VarDecl *D, const StackFrame *SF) const;
276
277 //==---------------------------------------------------------------------==//
278 // Binding and retrieving values to/from the environment and symbolic store.
279 //==---------------------------------------------------------------------==//
280
281 /// Create a new state by binding the value \p V to the expression \p E in
282 /// the state's environment.
283 [[nodiscard]] ProgramStateRef BindExpr(const Expr *E, const StackFrame *SF,
284 SVal V, bool Invalidate = true) const;
285
286 [[nodiscard]] ProgramStateRef bindLoc(Loc location, SVal V,
287 const StackFrame *SF,
288 bool notifyChanges = true) const;
289
290 [[nodiscard]] ProgramStateRef bindLoc(SVal location, SVal V,
291 const StackFrame *SF) const;
292
293 /// Initializes the region of memory represented by \p loc with an initial
294 /// value. Once initialized, all values loaded from any sub-regions of that
295 /// region will be equal to \p V, unless overwritten later by the program.
296 /// This method should not be used on regions that are already initialized.
297 /// If you need to indicate that memory contents have suddenly become unknown
298 /// within a certain region of memory, consider invalidateRegions().
300 const StackFrame *SF) const;
301
302 /// Performs C++ zero-initialization procedure on the region of memory
303 /// represented by \p loc.
305 const StackFrame *SF) const;
306
307 [[nodiscard]] ProgramStateRef killBinding(Loc LV) const;
308
309 /// Returns the state with bindings for the given regions cleared from the
310 /// store. If \p Call is non-null, also invalidates global regions (but if
311 /// \p Call is from a system header, then this is limited to globals declared
312 /// in system headers).
313 ///
314 /// This calls the lower-level method \c StoreManager::invalidateRegions to
315 /// do the actual invalidation, then calls the checker callbacks which should
316 /// be triggered by this event.
317 ///
318 /// \param Regions the set of regions to be invalidated.
319 /// \param Elem The CFG Element that caused the invalidation.
320 /// \param BlockCount The number of times the current basic block has been
321 /// visited.
322 /// \param CausesPointerEscape the flag is set to true when the invalidation
323 /// entails escape of a symbol (representing a pointer). For example,
324 /// due to it being passed as an argument in a call.
325 /// \param IS the set of invalidated symbols.
326 /// \param Call if non-null, the invalidated regions represent parameters to
327 /// the call and should be considered directly invalidated.
328 /// \param ITraits information about special handling for particular regions
329 /// or symbols.
332 unsigned BlockCount, const StackFrame *SF, bool CausesPointerEscape,
333 InvalidatedSymbols *IS = nullptr, const CallEvent *Call = nullptr,
334 RegionAndSymbolInvalidationTraits *ITraits = nullptr) const;
335
336 [[nodiscard]] ProgramStateRef
338 unsigned BlockCount, const StackFrame *SF,
339 bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
340 const CallEvent *Call = nullptr,
341 RegionAndSymbolInvalidationTraits *ITraits = nullptr) const;
342
343 /// enterStackFrame - Returns the state for entry to the given stack frame,
344 /// preserving the current state.
345 [[nodiscard]] ProgramStateRef
346 enterStackFrame(const CallEvent &Call, const StackFrame *CalleeSF) const;
347
348 /// Return the value of 'self' if available in the given context.
349 SVal getSelfSVal(const StackFrame *SF) const;
350
351 /// Get the lvalue for a base class object reference.
352 Loc getLValue(const CXXBaseSpecifier &BaseSpec, const SubRegion *Super) const;
353
354 /// Get the lvalue for a base class object reference.
355 Loc getLValue(const CXXRecordDecl *BaseClass, const SubRegion *Super,
356 bool IsVirtual) const;
357
358 /// Get the lvalue for a variable reference.
359 Loc getLValue(const VarDecl *D, const StackFrame *SF) const;
360
361 Loc getLValue(const CompoundLiteralExpr *literal, const StackFrame *SF) const;
362
363 /// Get the lvalue for an ivar reference.
364 SVal getLValue(const ObjCIvarDecl *decl, SVal base) const;
365
366 /// Get the lvalue for a field reference.
367 SVal getLValue(const FieldDecl *decl, SVal Base) const;
368
369 /// Get the lvalue for an indirect field reference.
371
372 /// Get the lvalue for an array index.
373 SVal getLValue(QualType ElementType, SVal Idx, SVal Base) const;
374
375 /// Returns the SVal bound to the expression \p E in the state's environment.
376 SVal getSVal(const Expr *E, const StackFrame *SF) const;
377
378 SVal getSValAsScalarOrLoc(const Expr *E, const StackFrame *SF) const;
379
380 /// Return the value bound to the specified location.
381 /// Returns UnknownVal() if none found.
382 SVal getSVal(Loc LV, QualType T = QualType()) const;
383
384 /// Returns the "raw" SVal bound to LV before any value simplification.
385 SVal getRawSVal(Loc LV, QualType T= QualType()) const;
386
387 /// Return the value bound to the specified location.
388 /// Returns UnknownVal() if none found.
389 SVal getSVal(const MemRegion* R, QualType T = QualType()) const;
390
391 /// Return the value bound to the specified location, assuming
392 /// that the value is a scalar integer or an enumeration or a pointer.
393 /// Returns UnknownVal() if none found or the region is not known to hold
394 /// a value of such type.
395 SVal getSValAsScalarOrLoc(const MemRegion *R) const;
396
397 using region_iterator = const MemRegion **;
398
399 /// Visits the symbols reachable from the given SVal using the provided
400 /// SymbolVisitor.
401 ///
402 /// This is a convenience API. Consider using ScanReachableSymbols class
403 /// directly when making multiple scans on the same state with the same
404 /// visitor to avoid repeated initialization cost.
405 /// \sa ScanReachableSymbols
406 bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const;
407
408 /// Visits the symbols reachable from the regions in the given
409 /// MemRegions range using the provided SymbolVisitor.
410 bool scanReachableSymbols(llvm::iterator_range<region_iterator> Reachable,
411 SymbolVisitor &visitor) const;
412
413 template <typename CB> CB scanReachableSymbols(SVal val) const;
414 template <typename CB> CB
415 scanReachableSymbols(llvm::iterator_range<region_iterator> Reachable) const;
416
417 //==---------------------------------------------------------------------==//
418 // Accessing the Generic Data Map (GDM).
419 //==---------------------------------------------------------------------==//
420
421 void *const *FindGDM(const void *K) const;
422
423 template <typename T>
424 [[nodiscard]] ProgramStateRef
425 add(typename ProgramStateTrait<T>::key_type K) const;
426
427 template <typename T>
432
433 template<typename T>
439
440 template <typename T>
442
443 template <typename T>
444 [[nodiscard]] ProgramStateRef
445 remove(typename ProgramStateTrait<T>::key_type K) const;
446
447 template <typename T>
448 [[nodiscard]] ProgramStateRef
451
452 template <typename T> [[nodiscard]] ProgramStateRef remove() const;
453
454 template <typename T>
455 [[nodiscard]] ProgramStateRef
456 set(typename ProgramStateTrait<T>::data_type D) const;
457
458 template <typename T>
459 [[nodiscard]] ProgramStateRef
461 typename ProgramStateTrait<T>::value_type E) const;
462
463 template <typename T>
464 [[nodiscard]] ProgramStateRef
468
469 template<typename T>
474
475 // Pretty-printing.
476 void printJson(raw_ostream &Out, const StackFrame *SF = nullptr,
477 const char *NL = "\n", unsigned int Space = 0,
478 bool IsDot = false) const;
479
480 void printDOT(raw_ostream &Out, const StackFrame *SF = nullptr,
481 unsigned int Space = 0) const;
482
483 void dump() const;
484
485private:
486 friend void ProgramStateRetain(const ProgramState *state);
487 friend void ProgramStateRelease(const ProgramState *state);
488
489 SVal desugarReference(SVal Val) const;
490 SVal wrapSymbolicRegion(SVal Base) const;
491};
492
493//===----------------------------------------------------------------------===//
494// ProgramStateManager - Factory object for ProgramStates.
495//===----------------------------------------------------------------------===//
496
498 friend class ProgramState;
499 friend void ProgramStateRelease(const ProgramState *state);
500private:
501 /// Eng - The ExprEngine that owns this state manager.
502 ExprEngine *Eng; /* Can be null. */
503
504 EnvironmentManager EnvMgr;
505 std::unique_ptr<StoreManager> StoreMgr;
506 std::unique_ptr<ConstraintManager> ConstraintMgr;
507
508 ProgramState::GenericDataMap::Factory GDMFactory;
509
510 typedef llvm::DenseMap<const void *, std::pair<void *, void (*)(void *)>>
511 GDMContextsTy;
512 GDMContextsTy GDMContexts;
513
514 /// StateSet - FoldingSet containing all the states created for analyzing
515 /// a particular function. This is used to unique states.
516 llvm::FoldingSet<ProgramState> StateSet;
517
518 /// Object that manages the data for all created SVals.
519 std::unique_ptr<SValBuilder> svalBuilder;
520
521 /// Manages memory for created CallEvents.
522 std::unique_ptr<CallEventManager> CallEventMgr;
523
524 /// A BumpPtrAllocator to allocate states.
525 llvm::BumpPtrAllocator &Alloc;
526
527 /// A vector of ProgramStates that we can reuse.
528 std::vector<ProgramState *> freeStates;
529
530public:
532 StoreManagerCreator CreateStoreManager,
533 ConstraintManagerCreator CreateConstraintManager,
534 llvm::BumpPtrAllocator& alloc,
535 ExprEngine *expreng);
536
538
540
541 ASTContext &getContext() { return svalBuilder->getContext(); }
542 const ASTContext &getContext() const { return svalBuilder->getContext(); }
543
545 return svalBuilder->getBasicValueFactory();
546 }
547
549 return *svalBuilder;
550 }
551
553 return *svalBuilder;
554 }
555
557 return svalBuilder->getSymbolManager();
558 }
560 return svalBuilder->getSymbolManager();
561 }
562
563 llvm::BumpPtrAllocator& getAllocator() { return Alloc; }
564
566 return svalBuilder->getRegionManager();
567 }
569 return svalBuilder->getRegionManager();
570 }
571
572 CallEventManager &getCallEventManager() { return *CallEventMgr; }
573
574 StoreManager &getStoreManager() { return *StoreMgr; }
575 const StoreManager &getStoreManager() const { return *StoreMgr; }
576 ConstraintManager &getConstraintManager() { return *ConstraintMgr; }
578 return *ConstraintMgr;
579 }
580 ExprEngine &getOwningEngine() { return *Eng; }
581
583 ProgramStateRef St, const StackFrame *SF, SymbolReaper &SymReaper);
584
585public:
586
588 return StoreMgr->ArrayToPointer(Array, ElementTy);
589 }
590
591 // Methods that manipulate the GDM.
592 ProgramStateRef addGDM(ProgramStateRef St, const void *Key, void *Data);
593 ProgramStateRef removeGDM(ProgramStateRef state, const void *Key);
594
595 // Methods that query & manipulate the Store.
596
598 StoreMgr->iterBindings(state->getStore(), F);
599 }
600
603 ProgramStateRef GDMState);
604
606 return ConstraintMgr->haveEqualConstraints(S1, S2);
607 }
608
610 return S1->Env == S2->Env;
611 }
612
614 return S1->store == S2->store;
615 }
616
617 //==---------------------------------------------------------------------==//
618 // Generic Data Map methods.
619 //==---------------------------------------------------------------------==//
620 //
621 // ProgramStateManager and ProgramState support a "generic data map" that allows
622 // different clients of ProgramState objects to embed arbitrary data within a
623 // ProgramState object. The generic data map is essentially an immutable map
624 // from a "tag" (that acts as the "key" for a client) and opaque values.
625 // Tags/keys and values are simply void* values. The typical way that clients
626 // generate unique tags are by taking the address of a static variable.
627 // Clients are responsible for ensuring that data values referred to by a
628 // the data pointer are immutable (and thus are essentially purely functional
629 // data).
630 //
631 // The templated methods below use the ProgramStateTrait<T> class
632 // to resolve keys into the GDM and to return data values to clients.
633 //
634
635 // Trait based GDM dispatch.
636 template <typename T>
641
642 template<typename T>
651
652 template <typename T>
659
660 template <typename T>
668
669 template <typename T>
673
674 void *FindGDMContext(const void *index,
675 void *(*CreateContext)(llvm::BumpPtrAllocator &),
676 void (*DeleteContext)(void *));
677
678 template <typename T>
686};
687
688
689//===----------------------------------------------------------------------===//
690// Out-of-line method definitions for ProgramState.
691//===----------------------------------------------------------------------===//
692
694 return stateMgr->getConstraintManager();
695}
696
698 const StackFrame *SF) const {
700}
701
703 bool Assumption) const {
704 if (Cond.isUnknown())
705 return this;
706
707 return getStateManager().ConstraintMgr
708 ->assume(this, Cond.castAs<DefinedSVal>(), Assumption);
709}
710
711inline std::pair<ProgramStateRef , ProgramStateRef >
713 if (Cond.isUnknown())
714 return std::make_pair(this, this);
715
716 return getStateManager().ConstraintMgr
717 ->assumeDual(this, Cond.castAs<DefinedSVal>());
718}
719
721 DefinedOrUnknownSVal Val, const llvm::APSInt &From, const llvm::APSInt &To,
722 bool Assumption) const {
723 if (Val.isUnknown())
724 return this;
725
726 assert(isa<NonLoc>(Val) && "Only NonLocs are supported!");
727
728 return getStateManager().ConstraintMgr->assumeInclusiveRange(
729 this, Val.castAs<NonLoc>(), From, To, Assumption);
730}
731
732inline std::pair<ProgramStateRef, ProgramStateRef>
734 const llvm::APSInt &From,
735 const llvm::APSInt &To) const {
736 if (Val.isUnknown())
737 return std::make_pair(this, this);
738
739 assert(isa<NonLoc>(Val) && "Only NonLocs are supported!");
740
741 return getStateManager().ConstraintMgr->assumeInclusiveRangeDual(
742 this, Val.castAs<NonLoc>(), From, To);
743}
744
746 const StackFrame *SF) const {
747 if (std::optional<Loc> L = LV.getAs<Loc>())
748 return bindLoc(*L, V, SF);
749 return this;
750}
751
753 const SubRegion *Super) const {
754 const auto *Base = BaseSpec.getType()->getAsCXXRecordDecl();
755 return loc::MemRegionVal(
756 getStateManager().getRegionManager().getCXXBaseObjectRegion(
757 Base, Super, BaseSpec.isVirtual()));
758}
759
761 const SubRegion *Super,
762 bool IsVirtual) const {
763 return loc::MemRegionVal(
764 getStateManager().getRegionManager().getCXXBaseObjectRegion(
765 BaseClass, Super, IsVirtual));
766}
767
769 const StackFrame *SF) const {
770 return getStateManager().StoreMgr->getLValueVar(VD, SF);
771}
772
774 const StackFrame *SF) const {
775 return getStateManager().StoreMgr->getLValueCompoundLiteral(literal, SF);
776}
777
779 return getStateManager().StoreMgr->getLValueIvar(D, Base);
780}
781
782inline SVal ProgramState::getLValue(QualType ElementType, SVal Idx, SVal Base) const{
783 if (std::optional<NonLoc> N = Idx.getAs<NonLoc>())
784 return getStateManager().StoreMgr->getLValueElement(ElementType, *N, Base);
785 return UnknownVal();
786}
787
788inline SVal ProgramState::getSVal(const Expr *E, const StackFrame *SF) const {
789 return Env.getSVal(EnvironmentEntry(E, SF), *getStateManager().svalBuilder);
790}
791
793 const StackFrame *SF) const {
794 QualType T = E->getType();
795 if (E->isGLValue() || Loc::isLocType(T) || T->isIntegralOrEnumerationType())
796 return getSVal(E, SF);
797 return UnknownVal();
798}
799
801 return getStateManager().StoreMgr->getBinding(getStore(), LV, T);
802}
803
804inline SVal ProgramState::getSVal(const MemRegion* R, QualType T) const {
805 return getStateManager().StoreMgr->getBinding(getStore(),
807 T);
808}
809
813
817
818template<typename T>
822
823template <typename T>
827
828template<typename T>
832
833template<typename T>
838
839template <typename T>
841 return getStateManager().remove<T>(this);
842}
843
844template<typename T>
848
849template<typename T>
854
855template<typename T>
861
862template <typename CB>
864 CB cb(this);
865 scanReachableSymbols(val, cb);
866 return cb;
867}
868
869template <typename CB>
871 llvm::iterator_range<region_iterator> Reachable) const {
872 CB cb(this);
873 scanReachableSymbols(Reachable, cb);
874 return cb;
875}
876
877/// \class ScanReachableSymbols
878/// A utility class that visits the reachable symbols using a custom
879/// SymbolVisitor. Terminates recursive traversal when the visitor function
880/// returns false.
882 typedef llvm::DenseSet<const void*> VisitedItems;
883
884 VisitedItems visited;
885 ProgramStateRef state;
886 SymbolVisitor &visitor;
887public:
889 : state(std::move(st)), visitor(v) {}
890
892 bool scan(nonloc::CompoundVal val);
893 bool scan(SVal val);
894 bool scan(const MemRegion *R);
895 bool scan(const SymExpr *sym);
896};
897
898} // end ento namespace
899
900} // end clang namespace
901
902#endif
#define V(N, I)
llvm::APSInt APSInt
Definition Compiler.cpp:24
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::json::Array Array
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
Represents a base class of a C++ class.
Definition DeclCXX.h:146
bool isVirtual() const
Determines whether the base class is a virtual base class (or not).
Definition DeclCXX.h:203
QualType getType() const
Retrieves the type of the base class.
Definition DeclCXX.h:249
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
CompoundLiteralExpr - [C99 6.5.2.5].
Definition Expr.h:3608
This represents one expression.
Definition Expr.h:112
bool isGLValue() const
Definition Expr.h:287
QualType getType() const
Definition Expr.h:144
Represents a member of a struct/union/class.
Definition Decl.h:3166
Represents a field injected from an anonymous union/struct into the parent scope.
Definition Decl.h:3473
ObjCIvarDecl - Represents an ObjC instance variable.
Definition DeclObjC.h:1952
A (possibly-)qualified type.
Definition TypeBase.h:937
It represents a stack frame of the call stack.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
Represents a variable declaration or definition.
Definition Decl.h:924
Manages the lifetime of CallEvent objects.
Definition CallEvent.h:1363
Represents an abstract call to a function or method along a particular path.
Definition CallEvent.h:152
An entry in the environment consists of a Stmt and an StackFrame.
Definition Environment.h:35
An immutable map from EnvironmentEntries to SVals.
Definition Environment.h:55
static bool isLocType(QualType T)
Definition SVals.h:262
const VarRegion * getVarRegion(const VarDecl *VD, const StackFrame *SF)
getVarRegion - Retrieve or create the memory region associated with a specified VarDecl and StackFram...
MemRegion - The root abstract class for all memory regions.
Definition MemRegion.h:97
ProgramStateRef remove(ProgramStateRef st)
const MemRegionManager & getRegionManager() const
bool haveEqualStores(ProgramStateRef S1, ProgramStateRef S2) const
const ASTContext & getContext() const
ProgramStateRef getInitialState(const StackFrame *InitSF)
const StoreManager & getStoreManager() const
void * FindGDMContext(const void *index, void *(*CreateContext)(llvm::BumpPtrAllocator &), void(*DeleteContext)(void *))
CallEventManager & getCallEventManager()
bool haveEqualEnvironments(ProgramStateRef S1, ProgramStateRef S2) const
const SymbolManager & getSymbolManager() const
const SValBuilder & getSValBuilder() const
friend void ProgramStateRelease(const ProgramState *state)
Decrement the number of times this state is referenced.
ProgramStateRef set(ProgramStateRef st, typename ProgramStateTrait< T >::data_type D)
ProgramStateRef removeDeadBindingsFromEnvironmentAndStore(ProgramStateRef St, const StackFrame *SF, SymbolReaper &SymReaper)
ProgramStateRef getPersistentStateWithGDM(ProgramStateRef FromState, ProgramStateRef GDMState)
ProgramStateRef removeGDM(ProgramStateRef state, const void *Key)
MemRegionManager & getRegionManager()
bool haveEqualConstraints(ProgramStateRef S1, ProgramStateRef S2) const
ProgramStateRef remove(ProgramStateRef st, typename ProgramStateTrait< T >::key_type K, typename ProgramStateTrait< T >::context_type C)
ProgramStateRef addGDM(ProgramStateRef St, const void *Key, void *Data)
ProgramStateRef set(ProgramStateRef st, typename ProgramStateTrait< T >::key_type K, typename ProgramStateTrait< T >::value_type V, typename ProgramStateTrait< T >::context_type C)
ProgramStateRef add(ProgramStateRef st, typename ProgramStateTrait< T >::key_type K, typename ProgramStateTrait< T >::context_type C)
ProgramStateRef getPersistentState(ProgramState &Impl)
void iterBindings(ProgramStateRef state, StoreManager::BindingsHandler &F)
SVal ArrayToPointer(Loc Array, QualType ElementTy)
const ConstraintManager & getConstraintManager() const
llvm::BumpPtrAllocator & getAllocator()
BasicValueFactory & getBasicVals()
ProgramStateTrait< T >::context_type get_context()
ProgramStateManager(ASTContext &Ctx, StoreManagerCreator CreateStoreManager, ConstraintManagerCreator CreateConstraintManager, llvm::BumpPtrAllocator &alloc, ExprEngine *expreng)
ConstraintManager & getConstraintManager()
ProgramState - This class encapsulates:
bool scanReachableSymbols(SVal val, SymbolVisitor &visitor) const
Visits the symbols reachable from the given SVal using the provided SymbolVisitor.
ProgramStateTrait< T >::data_type get() const
Loc getLValue(const CXXBaseSpecifier &BaseSpec, const SubRegion *Super) const
Get the lvalue for a base class object reference.
friend void ProgramStateRetain(const ProgramState *state)
Increments the number of times this state is referenced.
friend class ProgramStateManager
llvm::ImmutableMap< const void *, void * > GenericDataMap
ProgramStateRef assumeInclusiveRange(DefinedOrUnknownSVal Val, const llvm::APSInt &From, const llvm::APSInt &To, bool assumption) const
Assumes that the value of Val is bounded with [From; To] (if assumption is "true") or it is fully out...
bool contains(typename ProgramStateTrait< T >::key_type key) const
ProgramStateRef bindDefaultInitial(SVal loc, SVal V, const StackFrame *SF) const
Initializes the region of memory represented by loc with an initial value.
ConstraintManager & getConstraintManager() const
Return the ConstraintManager.
LLVM_ATTRIBUTE_RETURNS_NONNULL const VarRegion * getRegion(const VarDecl *D, const StackFrame *SF) const
Utility method for getting regions.
ProgramStateRef invalidateRegions(ArrayRef< SVal > Values, ConstCFGElementRef Elem, unsigned BlockCount, const StackFrame *SF, bool CausesPointerEscape, InvalidatedSymbols *IS=nullptr, const CallEvent *Call=nullptr, RegionAndSymbolInvalidationTraits *ITraits=nullptr) const
ProgramStateRef add(typename ProgramStateTrait< T >::key_type K) const
void Profile(llvm::FoldingSetNodeID &ID) const
Profile - Used to profile the contents of this object for inclusion in a FoldingSet.
SVal getRawSVal(Loc LV, QualType T=QualType()) const
Returns the "raw" SVal bound to LV before any value simplification.
ConditionTruthVal isNull(SVal V) const
Check if the given SVal is constrained to zero or is a zero constant.
ProgramStateRef bindLoc(Loc location, SVal V, const StackFrame *SF, bool notifyChanges=true) const
ProgramStateManager & getStateManager() const
Return the ProgramStateManager associated with this state.
ProgramStateRef killBinding(Loc LV) const
ProgramState(ProgramStateManager *mgr, const Environment &env, StoreRef st, GenericDataMap gdm)
This ctor is used when creating the first ProgramState object.
GenericDataMap getGDM() const
getGDM - Return the generic data map associated with this state.
const Environment & getEnvironment() const
getEnvironment - Return the environment associated with this state.
ProgramStateRef BindExpr(const Expr *E, const StackFrame *SF, SVal V, bool Invalidate=true) const
Create a new state by binding the value V to the expression E in the state's environment.
friend void ProgramStateRelease(const ProgramState *state)
Decrement the number of times this state is referenced.
ProgramStateRef bindDefaultZero(SVal loc, const StackFrame *SF) const
Performs C++ zero-initialization procedure on the region of memory represented by loc.
SVal getSVal(const Expr *E, const StackFrame *SF) const
Returns the SVal bound to the expression E in the state's environment.
ProgramStateRef assume(DefinedOrUnknownSVal cond, bool assumption) const
Assumes that the value of cond is zero (if assumption is "false") or non-zero (if assumption is "true...
Store getStore() const
Return the store associated with this state.
ConditionTruthVal areEqual(SVal Lhs, SVal Rhs) const
ConditionTruthVal isNonNull(SVal V) const
Check if the given SVal is not constrained to zero and is not a zero constant.
ProgramStateRef set(typename ProgramStateTrait< T >::data_type D) const
ProgramStateRef assumeInBound(DefinedOrUnknownSVal idx, DefinedOrUnknownSVal upperBound, bool assumption, QualType IndexType=QualType()) const
ProgramStateTrait< T >::lookup_type get(typename ProgramStateTrait< T >::key_type key) const
SVal getSValAsScalarOrLoc(const Expr *E, const StackFrame *SF) const
ProgramStateRef invalidateRegions(ArrayRef< const MemRegion * > Regions, ConstCFGElementRef Elem, unsigned BlockCount, const StackFrame *SF, bool CausesPointerEscape, InvalidatedSymbols *IS=nullptr, const CallEvent *Call=nullptr, RegionAndSymbolInvalidationTraits *ITraits=nullptr) const
Returns the state with bindings for the given regions cleared from the store.
const MemRegion ** region_iterator
ProgramStateTrait< T >::context_type get_context() const
void printDOT(raw_ostream &Out, const StackFrame *SF=nullptr, unsigned int Space=0) const
SVal getSelfSVal(const StackFrame *SF) const
Return the value of 'self' if available in the given context.
void printJson(raw_ostream &Out, const StackFrame *SF=nullptr, const char *NL="\n", unsigned int Space=0, bool IsDot=false) const
static void Profile(llvm::FoldingSetNodeID &ID, const ProgramState *V)
Profile - Profile the contents of a ProgramState object for use in a FoldingSet.
BasicValueFactory & getBasicVals() const
std::pair< ProgramStateRef, ProgramStateRef > assumeInBoundDual(DefinedOrUnknownSVal idx, DefinedOrUnknownSVal upperBound, QualType IndexType=QualType()) const
void *const * FindGDM(const void *K) const
ProgramStateRef remove() const
void setGDM(GenericDataMap gdm)
AnalysisManager & getAnalysisManager() const
ProgramStateRef enterStackFrame(const CallEvent &Call, const StackFrame *CalleeSF) const
enterStackFrame - Returns the state for entry to the given stack frame, preserving the current state.
SymbolManager & getSymbolManager() const
Information about invalidation for a particular region/symbol.
Definition MemRegion.h:1656
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition SVals.h:56
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
Definition SVals.h:87
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Definition SVals.h:83
bool isUnknown() const
Definition SVals.h:105
ScanReachableSymbols(ProgramStateRef st, SymbolVisitor &v)
bool scan(nonloc::LazyCompoundVal val)
SubRegion - A region that subsets another larger region.
Definition MemRegion.h:473
Symbolic value.
Definition SymExpr.h:32
A class responsible for cleaning up unused symbols.
The simplest example of a concrete compound value is nonloc::CompoundVal, which represents a concrete...
Definition SVals.h:339
While nonloc::CompoundVal covers a few simple use cases, nonloc::LazyCompoundVal is a more performant...
Definition SVals.h:389
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
llvm::DenseSet< SymbolRef > InvalidatedSymbols
Definition Store.h:50
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
std::unique_ptr< ConstraintManager >(* ConstraintManagerCreator)(ProgramStateManager &, ExprEngine *)
std::unique_ptr< StoreManager >(* StoreManagerCreator)(ProgramStateManager &)
const void * Store
Store - This opaque type encapsulates an immutable mapping from locations to values.
Definition StoreRef.h:27
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
CFGBlock::ConstCFGElementRef ConstCFGElementRef
Definition CFG.h:1248
Expr * Cond
};
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
static void * MakeVoidPtr(data_type D)
static data_type MakeData(void *const *P)