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