| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 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 "clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h" |
| 24 | #include "llvm/ADT/FoldingSet.h" |
| 25 | #include "llvm/ADT/ImmutableMap.h" |
| 26 | #include "llvm/Support/Allocator.h" |
| 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 &, SubEngine *); |
| 44 | typedef std::unique_ptr<StoreManager>(*StoreManagerCreator)( |
| 45 | ProgramStateManager &); |
| 46 | typedef llvm::ImmutableMap<const SubRegion*, TaintTagType> TaintedSubRegions; |
| 47 | |
| 48 | |
| 49 | |
| 50 | |
| 51 | |
| 52 | template <typename T> struct ProgramStatePartialTrait; |
| 53 | |
| 54 | template <typename T> struct ProgramStateTrait { |
| 55 | typedef typename T::data_type data_type; |
| 56 | static inline void *MakeVoidPtr(data_type D) { return (void*) D; } |
| 57 | static inline data_type MakeData(void *const* P) { |
| 58 | return P ? (data_type) *P : (data_type) 0; |
| 59 | } |
| 60 | }; |
| 61 | |
| 62 | |
| 63 | |
| 64 | |
| 65 | |
| 66 | |
| 67 | |
| 68 | |
| 69 | |
| 70 | |
| 71 | |
| 72 | |
| 73 | |
| 74 | class ProgramState : public llvm::FoldingSetNode { |
| 75 | public: |
| 76 | typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy; |
| 77 | typedef llvm::ImmutableMap<void*, void*> GenericDataMap; |
| 78 | |
| 79 | private: |
| 80 | void operator=(const ProgramState& R) = delete; |
| 81 | |
| 82 | friend class ProgramStateManager; |
| 83 | friend class ExplodedGraph; |
| 84 | friend class ExplodedNode; |
| 85 | |
| 86 | ProgramStateManager *stateMgr; |
| 87 | Environment Env; |
| 88 | Store store; |
| 89 | GenericDataMap GDM; |
| 90 | unsigned refCount; |
| 91 | |
| 92 | |
| 93 | |
| 94 | ProgramStateRef makeWithStore(const StoreRef &store) const; |
| 95 | |
| 96 | void setStore(const StoreRef &storeRef); |
| 97 | |
| 98 | public: |
| 99 | |
| 100 | ProgramState(ProgramStateManager *mgr, const Environment& env, |
| 101 | StoreRef st, GenericDataMap gdm); |
| 102 | |
| 103 | |
| 104 | |
| 105 | ProgramState(const ProgramState &RHS); |
| 106 | |
| 107 | ~ProgramState(); |
| 108 | |
| 109 | int64_t getID() const; |
| 110 | |
| 111 | |
| 112 | ProgramStateManager &getStateManager() const { |
| 113 | return *stateMgr; |
| 114 | } |
| 115 | |
| 116 | AnalysisManager &getAnalysisManager() const; |
| 117 | |
| 118 | |
| 119 | ConstraintManager &getConstraintManager() const; |
| 120 | |
| 121 | |
| 122 | |
| 123 | const Environment& getEnvironment() const { return Env; } |
| 124 | |
| 125 | |
| 126 | |
| 127 | Store getStore() const { return store; } |
| 128 | |
| 129 | |
| 130 | |
| 131 | GenericDataMap getGDM() const { return GDM; } |
| 132 | |
| 133 | void setGDM(GenericDataMap gdm) { GDM = gdm; } |
| 134 | |
| 135 | |
| 136 | |
| 137 | |
| 138 | static void Profile(llvm::FoldingSetNodeID& ID, const ProgramState *V) { |
| 139 | V->Env.Profile(ID); |
| 140 | ID.AddPointer(V->store); |
| 141 | V->GDM.Profile(ID); |
| 142 | } |
| 143 | |
| 144 | |
| 145 | |
| 146 | void Profile(llvm::FoldingSetNodeID& ID) const { |
| 147 | Profile(ID, this); |
| 148 | } |
| 149 | |
| 150 | BasicValueFactory &getBasicVals() const; |
| 151 | SymbolManager &getSymbolManager() const; |
| 152 | |
| 153 | |
| 154 | |
| 155 | |
| 156 | |
| 157 | |
| 158 | |
| 159 | |
| 160 | |
| 161 | |
| 162 | |
| 163 | |
| 164 | |
| 165 | |
| 166 | |
| 167 | |
| 168 | |
| 169 | |
| 170 | |
| 171 | |
| 172 | |
| 173 | |
| 174 | |
| 175 | |
| 176 | |
| 177 | |
| 178 | |
| 179 | |
| 180 | |
| 181 | |
| 182 | |
| 183 | |
| 184 | LLVM_NODISCARD ProgramStateRef assume(DefinedOrUnknownSVal cond, |
| 185 | bool assumption) const; |
| 186 | |
| 187 | |
| 188 | |
| 189 | |
| 190 | |
| 191 | |
| 192 | LLVM_NODISCARD std::pair<ProgramStateRef, ProgramStateRef> |
| 193 | assume(DefinedOrUnknownSVal cond) const; |
| 194 | |
| 195 | LLVM_NODISCARD ProgramStateRef |
| 196 | assumeInBound(DefinedOrUnknownSVal idx, DefinedOrUnknownSVal upperBound, |
| 197 | bool assumption, QualType IndexType = QualType()) const; |
| 198 | |
| 199 | |
| 200 | |
| 201 | |
| 202 | |
| 203 | |
| 204 | |
| 205 | LLVM_NODISCARD ProgramStateRef assumeInclusiveRange(DefinedOrUnknownSVal Val, |
| 206 | const llvm::APSInt &From, |
| 207 | const llvm::APSInt &To, |
| 208 | bool assumption) const; |
| 209 | |
| 210 | |
| 211 | |
| 212 | |
| 213 | |
| 214 | |
| 215 | LLVM_NODISCARD std::pair<ProgramStateRef, ProgramStateRef> |
| 216 | assumeInclusiveRange(DefinedOrUnknownSVal Val, const llvm::APSInt &From, |
| 217 | const llvm::APSInt &To) const; |
| 218 | |
| 219 | |
| 220 | |
| 221 | ConditionTruthVal isNonNull(SVal V) const; |
| 222 | |
| 223 | |
| 224 | |
| 225 | ConditionTruthVal isNull(SVal V) const; |
| 226 | |
| 227 | |
| 228 | ConditionTruthVal areEqual(SVal Lhs, SVal Rhs) const; |
| 229 | |
| 230 | |
| 231 | const VarRegion* getRegion(const VarDecl *D, const LocationContext *LC) const; |
| 232 | |
| 233 | |
| 234 | |
| 235 | |
| 236 | |
| 237 | |
| 238 | |
| 239 | LLVM_NODISCARD ProgramStateRef BindExpr(const Stmt *S, |
| 240 | const LocationContext *LCtx, SVal V, |
| 241 | bool Invalidate = true) const; |
| 242 | |
| 243 | LLVM_NODISCARD ProgramStateRef bindLoc(Loc location, SVal V, |
| 244 | const LocationContext *LCtx, |
| 245 | bool notifyChanges = true) const; |
| 246 | |
| 247 | LLVM_NODISCARD ProgramStateRef bindLoc(SVal location, SVal V, |
| 248 | const LocationContext *LCtx) const; |
| 249 | |
| 250 | |
| 251 | |
| 252 | |
| 253 | |
| 254 | |
| 255 | |
| 256 | LLVM_NODISCARD ProgramStateRef |
| 257 | bindDefaultInitial(SVal loc, SVal V, const LocationContext *LCtx) const; |
| 258 | |
| 259 | |
| 260 | |
| 261 | LLVM_NODISCARD ProgramStateRef |
| 262 | bindDefaultZero(SVal loc, const LocationContext *LCtx) const; |
| 263 | |
| 264 | LLVM_NODISCARD ProgramStateRef killBinding(Loc LV) const; |
| 265 | |
| 266 | |
| 267 | |
| 268 | |
| 269 | |
| 270 | |
| 271 | |
| 272 | |
| 273 | |
| 274 | |
| 275 | |
| 276 | |
| 277 | |
| 278 | |
| 279 | |
| 280 | |
| 281 | |
| 282 | |
| 283 | |
| 284 | LLVM_NODISCARD ProgramStateRef |
| 285 | invalidateRegions(ArrayRef<const MemRegion *> Regions, const Expr *E, |
| 286 | unsigned BlockCount, const LocationContext *LCtx, |
| 287 | bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr, |
| 288 | const CallEvent *Call = nullptr, |
| 289 | RegionAndSymbolInvalidationTraits *ITraits = nullptr) const; |
| 290 | |
| 291 | LLVM_NODISCARD ProgramStateRef |
| 292 | invalidateRegions(ArrayRef<SVal> Regions, const Expr *E, |
| 293 | unsigned BlockCount, const LocationContext *LCtx, |
| 294 | bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr, |
| 295 | const CallEvent *Call = nullptr, |
| 296 | RegionAndSymbolInvalidationTraits *ITraits = nullptr) const; |
| 297 | |
| 298 | |
| 299 | |
| 300 | LLVM_NODISCARD ProgramStateRef enterStackFrame( |
| 301 | const CallEvent &Call, const StackFrameContext *CalleeCtx) const; |
| 302 | |
| 303 | |
| 304 | Loc getLValue(const CXXBaseSpecifier &BaseSpec, const SubRegion *Super) const; |
| 305 | |
| 306 | |
| 307 | Loc getLValue(const CXXRecordDecl *BaseClass, const SubRegion *Super, |
| 308 | bool IsVirtual) const; |
| 309 | |
| 310 | |
| 311 | Loc getLValue(const VarDecl *D, const LocationContext *LC) const; |
| 312 | |
| 313 | Loc getLValue(const CompoundLiteralExpr *literal, |
| 314 | const LocationContext *LC) const; |
| 315 | |
| 316 | |
| 317 | SVal getLValue(const ObjCIvarDecl *decl, SVal base) const; |
| 318 | |
| 319 | |
| 320 | SVal getLValue(const FieldDecl *decl, SVal Base) const; |
| 321 | |
| 322 | |
| 323 | SVal getLValue(const IndirectFieldDecl *decl, SVal Base) const; |
| 324 | |
| 325 | |
| 326 | SVal getLValue(QualType ElementType, SVal Idx, SVal Base) const; |
| 327 | |
| 328 | |
| 329 | SVal getSVal(const Stmt *S, const LocationContext *LCtx) const; |
| 330 | |
| 331 | SVal getSValAsScalarOrLoc(const Stmt *Ex, const LocationContext *LCtx) const; |
| 332 | |
| 333 | |
| 334 | |
| 335 | SVal getSVal(Loc LV, QualType T = QualType()) const; |
| 336 | |
| 337 | |
| 338 | SVal getRawSVal(Loc LV, QualType T= QualType()) const; |
| 339 | |
| 340 | |
| 341 | |
| 342 | SVal getSVal(const MemRegion* R, QualType T = QualType()) const; |
| 343 | |
| 344 | |
| 345 | |
| 346 | |
| 347 | |
| 348 | SVal getSValAsScalarOrLoc(const MemRegion *R) const; |
| 349 | |
| 350 | using region_iterator = const MemRegion **; |
| 351 | |
| 352 | |
| 353 | |
| 354 | |
| 355 | |
| 356 | |
| 357 | |
| 358 | |
| 359 | bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const; |
| 360 | |
| 361 | |
| 362 | |
| 363 | bool scanReachableSymbols(llvm::iterator_range<region_iterator> Reachable, |
| 364 | SymbolVisitor &visitor) const; |
| 365 | |
| 366 | template <typename CB> CB scanReachableSymbols(SVal val) const; |
| 367 | template <typename CB> CB |
| 368 | scanReachableSymbols(llvm::iterator_range<region_iterator> Reachable) const; |
| 369 | |
| 370 | |
| 371 | LLVM_NODISCARD ProgramStateRef |
| 372 | addTaint(const Stmt *S, const LocationContext *LCtx, |
| 373 | TaintTagType Kind = TaintTagGeneric) const; |
| 374 | |
| 375 | |
| 376 | LLVM_NODISCARD ProgramStateRef |
| 377 | addTaint(SVal V, TaintTagType Kind = TaintTagGeneric) const; |
| 378 | |
| 379 | |
| 380 | LLVM_NODISCARD ProgramStateRef addTaint(SymbolRef S, |
| 381 | TaintTagType Kind = TaintTagGeneric) const; |
| 382 | |
| 383 | |
| 384 | LLVM_NODISCARD ProgramStateRef |
| 385 | addTaint(const MemRegion *R, TaintTagType Kind = TaintTagGeneric) const; |
| 386 | |
| 387 | |
| 388 | |
| 389 | |
| 390 | |
| 391 | LLVM_NODISCARD ProgramStateRef |
| 392 | addPartialTaint(SymbolRef ParentSym, const SubRegion *SubRegion, |
| 393 | TaintTagType Kind = TaintTagGeneric) const; |
| 394 | |
| 395 | |
| 396 | bool isTainted(const Stmt *S, const LocationContext *LCtx, |
| 397 | TaintTagType Kind = TaintTagGeneric) const; |
| 398 | bool isTainted(SVal V, TaintTagType Kind = TaintTagGeneric) const; |
| 399 | bool isTainted(SymbolRef Sym, TaintTagType Kind = TaintTagGeneric) const; |
| 400 | bool isTainted(const MemRegion *Reg, TaintTagType Kind=TaintTagGeneric) const; |
| 401 | |
| 402 | |
| 403 | |
| 404 | |
| 405 | |
| 406 | void *const* FindGDM(void *K) const; |
| 407 | |
| 408 | template <typename T> |
| 409 | LLVM_NODISCARD ProgramStateRef |
| 410 | add(typename ProgramStateTrait<T>::key_type K) const; |
| 411 | |
| 412 | template <typename T> |
| 413 | typename ProgramStateTrait<T>::data_type |
| 414 | get() const { |
| 415 | return ProgramStateTrait<T>::MakeData(FindGDM(ProgramStateTrait<T>::GDMIndex())); |
| 416 | } |
| 417 | |
| 418 | template<typename T> |
| 419 | typename ProgramStateTrait<T>::lookup_type |
| 420 | get(typename ProgramStateTrait<T>::key_type key) const { |
| 421 | void *const* d = FindGDM(ProgramStateTrait<T>::GDMIndex()); |
| 422 | return ProgramStateTrait<T>::Lookup(ProgramStateTrait<T>::MakeData(d), key); |
| 423 | } |
| 424 | |
| 425 | template <typename T> |
| 426 | typename ProgramStateTrait<T>::context_type get_context() const; |
| 427 | |
| 428 | template <typename T> |
| 429 | LLVM_NODISCARD ProgramStateRef |
| 430 | remove(typename ProgramStateTrait<T>::key_type K) const; |
| 431 | |
| 432 | template <typename T> |
| 433 | LLVM_NODISCARD ProgramStateRef |
| 434 | remove(typename ProgramStateTrait<T>::key_type K, |
| 435 | typename ProgramStateTrait<T>::context_type C) const; |
| 436 | |
| 437 | template <typename T> LLVM_NODISCARD ProgramStateRef remove() const; |
| 438 | |
| 439 | template <typename T> |
| 440 | LLVM_NODISCARD ProgramStateRef |
| 441 | set(typename ProgramStateTrait<T>::data_type D) const; |
| 442 | |
| 443 | template <typename T> |
| 444 | LLVM_NODISCARD ProgramStateRef |
| 445 | set(typename ProgramStateTrait<T>::key_type K, |
| 446 | typename ProgramStateTrait<T>::value_type E) const; |
| 447 | |
| 448 | template <typename T> |
| 449 | LLVM_NODISCARD ProgramStateRef |
| 450 | set(typename ProgramStateTrait<T>::key_type K, |
| 451 | typename ProgramStateTrait<T>::value_type E, |
| 452 | typename ProgramStateTrait<T>::context_type C) const; |
| 453 | |
| 454 | template<typename T> |
| 455 | bool contains(typename ProgramStateTrait<T>::key_type key) const { |
| 456 | void *const* d = FindGDM(ProgramStateTrait<T>::GDMIndex()); |
| 457 | return ProgramStateTrait<T>::Contains(ProgramStateTrait<T>::MakeData(d), key); |
| 458 | } |
| 459 | |
| 460 | |
| 461 | void print(raw_ostream &Out, const char *nl = "\n", const char *sep = "", |
| 462 | const LocationContext *CurrentLC = nullptr) const; |
| 463 | void printDOT(raw_ostream &Out, |
| 464 | const LocationContext *CurrentLC = nullptr) const; |
| 465 | void printTaint(raw_ostream &Out, const char *nl = "\n") const; |
| 466 | |
| 467 | void dump() const; |
| 468 | void dumpTaint() const; |
| 469 | |
| 470 | private: |
| 471 | friend void ProgramStateRetain(const ProgramState *state); |
| 472 | friend void ProgramStateRelease(const ProgramState *state); |
| 473 | |
| 474 | |
| 475 | |
| 476 | ProgramStateRef |
| 477 | invalidateRegionsImpl(ArrayRef<SVal> Values, |
| 478 | const Expr *E, unsigned BlockCount, |
| 479 | const LocationContext *LCtx, |
| 480 | bool ResultsInSymbolEscape, |
| 481 | InvalidatedSymbols *IS, |
| 482 | RegionAndSymbolInvalidationTraits *HTraits, |
| 483 | const CallEvent *Call) const; |
| 484 | }; |
| 485 | |
| 486 | |
| 487 | |
| 488 | |
| 489 | |
| 490 | class ProgramStateManager { |
| 491 | friend class ProgramState; |
| 492 | friend void ProgramStateRelease(const ProgramState *state); |
| 493 | private: |
| 494 | |
| 495 | SubEngine *Eng; |
| 496 | |
| 497 | EnvironmentManager EnvMgr; |
| 498 | std::unique_ptr<StoreManager> StoreMgr; |
| 499 | std::unique_ptr<ConstraintManager> ConstraintMgr; |
| 500 | |
| 501 | ProgramState::GenericDataMap::Factory GDMFactory; |
| 502 | TaintedSubRegions::Factory TSRFactory; |
| 503 | |
| 504 | typedef llvm::DenseMap<void*,std::pair<void*,void (*)(void*)> > GDMContextsTy; |
| 505 | GDMContextsTy GDMContexts; |
| 506 | |
| 507 | |
| 508 | |
| 509 | llvm::FoldingSet<ProgramState> StateSet; |
| 510 | |
| 511 | |
| 512 | std::unique_ptr<SValBuilder> svalBuilder; |
| 513 | |
| 514 | |
| 515 | std::unique_ptr<CallEventManager> CallEventMgr; |
| 516 | |
| 517 | |
| 518 | llvm::BumpPtrAllocator &Alloc; |
| 519 | |
| 520 | |
| 521 | std::vector<ProgramState *> freeStates; |
| 522 | |
| 523 | public: |
| 524 | ProgramStateManager(ASTContext &Ctx, |
| 525 | StoreManagerCreator CreateStoreManager, |
| 526 | ConstraintManagerCreator CreateConstraintManager, |
| 527 | llvm::BumpPtrAllocator& alloc, |
| 528 | SubEngine *subeng); |
| 529 | |
| 530 | ~ProgramStateManager(); |
| 531 | |
| 532 | ProgramStateRef getInitialState(const LocationContext *InitLoc); |
| 533 | |
| 534 | ASTContext &getContext() { return svalBuilder->getContext(); } |
| 535 | const ASTContext &getContext() const { return svalBuilder->getContext(); } |
| 536 | |
| 537 | BasicValueFactory &getBasicVals() { |
| 538 | return svalBuilder->getBasicValueFactory(); |
| 539 | } |
| 540 | |
| 541 | SValBuilder &getSValBuilder() { |
| 542 | return *svalBuilder; |
| 543 | } |
| 544 | |
| 545 | SymbolManager &getSymbolManager() { |
| 546 | return svalBuilder->getSymbolManager(); |
| 547 | } |
| 548 | const SymbolManager &getSymbolManager() const { |
| 549 | return svalBuilder->getSymbolManager(); |
| 550 | } |
| 551 | |
| 552 | llvm::BumpPtrAllocator& getAllocator() { return Alloc; } |
| 553 | |
| 554 | MemRegionManager& getRegionManager() { |
| 555 | return svalBuilder->getRegionManager(); |
| 556 | } |
| 557 | const MemRegionManager &getRegionManager() const { |
| 558 | return svalBuilder->getRegionManager(); |
| 559 | } |
| 560 | |
| 561 | CallEventManager &getCallEventManager() { return *CallEventMgr; } |
| 562 | |
| 563 | StoreManager &getStoreManager() { return *StoreMgr; } |
| 564 | ConstraintManager &getConstraintManager() { return *ConstraintMgr; } |
| 565 | SubEngine &getOwningEngine() { return *Eng; } |
| 566 | |
| 567 | ProgramStateRef removeDeadBindings(ProgramStateRef St, |
| 568 | const StackFrameContext *LCtx, |
| 569 | SymbolReaper& SymReaper); |
| 570 | |
| 571 | public: |
| 572 | |
| 573 | SVal ArrayToPointer(Loc Array, QualType ElementTy) { |
| 574 | return StoreMgr->ArrayToPointer(Array, ElementTy); |
| 575 | } |
| 576 | |
| 577 | |
| 578 | ProgramStateRef addGDM(ProgramStateRef St, void *Key, void *Data); |
| 579 | ProgramStateRef removeGDM(ProgramStateRef state, void *Key); |
| 580 | |
| 581 | |
| 582 | |
| 583 | void iterBindings(ProgramStateRef state, StoreManager::BindingsHandler& F) { |
| 584 | StoreMgr->iterBindings(state->getStore(), F); |
| 585 | } |
| 586 | |
| 587 | ProgramStateRef getPersistentState(ProgramState &Impl); |
| 588 | ProgramStateRef getPersistentStateWithGDM(ProgramStateRef FromState, |
| 589 | ProgramStateRef GDMState); |
| 590 | |
| 591 | bool haveEqualConstraints(ProgramStateRef S1, ProgramStateRef S2) const { |
| 592 | return ConstraintMgr->haveEqualConstraints(S1, S2); |
| 593 | } |
| 594 | |
| 595 | bool haveEqualEnvironments(ProgramStateRef S1, ProgramStateRef S2) const { |
| 596 | return S1->Env == S2->Env; |
| 597 | } |
| 598 | |
| 599 | bool haveEqualStores(ProgramStateRef S1, ProgramStateRef S2) const { |
| 600 | return S1->store == S2->store; |
| 601 | } |
| 602 | |
| 603 | |
| 604 | |
| 605 | |
| 606 | |
| 607 | |
| 608 | |
| 609 | |
| 610 | |
| 611 | |
| 612 | |
| 613 | |
| 614 | |
| 615 | |
| 616 | |
| 617 | |
| 618 | |
| 619 | |
| 620 | |
| 621 | |
| 622 | template <typename T> |
| 623 | ProgramStateRef set(ProgramStateRef st, typename ProgramStateTrait<T>::data_type D) { |
| 624 | return addGDM(st, ProgramStateTrait<T>::GDMIndex(), |
| 625 | ProgramStateTrait<T>::MakeVoidPtr(D)); |
| 626 | } |
| 627 | |
| 628 | template<typename T> |
| 629 | ProgramStateRef set(ProgramStateRef st, |
| 630 | typename ProgramStateTrait<T>::key_type K, |
| 631 | typename ProgramStateTrait<T>::value_type V, |
| 632 | typename ProgramStateTrait<T>::context_type C) { |
| 633 | |
| 634 | return addGDM(st, ProgramStateTrait<T>::GDMIndex(), |
| 635 | ProgramStateTrait<T>::MakeVoidPtr(ProgramStateTrait<T>::Set(st->get<T>(), K, V, C))); |
| 636 | } |
| 637 | |
| 638 | template <typename T> |
| 639 | ProgramStateRef add(ProgramStateRef st, |
| 640 | typename ProgramStateTrait<T>::key_type K, |
| 641 | typename ProgramStateTrait<T>::context_type C) { |
| 642 | return addGDM(st, ProgramStateTrait<T>::GDMIndex(), |
| 643 | ProgramStateTrait<T>::MakeVoidPtr(ProgramStateTrait<T>::Add(st->get<T>(), K, C))); |
| 644 | } |
| 645 | |
| 646 | template <typename T> |
| 647 | ProgramStateRef remove(ProgramStateRef st, |
| 648 | typename ProgramStateTrait<T>::key_type K, |
| 649 | typename ProgramStateTrait<T>::context_type C) { |
| 650 | |
| 651 | return addGDM(st, ProgramStateTrait<T>::GDMIndex(), |
| 652 | ProgramStateTrait<T>::MakeVoidPtr(ProgramStateTrait<T>::Remove(st->get<T>(), K, C))); |
| 653 | } |
| 654 | |
| 655 | template <typename T> |
| 656 | ProgramStateRef remove(ProgramStateRef st) { |
| 657 | return removeGDM(st, ProgramStateTrait<T>::GDMIndex()); |
| 658 | } |
| 659 | |
| 660 | void *FindGDMContext(void *index, |
| 661 | void *(*CreateContext)(llvm::BumpPtrAllocator&), |
| 662 | void (*DeleteContext)(void*)); |
| 663 | |
| 664 | template <typename T> |
| 665 | typename ProgramStateTrait<T>::context_type get_context() { |
| 666 | void *p = FindGDMContext(ProgramStateTrait<T>::GDMIndex(), |
| 667 | ProgramStateTrait<T>::CreateContext, |
| 668 | ProgramStateTrait<T>::DeleteContext); |
| 669 | |
| 670 | return ProgramStateTrait<T>::MakeContext(p); |
| 671 | } |
| 672 | |
| 673 | void EndPath(ProgramStateRef St) { |
| 674 | ConstraintMgr->EndPath(St); |
| 675 | } |
| 676 | }; |
| 677 | |
| 678 | |
| 679 | |
| 680 | |
| 681 | |
| 682 | |
| 683 | inline ConstraintManager &ProgramState::getConstraintManager() const { |
| 684 | return stateMgr->getConstraintManager(); |
| 685 | } |
| 686 | |
| 687 | inline const VarRegion* ProgramState::getRegion(const VarDecl *D, |
| 688 | const LocationContext *LC) const |
| 689 | { |
| 690 | return getStateManager().getRegionManager().getVarRegion(D, LC); |
| 691 | } |
| 692 | |
| 693 | inline ProgramStateRef ProgramState::assume(DefinedOrUnknownSVal Cond, |
| 694 | bool Assumption) const { |
| 695 | if (Cond.isUnknown()) |
| 696 | return this; |
| 697 | |
| 698 | return getStateManager().ConstraintMgr |
| 699 | ->assume(this, Cond.castAs<DefinedSVal>(), Assumption); |
| 700 | } |
| 701 | |
| 702 | inline std::pair<ProgramStateRef , ProgramStateRef > |
| 703 | ProgramState::assume(DefinedOrUnknownSVal Cond) const { |
| 704 | if (Cond.isUnknown()) |
| 705 | return std::make_pair(this, this); |
| 706 | |
| 707 | return getStateManager().ConstraintMgr |
| 708 | ->assumeDual(this, Cond.castAs<DefinedSVal>()); |
| 709 | } |
| 710 | |
| 711 | inline ProgramStateRef ProgramState::assumeInclusiveRange( |
| 712 | DefinedOrUnknownSVal Val, const llvm::APSInt &From, const llvm::APSInt &To, |
| 713 | bool Assumption) const { |
| 714 | if (Val.isUnknown()) |
| 715 | return this; |
| 716 | |
| 717 | (0) . __assert_fail ("Val.getAs() && \"Only NonLocs are supported!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h", 717, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true">assert(Val.getAs<NonLoc>() && "Only NonLocs are supported!"); |
| 718 | |
| 719 | return getStateManager().ConstraintMgr->assumeInclusiveRange( |
| 720 | this, Val.castAs<NonLoc>(), From, To, Assumption); |
| 721 | } |
| 722 | |
| 723 | inline std::pair<ProgramStateRef, ProgramStateRef> |
| 724 | ProgramState::assumeInclusiveRange(DefinedOrUnknownSVal Val, |
| 725 | const llvm::APSInt &From, |
| 726 | const llvm::APSInt &To) const { |
| 727 | if (Val.isUnknown()) |
| 728 | return std::make_pair(this, this); |
| 729 | |
| 730 | (0) . __assert_fail ("Val.getAs() && \"Only NonLocs are supported!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h", 730, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true">assert(Val.getAs<NonLoc>() && "Only NonLocs are supported!"); |
| 731 | |
| 732 | return getStateManager().ConstraintMgr->assumeInclusiveRangeDual( |
| 733 | this, Val.castAs<NonLoc>(), From, To); |
| 734 | } |
| 735 | |
| 736 | inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V, const LocationContext *LCtx) const { |
| 737 | if (Optional<Loc> L = LV.getAs<Loc>()) |
| 738 | return bindLoc(*L, V, LCtx); |
| 739 | return this; |
| 740 | } |
| 741 | |
| 742 | inline Loc ProgramState::getLValue(const CXXBaseSpecifier &BaseSpec, |
| 743 | const SubRegion *Super) const { |
| 744 | const auto *Base = BaseSpec.getType()->getAsCXXRecordDecl(); |
| 745 | return loc::MemRegionVal( |
| 746 | getStateManager().getRegionManager().getCXXBaseObjectRegion( |
| 747 | Base, Super, BaseSpec.isVirtual())); |
| 748 | } |
| 749 | |
| 750 | inline Loc ProgramState::getLValue(const CXXRecordDecl *BaseClass, |
| 751 | const SubRegion *Super, |
| 752 | bool IsVirtual) const { |
| 753 | return loc::MemRegionVal( |
| 754 | getStateManager().getRegionManager().getCXXBaseObjectRegion( |
| 755 | BaseClass, Super, IsVirtual)); |
| 756 | } |
| 757 | |
| 758 | inline Loc ProgramState::getLValue(const VarDecl *VD, |
| 759 | const LocationContext *LC) const { |
| 760 | return getStateManager().StoreMgr->getLValueVar(VD, LC); |
| 761 | } |
| 762 | |
| 763 | inline Loc ProgramState::getLValue(const CompoundLiteralExpr *literal, |
| 764 | const LocationContext *LC) const { |
| 765 | return getStateManager().StoreMgr->getLValueCompoundLiteral(literal, LC); |
| 766 | } |
| 767 | |
| 768 | inline SVal ProgramState::getLValue(const ObjCIvarDecl *D, SVal Base) const { |
| 769 | return getStateManager().StoreMgr->getLValueIvar(D, Base); |
| 770 | } |
| 771 | |
| 772 | inline SVal ProgramState::getLValue(const FieldDecl *D, SVal Base) const { |
| 773 | return getStateManager().StoreMgr->getLValueField(D, Base); |
| 774 | } |
| 775 | |
| 776 | inline SVal ProgramState::getLValue(const IndirectFieldDecl *D, |
| 777 | SVal Base) const { |
| 778 | StoreManager &SM = *getStateManager().StoreMgr; |
| 779 | for (const auto *I : D->chain()) { |
| 780 | Base = SM.getLValueField(cast<FieldDecl>(I), Base); |
| 781 | } |
| 782 | |
| 783 | return Base; |
| 784 | } |
| 785 | |
| 786 | inline SVal ProgramState::getLValue(QualType ElementType, SVal Idx, SVal Base) const{ |
| 787 | if (Optional<NonLoc> N = Idx.getAs<NonLoc>()) |
| 788 | return getStateManager().StoreMgr->getLValueElement(ElementType, *N, Base); |
| 789 | return UnknownVal(); |
| 790 | } |
| 791 | |
| 792 | inline SVal ProgramState::getSVal(const Stmt *Ex, |
| 793 | const LocationContext *LCtx) const{ |
| 794 | return Env.getSVal(EnvironmentEntry(Ex, LCtx), |
| 795 | *getStateManager().svalBuilder); |
| 796 | } |
| 797 | |
| 798 | inline SVal |
| 799 | ProgramState::getSValAsScalarOrLoc(const Stmt *S, |
| 800 | const LocationContext *LCtx) const { |
| 801 | if (const Expr *Ex = dyn_cast<Expr>(S)) { |
| 802 | QualType T = Ex->getType(); |
| 803 | if (Ex->isGLValue() || Loc::isLocType(T) || |
| 804 | T->isIntegralOrEnumerationType()) |
| 805 | return getSVal(S, LCtx); |
| 806 | } |
| 807 | |
| 808 | return UnknownVal(); |
| 809 | } |
| 810 | |
| 811 | inline SVal ProgramState::getRawSVal(Loc LV, QualType T) const { |
| 812 | return getStateManager().StoreMgr->getBinding(getStore(), LV, T); |
| 813 | } |
| 814 | |
| 815 | inline SVal ProgramState::getSVal(const MemRegion* R, QualType T) const { |
| 816 | return getStateManager().StoreMgr->getBinding(getStore(), |
| 817 | loc::MemRegionVal(R), |
| 818 | T); |
| 819 | } |
| 820 | |
| 821 | inline BasicValueFactory &ProgramState::getBasicVals() const { |
| 822 | return getStateManager().getBasicVals(); |
| 823 | } |
| 824 | |
| 825 | inline SymbolManager &ProgramState::getSymbolManager() const { |
| 826 | return getStateManager().getSymbolManager(); |
| 827 | } |
| 828 | |
| 829 | template<typename T> |
| 830 | ProgramStateRef ProgramState::add(typename ProgramStateTrait<T>::key_type K) const { |
| 831 | return getStateManager().add<T>(this, K, get_context<T>()); |
| 832 | } |
| 833 | |
| 834 | template <typename T> |
| 835 | typename ProgramStateTrait<T>::context_type ProgramState::get_context() const { |
| 836 | return getStateManager().get_context<T>(); |
| 837 | } |
| 838 | |
| 839 | template<typename T> |
| 840 | ProgramStateRef ProgramState::remove(typename ProgramStateTrait<T>::key_type K) const { |
| 841 | return getStateManager().remove<T>(this, K, get_context<T>()); |
| 842 | } |
| 843 | |
| 844 | template<typename T> |
| 845 | ProgramStateRef ProgramState::remove(typename ProgramStateTrait<T>::key_type K, |
| 846 | typename ProgramStateTrait<T>::context_type C) const { |
| 847 | return getStateManager().remove<T>(this, K, C); |
| 848 | } |
| 849 | |
| 850 | template <typename T> |
| 851 | ProgramStateRef ProgramState::remove() const { |
| 852 | return getStateManager().remove<T>(this); |
| 853 | } |
| 854 | |
| 855 | template<typename T> |
| 856 | ProgramStateRef ProgramState::set(typename ProgramStateTrait<T>::data_type D) const { |
| 857 | return getStateManager().set<T>(this, D); |
| 858 | } |
| 859 | |
| 860 | template<typename T> |
| 861 | ProgramStateRef ProgramState::set(typename ProgramStateTrait<T>::key_type K, |
| 862 | typename ProgramStateTrait<T>::value_type E) const { |
| 863 | return getStateManager().set<T>(this, K, E, get_context<T>()); |
| 864 | } |
| 865 | |
| 866 | template<typename T> |
| 867 | ProgramStateRef ProgramState::set(typename ProgramStateTrait<T>::key_type K, |
| 868 | typename ProgramStateTrait<T>::value_type E, |
| 869 | typename ProgramStateTrait<T>::context_type C) const { |
| 870 | return getStateManager().set<T>(this, K, E, C); |
| 871 | } |
| 872 | |
| 873 | template <typename CB> |
| 874 | CB ProgramState::scanReachableSymbols(SVal val) const { |
| 875 | CB cb(this); |
| 876 | scanReachableSymbols(val, cb); |
| 877 | return cb; |
| 878 | } |
| 879 | |
| 880 | template <typename CB> |
| 881 | CB ProgramState::scanReachableSymbols( |
| 882 | llvm::iterator_range<region_iterator> Reachable) const { |
| 883 | CB cb(this); |
| 884 | scanReachableSymbols(Reachable, cb); |
| 885 | return cb; |
| 886 | } |
| 887 | |
| 888 | |
| 889 | |
| 890 | |
| 891 | |
| 892 | class ScanReachableSymbols { |
| 893 | typedef llvm::DenseSet<const void*> VisitedItems; |
| 894 | |
| 895 | VisitedItems visited; |
| 896 | ProgramStateRef state; |
| 897 | SymbolVisitor &visitor; |
| 898 | public: |
| 899 | ScanReachableSymbols(ProgramStateRef st, SymbolVisitor &v) |
| 900 | : state(std::move(st)), visitor(v) {} |
| 901 | |
| 902 | bool scan(nonloc::LazyCompoundVal val); |
| 903 | bool scan(nonloc::CompoundVal val); |
| 904 | bool scan(SVal val); |
| 905 | bool scan(const MemRegion *R); |
| 906 | bool scan(const SymExpr *sym); |
| 907 | }; |
| 908 | |
| 909 | } |
| 910 | |
| 911 | } |
| 912 | |
| 913 | #endif |
| 914 | |