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 analysisa 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" 17 #include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h" 18 #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h" 19 #include "clang/StaticAnalyzer/Core/PathSensitive/Environment.h" 20 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" 21 #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" 22 #include "clang/StaticAnalyzer/Core/PathSensitive/Store.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 29 namespace llvm { 30 class APSInt; 31 } 32 33 namespace clang { 34 class ASTContext; 35 36 namespace ento { 37 38 class AnalysisManager; 39 class CallEvent; 40 class CallEventManager; 41 42 typedef std::unique_ptr<ConstraintManager>(*ConstraintManagerCreator)( 43 ProgramStateManager &, ExprEngine *); 44 typedef std::unique_ptr<StoreManager>(*StoreManagerCreator)( 45 ProgramStateManager &); 46 47 //===----------------------------------------------------------------------===// 48 // ProgramStateTrait - Traits used by the Generic Data Map of a ProgramState. 49 //===----------------------------------------------------------------------===// 50 51 template <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. 71 class ProgramState : public llvm::FoldingSetNode { 72 public: 73 typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy; 74 typedef llvm::ImmutableMap<void*, void*> GenericDataMap; 75 76 private: 77 void operator=(const ProgramState& R) = delete; 78 79 friend class ProgramStateManager; 80 friend class ExplodedGraph; 81 friend class ExplodedNode; 82 friend class NodeBuilder; 83 84 ProgramStateManager *stateMgr; 85 Environment Env; // Maps a Stmt to its current SVal. 86 Store store; // Maps a location to its current value. 87 GenericDataMap GDM; // Custom data stored by a client of this class. 88 89 // A state is infeasible if there is a contradiction among the constraints. 90 // An infeasible state is represented by a `nullptr`. 91 // In the sense of `assumeDual`, a state can have two children by adding a 92 // new constraint and the negation of that new constraint. A parent state is 93 // over-constrained if both of its children are infeasible. In the 94 // mathematical sense, it means that the parent is infeasible and we should 95 // have realized that at the moment when we have created it. However, we 96 // could not recognize that because of the imperfection of the underlying 97 // constraint solver. We say it is posteriorly over-constrained because we 98 // recognize that a parent is infeasible only *after* a new and more specific 99 // constraint and its negation are evaluated. 100 // 101 // Example: 102 // 103 // x * x = 4 and x is in the range [0, 1] 104 // This is an already infeasible state, but the constraint solver is not 105 // capable of handling sqrt, thus we don't know it yet. 106 // 107 // Then a new constraint `x = 0` is added. At this moment the constraint 108 // solver re-evaluates the existing constraints and realizes the 109 // contradiction `0 * 0 = 4`. 110 // We also evaluate the negated constraint `x != 0`; the constraint solver 111 // deduces `x = 1` and then realizes the contradiction `1 * 1 = 4`. 112 // Both children are infeasible, thus the parent state is marked as 113 // posteriorly over-constrained. These parents are handled with special care: 114 // we do not allow transitions to exploded nodes with such states. 115 bool PosteriorlyOverconstrained = false; 116 // Make internal constraint solver entities friends so they can access the 117 // overconstrained-related functions. We want to keep this API inaccessible 118 // for Checkers. 119 friend class ConstraintManager; 120 bool isPosteriorlyOverconstrained() const { 121 return PosteriorlyOverconstrained; 122 } 123 ProgramStateRef cloneAsPosteriorlyOverconstrained() const; 124 125 unsigned refCount; 126 127 /// makeWithStore - Return a ProgramState with the same values as the current 128 /// state with the exception of using the specified Store. 129 ProgramStateRef makeWithStore(const StoreRef &store) const; 130 131 void setStore(const StoreRef &storeRef); 132 133 public: 134 /// This ctor is used when creating the first ProgramState object. 135 ProgramState(ProgramStateManager *mgr, const Environment& env, 136 StoreRef st, GenericDataMap gdm); 137 138 /// Copy ctor - We must explicitly define this or else the "Next" ptr 139 /// in FoldingSetNode will also get copied. 140 ProgramState(const ProgramState &RHS); 141 142 ~ProgramState(); 143 144 int64_t getID() const; 145 146 /// Return the ProgramStateManager associated with this state. 147 ProgramStateManager &getStateManager() const { 148 return *stateMgr; 149 } 150 151 AnalysisManager &getAnalysisManager() const; 152 153 /// Return the ConstraintManager. 154 ConstraintManager &getConstraintManager() const; 155 156 /// getEnvironment - Return the environment associated with this state. 157 /// The environment is the mapping from expressions to values. 158 const Environment& getEnvironment() const { return Env; } 159 160 /// Return the store associated with this state. The store 161 /// is a mapping from locations to values. 162 Store getStore() const { return store; } 163 164 165 /// getGDM - Return the generic data map associated with this state. 166 GenericDataMap getGDM() const { return GDM; } 167 168 void setGDM(GenericDataMap gdm) { GDM = gdm; } 169 170 /// Profile - Profile the contents of a ProgramState object for use in a 171 /// FoldingSet. Two ProgramState objects are considered equal if they 172 /// have the same Environment, Store, and GenericDataMap. 173 static void Profile(llvm::FoldingSetNodeID& ID, const ProgramState *V) { 174 V->Env.Profile(ID); 175 ID.AddPointer(V->store); 176 V->GDM.Profile(ID); 177 ID.AddBoolean(V->PosteriorlyOverconstrained); 178 } 179 180 /// Profile - Used to profile the contents of this object for inclusion 181 /// in a FoldingSet. 182 void Profile(llvm::FoldingSetNodeID& ID) const { 183 Profile(ID, this); 184 } 185 186 BasicValueFactory &getBasicVals() const; 187 SymbolManager &getSymbolManager() const; 188 189 //==---------------------------------------------------------------------==// 190 // Constraints on values. 191 //==---------------------------------------------------------------------==// 192 // 193 // Each ProgramState records constraints on symbolic values. These constraints 194 // are managed using the ConstraintManager associated with a ProgramStateManager. 195 // As constraints gradually accrue on symbolic values, added constraints 196 // may conflict and indicate that a state is infeasible (as no real values 197 // could satisfy all the constraints). This is the principal mechanism 198 // for modeling path-sensitivity in ExprEngine/ProgramState. 199 // 200 // Various "assume" methods form the interface for adding constraints to 201 // symbolic values. A call to 'assume' indicates an assumption being placed 202 // on one or symbolic values. 'assume' methods take the following inputs: 203 // 204 // (1) A ProgramState object representing the current state. 205 // 206 // (2) The assumed constraint (which is specific to a given "assume" method). 207 // 208 // (3) A binary value "Assumption" that indicates whether the constraint is 209 // assumed to be true or false. 210 // 211 // The output of "assume*" is a new ProgramState object with the added constraints. 212 // If no new state is feasible, NULL is returned. 213 // 214 215 /// Assumes that the value of \p cond is zero (if \p assumption is "false") 216 /// or non-zero (if \p assumption is "true"). 217 /// 218 /// This returns a new state with the added constraint on \p cond. 219 /// If no new state is feasible, NULL is returned. 220 [[nodiscard]] ProgramStateRef assume(DefinedOrUnknownSVal cond, 221 bool assumption) const; 222 223 /// Assumes both "true" and "false" for \p cond, and returns both 224 /// corresponding states (respectively). 225 /// 226 /// This is more efficient than calling assume() twice. Note that one (but not 227 /// both) of the returned states may be NULL. 228 [[nodiscard]] std::pair<ProgramStateRef, ProgramStateRef> 229 assume(DefinedOrUnknownSVal cond) const; 230 231 [[nodiscard]] std::pair<ProgramStateRef, ProgramStateRef> 232 assumeInBoundDual(DefinedOrUnknownSVal idx, DefinedOrUnknownSVal upperBound, 233 QualType IndexType = QualType()) const; 234 235 [[nodiscard]] ProgramStateRef 236 assumeInBound(DefinedOrUnknownSVal idx, DefinedOrUnknownSVal upperBound, 237 bool assumption, QualType IndexType = QualType()) const; 238 239 /// Assumes that the value of \p Val is bounded with [\p From; \p To] 240 /// (if \p assumption is "true") or it is fully out of this range 241 /// (if \p assumption is "false"). 242 /// 243 /// This returns a new state with the added constraint on \p cond. 244 /// If no new state is feasible, NULL is returned. 245 [[nodiscard]] ProgramStateRef assumeInclusiveRange(DefinedOrUnknownSVal Val, 246 const llvm::APSInt &From, 247 const llvm::APSInt &To, 248 bool assumption) const; 249 250 /// Assumes given range both "true" and "false" for \p Val, and returns both 251 /// corresponding states (respectively). 252 /// 253 /// This is more efficient than calling assume() twice. Note that one (but not 254 /// both) of the returned states may be NULL. 255 [[nodiscard]] std::pair<ProgramStateRef, ProgramStateRef> 256 assumeInclusiveRange(DefinedOrUnknownSVal Val, const llvm::APSInt &From, 257 const llvm::APSInt &To) const; 258 259 /// Check if the given SVal is not constrained to zero and is not 260 /// a zero constant. 261 ConditionTruthVal isNonNull(SVal V) const; 262 263 /// Check if the given SVal is constrained to zero or is a zero 264 /// constant. 265 ConditionTruthVal isNull(SVal V) const; 266 267 /// \return Whether values \p Lhs and \p Rhs are equal. 268 ConditionTruthVal areEqual(SVal Lhs, SVal Rhs) const; 269 270 /// Utility method for getting regions. 271 LLVM_ATTRIBUTE_RETURNS_NONNULL 272 const VarRegion* getRegion(const VarDecl *D, const LocationContext *LC) const; 273 274 //==---------------------------------------------------------------------==// 275 // Binding and retrieving values to/from the environment and symbolic store. 276 //==---------------------------------------------------------------------==// 277 278 /// Create a new state by binding the value 'V' to the statement 'S' in the 279 /// state's environment. 280 [[nodiscard]] ProgramStateRef BindExpr(const Stmt *S, 281 const LocationContext *LCtx, SVal V, 282 bool Invalidate = true) const; 283 284 [[nodiscard]] ProgramStateRef bindLoc(Loc location, SVal V, 285 const LocationContext *LCtx, 286 bool notifyChanges = true) const; 287 288 [[nodiscard]] ProgramStateRef bindLoc(SVal location, SVal V, 289 const LocationContext *LCtx) const; 290 291 /// Initializes the region of memory represented by \p loc with an initial 292 /// value. Once initialized, all values loaded from any sub-regions of that 293 /// region will be equal to \p V, unless overwritten later by the program. 294 /// This method should not be used on regions that are already initialized. 295 /// If you need to indicate that memory contents have suddenly become unknown 296 /// within a certain region of memory, consider invalidateRegions(). 297 [[nodiscard]] ProgramStateRef 298 bindDefaultInitial(SVal loc, SVal V, const LocationContext *LCtx) const; 299 300 /// Performs C++ zero-initialization procedure on the region of memory 301 /// represented by \p loc. 302 [[nodiscard]] ProgramStateRef 303 bindDefaultZero(SVal loc, const LocationContext *LCtx) const; 304 305 [[nodiscard]] ProgramStateRef killBinding(Loc LV) const; 306 307 /// Returns the state with bindings for the given regions 308 /// cleared from the store. 309 /// 310 /// Optionally invalidates global regions as well. 311 /// 312 /// \param Regions the set of regions to be invalidated. 313 /// \param E the expression that caused the invalidation. 314 /// \param BlockCount The number of times the current basic block has been 315 // visited. 316 /// \param CausesPointerEscape the flag is set to true when 317 /// the invalidation entails escape of a symbol (representing a 318 /// pointer). For example, due to it being passed as an argument in a 319 /// call. 320 /// \param IS the set of invalidated symbols. 321 /// \param Call if non-null, the invalidated regions represent parameters to 322 /// the call and should be considered directly invalidated. 323 /// \param ITraits information about special handling for a particular 324 /// region/symbol. 325 [[nodiscard]] ProgramStateRef 326 invalidateRegions(ArrayRef<const MemRegion *> Regions, const Expr *E, 327 unsigned BlockCount, const LocationContext *LCtx, 328 bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr, 329 const CallEvent *Call = nullptr, 330 RegionAndSymbolInvalidationTraits *ITraits = nullptr) const; 331 332 [[nodiscard]] ProgramStateRef 333 invalidateRegions(ArrayRef<SVal> Regions, const Expr *E, unsigned BlockCount, 334 const LocationContext *LCtx, bool CausesPointerEscape, 335 InvalidatedSymbols *IS = nullptr, 336 const CallEvent *Call = nullptr, 337 RegionAndSymbolInvalidationTraits *ITraits = nullptr) const; 338 339 /// enterStackFrame - Returns the state for entry to the given stack frame, 340 /// preserving the current state. 341 [[nodiscard]] ProgramStateRef 342 enterStackFrame(const CallEvent &Call, 343 const StackFrameContext *CalleeCtx) const; 344 345 /// Return the value of 'self' if available in the given context. 346 SVal getSelfSVal(const LocationContext *LC) const; 347 348 /// Get the lvalue for a base class object reference. 349 Loc getLValue(const CXXBaseSpecifier &BaseSpec, const SubRegion *Super) const; 350 351 /// Get the lvalue for a base class object reference. 352 Loc getLValue(const CXXRecordDecl *BaseClass, const SubRegion *Super, 353 bool IsVirtual) const; 354 355 /// Get the lvalue for a variable reference. 356 Loc getLValue(const VarDecl *D, const LocationContext *LC) const; 357 358 Loc getLValue(const CompoundLiteralExpr *literal, 359 const LocationContext *LC) const; 360 361 /// Get the lvalue for an ivar reference. 362 SVal getLValue(const ObjCIvarDecl *decl, SVal base) const; 363 364 /// Get the lvalue for a field reference. 365 SVal getLValue(const FieldDecl *decl, SVal Base) const; 366 367 /// Get the lvalue for an indirect field reference. 368 SVal getLValue(const IndirectFieldDecl *decl, SVal Base) const; 369 370 /// Get the lvalue for an array index. 371 SVal getLValue(QualType ElementType, SVal Idx, SVal Base) const; 372 373 /// Returns the SVal bound to the statement 'S' in the state's environment. 374 SVal getSVal(const Stmt *S, const LocationContext *LCtx) const; 375 376 SVal getSValAsScalarOrLoc(const Stmt *Ex, const LocationContext *LCtx) const; 377 378 /// Return the value bound to the specified location. 379 /// Returns UnknownVal() if none found. 380 SVal getSVal(Loc LV, QualType T = QualType()) const; 381 382 /// Returns the "raw" SVal bound to LV before any value simplfication. 383 SVal getRawSVal(Loc LV, QualType T= QualType()) const; 384 385 /// Return the value bound to the specified location. 386 /// Returns UnknownVal() if none found. 387 SVal getSVal(const MemRegion* R, QualType T = QualType()) const; 388 389 /// Return the value bound to the specified location, assuming 390 /// that the value is a scalar integer or an enumeration or a pointer. 391 /// Returns UnknownVal() if none found or the region is not known to hold 392 /// a value of such type. 393 SVal getSValAsScalarOrLoc(const MemRegion *R) const; 394 395 using region_iterator = const MemRegion **; 396 397 /// Visits the symbols reachable from the given SVal using the provided 398 /// SymbolVisitor. 399 /// 400 /// This is a convenience API. Consider using ScanReachableSymbols class 401 /// directly when making multiple scans on the same state with the same 402 /// visitor to avoid repeated initialization cost. 403 /// \sa ScanReachableSymbols 404 bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const; 405 406 /// Visits the symbols reachable from the regions in the given 407 /// MemRegions range using the provided SymbolVisitor. 408 bool scanReachableSymbols(llvm::iterator_range<region_iterator> Reachable, 409 SymbolVisitor &visitor) const; 410 411 template <typename CB> CB scanReachableSymbols(SVal val) const; 412 template <typename CB> CB 413 scanReachableSymbols(llvm::iterator_range<region_iterator> Reachable) const; 414 415 //==---------------------------------------------------------------------==// 416 // Accessing the Generic Data Map (GDM). 417 //==---------------------------------------------------------------------==// 418 419 void *const* FindGDM(void *K) const; 420 421 template <typename T> 422 [[nodiscard]] ProgramStateRef 423 add(typename ProgramStateTrait<T>::key_type K) const; 424 425 template <typename T> 426 typename ProgramStateTrait<T>::data_type 427 get() const { 428 return ProgramStateTrait<T>::MakeData(FindGDM(ProgramStateTrait<T>::GDMIndex())); 429 } 430 431 template<typename T> 432 typename ProgramStateTrait<T>::lookup_type 433 get(typename ProgramStateTrait<T>::key_type key) const { 434 void *const* d = FindGDM(ProgramStateTrait<T>::GDMIndex()); 435 return ProgramStateTrait<T>::Lookup(ProgramStateTrait<T>::MakeData(d), key); 436 } 437 438 template <typename T> 439 typename ProgramStateTrait<T>::context_type get_context() const; 440 441 template <typename T> 442 [[nodiscard]] ProgramStateRef 443 remove(typename ProgramStateTrait<T>::key_type K) const; 444 445 template <typename T> 446 [[nodiscard]] ProgramStateRef 447 remove(typename ProgramStateTrait<T>::key_type K, 448 typename ProgramStateTrait<T>::context_type C) const; 449 450 template <typename T> [[nodiscard]] ProgramStateRef remove() const; 451 452 template <typename T> 453 [[nodiscard]] ProgramStateRef 454 set(typename ProgramStateTrait<T>::data_type D) const; 455 456 template <typename T> 457 [[nodiscard]] ProgramStateRef 458 set(typename ProgramStateTrait<T>::key_type K, 459 typename ProgramStateTrait<T>::value_type E) const; 460 461 template <typename T> 462 [[nodiscard]] ProgramStateRef 463 set(typename ProgramStateTrait<T>::key_type K, 464 typename ProgramStateTrait<T>::value_type E, 465 typename ProgramStateTrait<T>::context_type C) const; 466 467 template<typename T> 468 bool contains(typename ProgramStateTrait<T>::key_type key) const { 469 void *const* d = FindGDM(ProgramStateTrait<T>::GDMIndex()); 470 return ProgramStateTrait<T>::Contains(ProgramStateTrait<T>::MakeData(d), key); 471 } 472 473 // Pretty-printing. 474 void printJson(raw_ostream &Out, const LocationContext *LCtx = nullptr, 475 const char *NL = "\n", unsigned int Space = 0, 476 bool IsDot = false) const; 477 478 void printDOT(raw_ostream &Out, const LocationContext *LCtx = nullptr, 479 unsigned int Space = 0) const; 480 481 void dump() const; 482 483 private: 484 friend void ProgramStateRetain(const ProgramState *state); 485 friend void ProgramStateRelease(const ProgramState *state); 486 487 /// \sa invalidateValues() 488 /// \sa invalidateRegions() 489 ProgramStateRef 490 invalidateRegionsImpl(ArrayRef<SVal> Values, 491 const Expr *E, unsigned BlockCount, 492 const LocationContext *LCtx, 493 bool ResultsInSymbolEscape, 494 InvalidatedSymbols *IS, 495 RegionAndSymbolInvalidationTraits *HTraits, 496 const CallEvent *Call) const; 497 498 SVal wrapSymbolicRegion(SVal Base) const; 499 }; 500 501 //===----------------------------------------------------------------------===// 502 // ProgramStateManager - Factory object for ProgramStates. 503 //===----------------------------------------------------------------------===// 504 505 class ProgramStateManager { 506 friend class ProgramState; 507 friend void ProgramStateRelease(const ProgramState *state); 508 private: 509 /// Eng - The ExprEngine that owns this state manager. 510 ExprEngine *Eng; /* Can be null. */ 511 512 EnvironmentManager EnvMgr; 513 std::unique_ptr<StoreManager> StoreMgr; 514 std::unique_ptr<ConstraintManager> ConstraintMgr; 515 516 ProgramState::GenericDataMap::Factory GDMFactory; 517 518 typedef llvm::DenseMap<void*,std::pair<void*,void (*)(void*)> > GDMContextsTy; 519 GDMContextsTy GDMContexts; 520 521 /// StateSet - FoldingSet containing all the states created for analyzing 522 /// a particular function. This is used to unique states. 523 llvm::FoldingSet<ProgramState> StateSet; 524 525 /// Object that manages the data for all created SVals. 526 std::unique_ptr<SValBuilder> svalBuilder; 527 528 /// Manages memory for created CallEvents. 529 std::unique_ptr<CallEventManager> CallEventMgr; 530 531 /// A BumpPtrAllocator to allocate states. 532 llvm::BumpPtrAllocator &Alloc; 533 534 /// A vector of ProgramStates that we can reuse. 535 std::vector<ProgramState *> freeStates; 536 537 public: 538 ProgramStateManager(ASTContext &Ctx, 539 StoreManagerCreator CreateStoreManager, 540 ConstraintManagerCreator CreateConstraintManager, 541 llvm::BumpPtrAllocator& alloc, 542 ExprEngine *expreng); 543 544 ~ProgramStateManager(); 545 546 ProgramStateRef getInitialState(const LocationContext *InitLoc); 547 548 ASTContext &getContext() { return svalBuilder->getContext(); } 549 const ASTContext &getContext() const { return svalBuilder->getContext(); } 550 551 BasicValueFactory &getBasicVals() { 552 return svalBuilder->getBasicValueFactory(); 553 } 554 555 SValBuilder &getSValBuilder() { 556 return *svalBuilder; 557 } 558 559 const SValBuilder &getSValBuilder() const { 560 return *svalBuilder; 561 } 562 563 SymbolManager &getSymbolManager() { 564 return svalBuilder->getSymbolManager(); 565 } 566 const SymbolManager &getSymbolManager() const { 567 return svalBuilder->getSymbolManager(); 568 } 569 570 llvm::BumpPtrAllocator& getAllocator() { return Alloc; } 571 572 MemRegionManager& getRegionManager() { 573 return svalBuilder->getRegionManager(); 574 } 575 const MemRegionManager &getRegionManager() const { 576 return svalBuilder->getRegionManager(); 577 } 578 579 CallEventManager &getCallEventManager() { return *CallEventMgr; } 580 581 StoreManager &getStoreManager() { return *StoreMgr; } 582 ConstraintManager &getConstraintManager() { return *ConstraintMgr; } 583 ExprEngine &getOwningEngine() { return *Eng; } 584 585 ProgramStateRef 586 removeDeadBindingsFromEnvironmentAndStore(ProgramStateRef St, 587 const StackFrameContext *LCtx, 588 SymbolReaper &SymReaper); 589 590 public: 591 592 SVal ArrayToPointer(Loc Array, QualType ElementTy) { 593 return StoreMgr->ArrayToPointer(Array, ElementTy); 594 } 595 596 // Methods that manipulate the GDM. 597 ProgramStateRef addGDM(ProgramStateRef St, void *Key, void *Data); 598 ProgramStateRef removeGDM(ProgramStateRef state, void *Key); 599 600 // Methods that query & manipulate the Store. 601 602 void iterBindings(ProgramStateRef state, StoreManager::BindingsHandler& F) { 603 StoreMgr->iterBindings(state->getStore(), F); 604 } 605 606 ProgramStateRef getPersistentState(ProgramState &Impl); 607 ProgramStateRef getPersistentStateWithGDM(ProgramStateRef FromState, 608 ProgramStateRef GDMState); 609 610 bool haveEqualConstraints(ProgramStateRef S1, ProgramStateRef S2) const { 611 return ConstraintMgr->haveEqualConstraints(S1, S2); 612 } 613 614 bool haveEqualEnvironments(ProgramStateRef S1, ProgramStateRef S2) const { 615 return S1->Env == S2->Env; 616 } 617 618 bool haveEqualStores(ProgramStateRef S1, ProgramStateRef S2) const { 619 return S1->store == S2->store; 620 } 621 622 //==---------------------------------------------------------------------==// 623 // Generic Data Map methods. 624 //==---------------------------------------------------------------------==// 625 // 626 // ProgramStateManager and ProgramState support a "generic data map" that allows 627 // different clients of ProgramState objects to embed arbitrary data within a 628 // ProgramState object. The generic data map is essentially an immutable map 629 // from a "tag" (that acts as the "key" for a client) and opaque values. 630 // Tags/keys and values are simply void* values. The typical way that clients 631 // generate unique tags are by taking the address of a static variable. 632 // Clients are responsible for ensuring that data values referred to by a 633 // the data pointer are immutable (and thus are essentially purely functional 634 // data). 635 // 636 // The templated methods below use the ProgramStateTrait<T> class 637 // to resolve keys into the GDM and to return data values to clients. 638 // 639 640 // Trait based GDM dispatch. 641 template <typename T> 642 ProgramStateRef set(ProgramStateRef st, typename ProgramStateTrait<T>::data_type D) { 643 return addGDM(st, ProgramStateTrait<T>::GDMIndex(), 644 ProgramStateTrait<T>::MakeVoidPtr(D)); 645 } 646 647 template<typename T> 648 ProgramStateRef set(ProgramStateRef st, 649 typename ProgramStateTrait<T>::key_type K, 650 typename ProgramStateTrait<T>::value_type V, 651 typename ProgramStateTrait<T>::context_type C) { 652 653 return addGDM(st, ProgramStateTrait<T>::GDMIndex(), 654 ProgramStateTrait<T>::MakeVoidPtr(ProgramStateTrait<T>::Set(st->get<T>(), K, V, C))); 655 } 656 657 template <typename T> 658 ProgramStateRef add(ProgramStateRef st, 659 typename ProgramStateTrait<T>::key_type K, 660 typename ProgramStateTrait<T>::context_type C) { 661 return addGDM(st, ProgramStateTrait<T>::GDMIndex(), 662 ProgramStateTrait<T>::MakeVoidPtr(ProgramStateTrait<T>::Add(st->get<T>(), K, C))); 663 } 664 665 template <typename T> 666 ProgramStateRef remove(ProgramStateRef st, 667 typename ProgramStateTrait<T>::key_type K, 668 typename ProgramStateTrait<T>::context_type C) { 669 670 return addGDM(st, ProgramStateTrait<T>::GDMIndex(), 671 ProgramStateTrait<T>::MakeVoidPtr(ProgramStateTrait<T>::Remove(st->get<T>(), K, C))); 672 } 673 674 template <typename T> 675 ProgramStateRef remove(ProgramStateRef st) { 676 return removeGDM(st, ProgramStateTrait<T>::GDMIndex()); 677 } 678 679 void *FindGDMContext(void *index, 680 void *(*CreateContext)(llvm::BumpPtrAllocator&), 681 void (*DeleteContext)(void*)); 682 683 template <typename T> 684 typename ProgramStateTrait<T>::context_type get_context() { 685 void *p = FindGDMContext(ProgramStateTrait<T>::GDMIndex(), 686 ProgramStateTrait<T>::CreateContext, 687 ProgramStateTrait<T>::DeleteContext); 688 689 return ProgramStateTrait<T>::MakeContext(p); 690 } 691 }; 692 693 694 //===----------------------------------------------------------------------===// 695 // Out-of-line method definitions for ProgramState. 696 //===----------------------------------------------------------------------===// 697 698 inline ConstraintManager &ProgramState::getConstraintManager() const { 699 return stateMgr->getConstraintManager(); 700 } 701 702 inline const VarRegion* ProgramState::getRegion(const VarDecl *D, 703 const LocationContext *LC) const 704 { 705 return getStateManager().getRegionManager().getVarRegion(D, LC); 706 } 707 708 inline ProgramStateRef ProgramState::assume(DefinedOrUnknownSVal Cond, 709 bool Assumption) const { 710 if (Cond.isUnknown()) 711 return this; 712 713 return getStateManager().ConstraintMgr 714 ->assume(this, Cond.castAs<DefinedSVal>(), Assumption); 715 } 716 717 inline std::pair<ProgramStateRef , ProgramStateRef > 718 ProgramState::assume(DefinedOrUnknownSVal Cond) const { 719 if (Cond.isUnknown()) 720 return std::make_pair(this, this); 721 722 return getStateManager().ConstraintMgr 723 ->assumeDual(this, Cond.castAs<DefinedSVal>()); 724 } 725 726 inline ProgramStateRef ProgramState::assumeInclusiveRange( 727 DefinedOrUnknownSVal Val, const llvm::APSInt &From, const llvm::APSInt &To, 728 bool Assumption) const { 729 if (Val.isUnknown()) 730 return this; 731 732 assert(isa<NonLoc>(Val) && "Only NonLocs are supported!"); 733 734 return getStateManager().ConstraintMgr->assumeInclusiveRange( 735 this, Val.castAs<NonLoc>(), From, To, Assumption); 736 } 737 738 inline std::pair<ProgramStateRef, ProgramStateRef> 739 ProgramState::assumeInclusiveRange(DefinedOrUnknownSVal Val, 740 const llvm::APSInt &From, 741 const llvm::APSInt &To) const { 742 if (Val.isUnknown()) 743 return std::make_pair(this, this); 744 745 assert(isa<NonLoc>(Val) && "Only NonLocs are supported!"); 746 747 return getStateManager().ConstraintMgr->assumeInclusiveRangeDual( 748 this, Val.castAs<NonLoc>(), From, To); 749 } 750 751 inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V, const LocationContext *LCtx) const { 752 if (std::optional<Loc> L = LV.getAs<Loc>()) 753 return bindLoc(*L, V, LCtx); 754 return this; 755 } 756 757 inline Loc ProgramState::getLValue(const CXXBaseSpecifier &BaseSpec, 758 const SubRegion *Super) const { 759 const auto *Base = BaseSpec.getType()->getAsCXXRecordDecl(); 760 return loc::MemRegionVal( 761 getStateManager().getRegionManager().getCXXBaseObjectRegion( 762 Base, Super, BaseSpec.isVirtual())); 763 } 764 765 inline Loc ProgramState::getLValue(const CXXRecordDecl *BaseClass, 766 const SubRegion *Super, 767 bool IsVirtual) const { 768 return loc::MemRegionVal( 769 getStateManager().getRegionManager().getCXXBaseObjectRegion( 770 BaseClass, Super, IsVirtual)); 771 } 772 773 inline Loc ProgramState::getLValue(const VarDecl *VD, 774 const LocationContext *LC) const { 775 return getStateManager().StoreMgr->getLValueVar(VD, LC); 776 } 777 778 inline Loc ProgramState::getLValue(const CompoundLiteralExpr *literal, 779 const LocationContext *LC) const { 780 return getStateManager().StoreMgr->getLValueCompoundLiteral(literal, LC); 781 } 782 783 inline SVal ProgramState::getLValue(const ObjCIvarDecl *D, SVal Base) const { 784 return getStateManager().StoreMgr->getLValueIvar(D, Base); 785 } 786 787 inline SVal ProgramState::getLValue(QualType ElementType, SVal Idx, SVal Base) const{ 788 if (std::optional<NonLoc> N = Idx.getAs<NonLoc>()) 789 return getStateManager().StoreMgr->getLValueElement(ElementType, *N, Base); 790 return UnknownVal(); 791 } 792 793 inline SVal ProgramState::getSVal(const Stmt *Ex, 794 const LocationContext *LCtx) const{ 795 return Env.getSVal(EnvironmentEntry(Ex, LCtx), 796 *getStateManager().svalBuilder); 797 } 798 799 inline SVal 800 ProgramState::getSValAsScalarOrLoc(const Stmt *S, 801 const LocationContext *LCtx) const { 802 if (const Expr *Ex = dyn_cast<Expr>(S)) { 803 QualType T = Ex->getType(); 804 if (Ex->isGLValue() || Loc::isLocType(T) || 805 T->isIntegralOrEnumerationType()) 806 return getSVal(S, LCtx); 807 } 808 809 return UnknownVal(); 810 } 811 812 inline SVal ProgramState::getRawSVal(Loc LV, QualType T) const { 813 return getStateManager().StoreMgr->getBinding(getStore(), LV, T); 814 } 815 816 inline SVal ProgramState::getSVal(const MemRegion* R, QualType T) const { 817 return getStateManager().StoreMgr->getBinding(getStore(), 818 loc::MemRegionVal(R), 819 T); 820 } 821 822 inline BasicValueFactory &ProgramState::getBasicVals() const { 823 return getStateManager().getBasicVals(); 824 } 825 826 inline SymbolManager &ProgramState::getSymbolManager() const { 827 return getStateManager().getSymbolManager(); 828 } 829 830 template<typename T> 831 ProgramStateRef ProgramState::add(typename ProgramStateTrait<T>::key_type K) const { 832 return getStateManager().add<T>(this, K, get_context<T>()); 833 } 834 835 template <typename T> 836 typename ProgramStateTrait<T>::context_type ProgramState::get_context() const { 837 return getStateManager().get_context<T>(); 838 } 839 840 template<typename T> 841 ProgramStateRef ProgramState::remove(typename ProgramStateTrait<T>::key_type K) const { 842 return getStateManager().remove<T>(this, K, get_context<T>()); 843 } 844 845 template<typename T> 846 ProgramStateRef ProgramState::remove(typename ProgramStateTrait<T>::key_type K, 847 typename ProgramStateTrait<T>::context_type C) const { 848 return getStateManager().remove<T>(this, K, C); 849 } 850 851 template <typename T> 852 ProgramStateRef ProgramState::remove() const { 853 return getStateManager().remove<T>(this); 854 } 855 856 template<typename T> 857 ProgramStateRef ProgramState::set(typename ProgramStateTrait<T>::data_type D) const { 858 return getStateManager().set<T>(this, D); 859 } 860 861 template<typename T> 862 ProgramStateRef ProgramState::set(typename ProgramStateTrait<T>::key_type K, 863 typename ProgramStateTrait<T>::value_type E) const { 864 return getStateManager().set<T>(this, K, E, get_context<T>()); 865 } 866 867 template<typename T> 868 ProgramStateRef ProgramState::set(typename ProgramStateTrait<T>::key_type K, 869 typename ProgramStateTrait<T>::value_type E, 870 typename ProgramStateTrait<T>::context_type C) const { 871 return getStateManager().set<T>(this, K, E, C); 872 } 873 874 template <typename CB> 875 CB ProgramState::scanReachableSymbols(SVal val) const { 876 CB cb(this); 877 scanReachableSymbols(val, cb); 878 return cb; 879 } 880 881 template <typename CB> 882 CB ProgramState::scanReachableSymbols( 883 llvm::iterator_range<region_iterator> Reachable) const { 884 CB cb(this); 885 scanReachableSymbols(Reachable, cb); 886 return cb; 887 } 888 889 /// \class ScanReachableSymbols 890 /// A utility class that visits the reachable symbols using a custom 891 /// SymbolVisitor. Terminates recursive traversal when the visitor function 892 /// returns false. 893 class ScanReachableSymbols { 894 typedef llvm::DenseSet<const void*> VisitedItems; 895 896 VisitedItems visited; 897 ProgramStateRef state; 898 SymbolVisitor &visitor; 899 public: 900 ScanReachableSymbols(ProgramStateRef st, SymbolVisitor &v) 901 : state(std::move(st)), visitor(v) {} 902 903 bool scan(nonloc::LazyCompoundVal val); 904 bool scan(nonloc::CompoundVal val); 905 bool scan(SVal val); 906 bool scan(const MemRegion *R); 907 bool scan(const SymExpr *sym); 908 }; 909 910 } // end ento namespace 911 912 } // end clang namespace 913 914 #endif 915