clang: lib/StaticAnalyzer/Core/ProgramState.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
21#include "llvm/Support/raw_ostream.h"
22#include
23
24using namespace clang;
25using namespace ento;
26
27namespace clang { namespace ento {
28
29
32}
33
34
36 assert(state->refCount > 0);
38 if (--s->refCount == 0) {
40 Mgr.StateSet.RemoveNode(s);
41 s->~ProgramState();
42 Mgr.freeStates.push_back(s);
43 }
44}
45}}
46
49 : stateMgr(mgr),
51 store(st.getStore()),
52 GDM(gdm),
53 refCount(0) {
55}
56
58 : stateMgr(RHS.stateMgr), Env(RHS.Env), store(RHS.store), GDM(RHS.GDM),
59 PosteriorlyOverconstrained(RHS.PosteriorlyOverconstrained), refCount(0) {
61}
62
64 if (store)
66}
67
70}
71
75 llvm::BumpPtrAllocator &alloc,
77 : Eng(ExprEng), EnvMgr(alloc), GDMFactory(alloc),
80 StoreMgr = (*CreateSMgr)(*this);
81 ConstraintMgr = (*CreateCMgr)(*this, ExprEng);
82}
83
84
86 for (GDMContextsTy::iterator I=GDMContexts.begin(), E=GDMContexts.end();
87 I!=E; ++I)
88 I->second.second(I->second.first);
89}
90
94
95
96
97
98
99
100
102
103 NewState.Env = EnvMgr.removeDeadBindings(NewState.Env, SymReaper, state);
104
105
106 StoreRef newStore = StoreMgr->removeDeadBindings(NewState.getStore(), LCtx,
107 SymReaper);
108 NewState.setStore(newStore);
110
112}
113
117 bool notifyChanges) const {
120 LV, V));
122 if (MR && notifyChanges)
124
125 return newState;
126}
127
133 const StoreRef &newStore = Mgr.StoreMgr->BindDefaultInitial(getStore(), R, V);
136}
137
142 const StoreRef &newStore = Mgr.StoreMgr->BindDefaultZero(getStore(), R);
145}
146
149
156 for (const MemRegion *Reg : Regions)
158
159 return invalidateRegions(Values, S, Count, LCtx, CausedByPointerEscape, IS,
160 Call, ITraits);
161}
162
168
171
173 if (!IS)
174 IS = &InvalidatedSyms;
175
177 if (!ITraits)
178 ITraits = &ITraitsLocal;
179
182 const StoreRef &NewStore = Mgr.StoreMgr->invalidateRegions(
183 getStore(), Values, S, Count, LCtx, Call, *IS, *ITraits,
184 &TopLevelInvalidated, &Invalidated);
185
187
188 if (CausedByPointerEscape) {
190 NewState, IS, TopLevelInvalidated, Call, *ITraits);
191 }
192
194 Invalidated, LCtx, Call);
195}
196
201
202 if (newStore.getStore() == OldStore)
203 return this;
204
205 return makeWithStore(newStore);
206}
207
208
209
210
211SVal ProgramState::desugarReference(SVal Val) const {
212 const auto *TyReg = dyn_cast_or_null(Val.getAsRegion());
213 if (!TyReg || !TyReg->getValueType()->isReferenceType())
214 return Val;
216}
217
218
219
220
221
222SVal ProgramState::wrapSymbolicRegion(SVal Val) const {
223 const auto *BaseReg = dyn_cast_or_null(Val.getAsRegion());
224 if (!BaseReg)
225 return Val;
226
228 QualType ElemTy = BaseReg->getPointeeStaticType();
230}
231
237 return makeWithStore(NewStore);
238}
239
242 if (!SelfDecl)
243 return SVal();
245}
246
248
249
250
253
254 if (const TypedValueRegion *TR = dyn_cast(R)) {
258 }
259
261}
262
265
266
267
268
269
270
271
273 if (SymbolRef sym = V.getAsSymbol()) {
276 .getSymVal(this, sym)) {
277
278
279
280
281
282
283
284
285
286
287
288
289
290
295 }
296 }
297 }
298
299 return V;
300}
301
304 SVal V, bool Invalidate) const{
307 Invalidate);
308 if (NewEnv == Env)
309 return this;
310
312 NewSt.Env = NewEnv;
314}
315
316[[nodiscard]] std::pair<ProgramStateRef, ProgramStateRef>
321 return {this, this};
322
323
324
325
329
330
332 if (indexTy.isNull())
335
336
340 return {this, this};
341
342
343 SVal newBound =
345 Min, indexTy);
346
348 return {this, this};
349
350
354 return {this, this};
355
356
359}
360
363 bool Assumption,
365 std::pair<ProgramStateRef, ProgramStateRef> R =
367 return Assumption ? R.first : R.second;
368}
369
372 if (IsNull.isUnderconstrained())
375}
376
379}
380
382 if (V.isZeroConstant())
383 return true;
384
385 if (V.isConstant())
386 return false;
387
388 SymbolRef Sym = V.getAsSymbol( true);
389 if (!Sym)
391
392 return getStateManager().ConstraintMgr->isNull(this, Sym);
393}
394
398 StoreMgr->getInitialStore(InitLoc),
399 GDMFactory.getEmptyMap());
400
402}
403
408 NewState.GDM = GDMState->GDM;
410}
411
413
414 llvm::FoldingSetNodeID ID;
415 State.Profile(ID);
416 void *InsertPos;
417
418 if (ProgramState *I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
419 return I;
420
422 if (!freeStates.empty()) {
423 newState = freeStates.back();
424 freeStates.pop_back();
425 }
426 else {
428 }
430 StateSet.InsertNode(newState, InsertPos);
431 return newState;
432}
433
436 NewSt.setStore(store);
438}
439
440ProgramStateRef ProgramState::cloneAsPosteriorlyOverconstrained() const {
442 NewSt.PosteriorlyOverconstrained = true;
444}
445
446void ProgramState::setStore(const StoreRef &newStore) {
448 if (newStoreStore)
450 if (store)
452 store = newStoreStore;
453}
454
456 Base = desugarReference(Base);
457 Base = wrapSymbolicRegion(Base);
459}
460
463 Base = desugarReference(Base);
464 Base = wrapSymbolicRegion(Base);
465
466
467
468
469 for (const auto *I : D->chain()) {
470 Base = SM.getLValueField(cast(I), Base);
471 }
473}
474
475
476
477
478
480 const char *NL, unsigned int Space,
481 bool IsDot) const {
482 Indent(Out, Space, IsDot) << "\"program_state\": {" << NL;
483 ++Space;
484
486
487
489
490
492
493
495
496
498
499
501
502 --Space;
503 Indent(Out, Space, IsDot) << '}';
504}
505
507 unsigned int Space) const {
508 printJson(Out, LCtx, "\\l", Space, true);
509}
510
513}
514
517}
518
519
520
521
522
524 return GDM.lookup(K);
525}
526
527void*
529 void *(*CreateContext)(llvm::BumpPtrAllocator&),
530 void (*DeleteContext)(void*)) {
531
532 std::pair<void*, void (*)(void*)>& p = GDMContexts[K];
533 if (!p.first) {
534 p.first = CreateContext(Alloc);
535 p.second = DeleteContext;
536 }
537
538 return p.first;
539}
540
544
545 if (M1 == M2)
546 return St;
547
549 NewSt.GDM = M2;
551}
552
556
557 if (NewM == OldM)
558 return state;
559
561 NewState.GDM = NewM;
563}
564
566 bool wasVisited = !visited.insert(val.getCVData()).second;
567 if (wasVisited)
568 return true;
569
570 StoreManager &StoreMgr = state->getStateManager().getStoreManager();
571
572
573
576}
577
581 return false;
582
583 return true;
584}
585
588 bool wasVisited = !visited.insert(SubSym).second;
589 if (wasVisited)
590 continue;
591
593 return false;
594 }
595
596 return true;
597}
598
601 return scan(X->getRegion());
602
603 if (std::optionalnonloc::LazyCompoundVal X =
606
609
611 return scan(Sym);
612
615
616 return true;
617}
618
620 if (isa(R))
621 return true;
622
623 bool wasVisited = !visited.insert(R).second;
624 if (wasVisited)
625 return true;
626
628 return false;
629
630
631 if (const SymbolicRegion *SR = dyn_cast(R))
632 if (!visitor.VisitSymbol(SR->getSymbol()))
633 return false;
634
635
636 if (const SubRegion *SR = dyn_cast(R)) {
637 const MemRegion *Super = SR->getSuperRegion();
638 if ((Super))
639 return false;
640
641
642 if (isa(Super)) {
643 StoreManager &StoreMgr = state->getStateManager().getStoreManager();
645 return false;
646 }
647 }
648
649
650 if (const BlockDataRegion *BDR = dyn_cast(R)) {
651 for (auto Var : BDR->referenced_vars()) {
652 if ((Var.getCapturedRegion()))
653 return false;
654 }
655 }
656
657 return true;
658}
659
662 return S.scan(val);
663}
664
666 llvm::iterator_range<region_iterator> Reachable,
669 for (const MemRegion *R : Reachable) {
670 if (!S.scan(R))
671 return false;
672 }
673 return true;
674}
ArrayRef< const MemRegion * > RegionList
ArrayRef< SVal > ValueList
__device__ __2f16 float __ockl_bool s
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Represents a member of a struct/union/class.
Represents a field injected from an anonymous union/struct into the parent scope.
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
const ImplicitParamDecl * getSelfDecl() const
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
It represents a stack frame of the call stack (based on CallEvent).
Stmt - This represents one statement.
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
A safe wrapper around APSInt objects allocated and owned by BasicValueFactory.
APSIntPtr getMinValue(const llvm::APSInt &v)
APSIntPtr Convert(const llvm::APSInt &To, const llvm::APSInt &From)
Convert - Create a new persistent APSInt with the same value as 'From' but with the bitwidth and sign...
BlockDataRegion - A region that represents a block instance.
Manages the lifetime of CallEvent objects.
Represents an abstract call to a function or method along a particular path.
ProgramStatePair assumeDual(ProgramStateRef State, DefinedSVal Cond)
Returns a pair of states (StTrue, StFalse) where the given condition is assumed to be true or false,...
virtual void printJson(raw_ostream &Out, ProgramStateRef State, const char *NL, unsigned int Space, bool IsDot) const =0
An entry in the environment consists of a Stmt and an LocationContext.
Environment getInitialEnvironment()
Environment bindExpr(Environment Env, const EnvironmentEntry &E, SVal V, bool Invalidate)
Bind a symbolic value to the given environment entry.
Environment removeDeadBindings(Environment Env, SymbolReaper &SymReaper, ProgramStateRef state)
An immutable map from EnvironemntEntries to SVals.
void printJson(raw_ostream &Out, const ASTContext &Ctx, const LocationContext *LCtx=nullptr, const char *NL="\n", unsigned int Space=0, bool IsDot=false) const
ProgramStateRef processRegionChange(ProgramStateRef state, const MemRegion *MR, const LocationContext *LCtx)
void printJson(raw_ostream &Out, ProgramStateRef State, const LocationContext *LCtx, const char *NL, unsigned int Space, bool IsDot) const
printJson - Called by ProgramStateManager to print checker-specific data.
ProgramStateRef processRegionChanges(ProgramStateRef state, const InvalidatedSymbols *invalidated, ArrayRef< const MemRegion * > ExplicitRegions, ArrayRef< const MemRegion * > Regions, const LocationContext *LCtx, const CallEvent *Call)
processRegionChanges - Called by ProgramStateManager whenever a change is made to the store.
ProgramStateRef notifyCheckersOfPointerEscape(ProgramStateRef State, const InvalidatedSymbols *Invalidated, ArrayRef< const MemRegion * > ExplicitRegions, const CallEvent *Call, RegionAndSymbolInvalidationTraits &ITraits)
Call PointerEscape callback when a value escapes as a result of region invalidation.
AnalysisManager & getAnalysisManager()
static bool isLocType(QualType T)
MemRegion - The root abstract class for all memory regions.
virtual bool isBoundable() const
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
SValBuilder & getSValBuilder()
ProgramStateRef removeDeadBindingsFromEnvironmentAndStore(ProgramStateRef St, const StackFrameContext *LCtx, SymbolReaper &SymReaper)
ExprEngine & getOwningEngine()
ProgramStateRef removeGDM(ProgramStateRef state, void *Key)
void * FindGDMContext(void *index, void *(*CreateContext)(llvm::BumpPtrAllocator &), void(*DeleteContext)(void *))
friend class ProgramState
ASTContext & getContext()
ProgramStateRef getPersistentStateWithGDM(ProgramStateRef FromState, ProgramStateRef GDMState)
ProgramStateRef addGDM(ProgramStateRef St, void *Key, void *Data)
ProgramStateRef getPersistentState(ProgramState &Impl)
ProgramStateRef getInitialState(const LocationContext *InitLoc)
StoreManager & getStoreManager()
ProgramStateManager(ASTContext &Ctx, StoreManagerCreator CreateStoreManager, ConstraintManagerCreator CreateConstraintManager, llvm::BumpPtrAllocator &alloc, ExprEngine *expreng)
ConstraintManager & getConstraintManager()
ProgramState - This class encapsulates:
bool scanReachableSymbols(SVal val, SymbolVisitor &visitor) const
Visits the symbols reachable from the given SVal using the provided SymbolVisitor.
Loc getLValue(const CXXBaseSpecifier &BaseSpec, const SubRegion *Super) const
Get the lvalue for a base class object reference.
ProgramStateRef bindDefaultZero(SVal loc, const LocationContext *LCtx) const
Performs C++ zero-initialization procedure on the region of memory represented by loc.
llvm::ImmutableMap< void *, void * > GenericDataMap
ProgramStateRef BindExpr(const Stmt *S, const LocationContext *LCtx, SVal V, bool Invalidate=true) const
Create a new state by binding the value 'V' to the statement 'S' in the state's environment.
void printJson(raw_ostream &Out, const LocationContext *LCtx=nullptr, const char *NL="\n", unsigned int Space=0, bool IsDot=false) const
ProgramStateRef bindDefaultInitial(SVal loc, SVal V, const LocationContext *LCtx) const
Initializes the region of memory represented by loc with an initial value.
ConstraintManager & getConstraintManager() const
Return the ConstraintManager.
SVal getSValAsScalarOrLoc(const Stmt *Ex, const LocationContext *LCtx) const
ProgramStateRef invalidateRegions(ArrayRef< const MemRegion * > Regions, const Stmt *S, unsigned BlockCount, const LocationContext *LCtx, bool CausesPointerEscape, InvalidatedSymbols *IS=nullptr, const CallEvent *Call=nullptr, RegionAndSymbolInvalidationTraits *ITraits=nullptr) const
Returns the state with bindings for the given regions cleared from the store.
SVal getSelfSVal(const LocationContext *LC) const
Return the value of 'self' if available in the given context.
SVal getRawSVal(Loc LV, QualType T=QualType()) const
Returns the "raw" SVal bound to LV before any value simplfication.
ConditionTruthVal isNull(SVal V) const
Check if the given SVal is constrained to zero or is a zero constant.
ProgramStateManager & getStateManager() const
Return the ProgramStateManager associated with this state.
ProgramStateRef killBinding(Loc LV) const
ProgramState(ProgramStateManager *mgr, const Environment &env, StoreRef st, GenericDataMap gdm)
This ctor is used when creating the first ProgramState object.
Store getStore() const
Return the store associated with this state.
ConditionTruthVal areEqual(SVal Lhs, SVal Rhs) const
void printDOT(raw_ostream &Out, const LocationContext *LCtx=nullptr, unsigned int Space=0) const
ConditionTruthVal isNonNull(SVal V) const
Check if the given SVal is not constrained to zero and is not a zero constant.
ProgramStateRef assumeInBound(DefinedOrUnknownSVal idx, DefinedOrUnknownSVal upperBound, bool assumption, QualType IndexType=QualType()) const
ProgramStateRef enterStackFrame(const CallEvent &Call, const StackFrameContext *CalleeCtx) const
enterStackFrame - Returns the state for entry to the given stack frame, preserving the current state.
LLVM_ATTRIBUTE_RETURNS_NONNULL const VarRegion * getRegion(const VarDecl *D, const LocationContext *LC) const
Utility method for getting regions.
SVal getSVal(const Stmt *S, const LocationContext *LCtx) const
Returns the SVal bound to the statement 'S' in the state's environment.
ProgramStateRef bindLoc(Loc location, SVal V, const LocationContext *LCtx, bool notifyChanges=true) const
BasicValueFactory & getBasicVals() const
std::pair< ProgramStateRef, ProgramStateRef > assumeInBoundDual(DefinedOrUnknownSVal idx, DefinedOrUnknownSVal upperBound, QualType IndexType=QualType()) const
AnalysisManager & getAnalysisManager() const
void *const * FindGDM(void *K) const
Information about invalidation for a particular region/symbol.
BasicValueFactory & getBasicValueFactory()
ASTContext & getContext()
QualType getArrayIndexType() const
virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy)=0
Create a new value which represents a binary expression with two non- location operands.
ConditionTruthVal areEqual(ProgramStateRef state, SVal lhs, SVal rhs)
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
bool isUnknownOrUndef() const
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
const MemRegion * getAsRegion() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
A utility class that visits the reachable symbols using a custom SymbolVisitor.
bool scan(nonloc::LazyCompoundVal val)
virtual bool scanReachableSymbols(Store S, const MemRegion *R, ScanReachableSymbols &Visitor)=0
Finds the transitive closure of symbols within the given region.
virtual void decrementReferenceCount(Store store)
If the StoreManager supports it, decrement the reference count of the specified Store object.
virtual void incrementReferenceCount(Store store)
If the StoreManager supports it, increment the reference count of the specified Store object.
virtual void printJson(raw_ostream &Out, Store S, const char *NL, unsigned int Space, bool IsDot) const =0
SubRegion - A region that subsets another larger region.
llvm::iterator_range< symbol_iterator > symbols() const
A class responsible for cleaning up unused symbols.
void setReapedStore(StoreRef st)
Set to the value of the symbolic store after StoreManager::removeDeadBindings has been called.
virtual bool VisitMemRegion(const MemRegion *)
virtual bool VisitSymbol(SymbolRef sym)=0
A visitor method invoked by ProgramStateManager::scanReachableSymbols.
SymbolicRegion - A special, "non-concrete" region.
TypedValueRegion - An abstract class representing regions having a typed value.
The simplest example of a concrete compound value is nonloc::CompoundVal, which represents a concrete...
Value representing integer constant.
While nonloc::CompoundVal covers a few simple use cases, nonloc::LazyCompoundVal is a more performant...
LLVM_ATTRIBUTE_RETURNS_NONNULL const LazyCompoundValData * getCVData() const
LLVM_ATTRIBUTE_RETURNS_NONNULL const TypedValueRegion * getRegion() const
This function itself is immaterial.
const void * getStore() const
It might return null.
SValBuilder * createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context, ProgramStateManager &stateMgr)
void printDynamicTypeInfoJson(raw_ostream &Out, ProgramStateRef State, const char *NL="\n", unsigned int Space=0, bool IsDot=false)
std::unique_ptr< ConstraintManager >(* ConstraintManagerCreator)(ProgramStateManager &, ExprEngine *)
std::unique_ptr< StoreManager >(* StoreManagerCreator)(ProgramStateManager &)
llvm::DenseSet< SymbolRef > InvalidatedSymbols
const void * Store
Store - This opaque type encapsulates an immutable mapping from locations to values.
void ProgramStateRetain(const ProgramState *state)
Increments the number of times this state is referenced.
void ProgramStateRelease(const ProgramState *state)
Decrement the number of times this state is referenced.
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T