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 | |