clang 22.0.0git
ProgramState.cpp
Go to the documentation of this file.
1//= ProgramState.cpp - 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 implements ProgramState and ProgramStateManager.
10//
11//===----------------------------------------------------------------------===//
12
14#include "clang/Analysis/CFG.h"
20#include "llvm/Support/raw_ostream.h"
21#include <optional>
22
23using namespace clang;
24using namespace ento;
25
26namespace clang { namespace ento {
27/// Increments the number of times this state is referenced.
28
29void ProgramStateRetain(const ProgramState *state) {
30 ++const_cast<ProgramState*>(state)->refCount;
31}
32
33/// Decrement the number of times this state is referenced.
35 assert(state->refCount > 0);
36 ProgramState *s = const_cast<ProgramState*>(state);
37 if (--s->refCount == 0) {
38 ProgramStateManager &Mgr = s->getStateManager();
39 Mgr.StateSet.RemoveNode(s);
40 s->~ProgramState();
41 Mgr.freeStates.push_back(s);
42 }
43}
44}}
45
48 : stateMgr(mgr),
49 Env(env),
50 store(st.getStore()),
51 GDM(gdm),
52 refCount(0) {
53 stateMgr->getStoreManager().incrementReferenceCount(store);
54}
55
57 : stateMgr(RHS.stateMgr), Env(RHS.Env), store(RHS.store), GDM(RHS.GDM),
58 PosteriorlyOverconstrained(RHS.PosteriorlyOverconstrained), refCount(0) {
59 stateMgr->getStoreManager().incrementReferenceCount(store);
60}
61
63 if (store)
64 stateMgr->getStoreManager().decrementReferenceCount(store);
65}
66
67int64_t ProgramState::getID() const {
68 return getStateManager().Alloc.identifyKnownAlignedObject<ProgramState>(this);
69}
70
72 StoreManagerCreator CreateSMgr,
73 ConstraintManagerCreator CreateCMgr,
74 llvm::BumpPtrAllocator &alloc,
75 ExprEngine *ExprEng)
76 : Eng(ExprEng), EnvMgr(alloc), GDMFactory(alloc),
77 svalBuilder(createSimpleSValBuilder(alloc, Ctx, *this)),
78 CallEventMgr(new CallEventManager(alloc)), Alloc(alloc) {
79 StoreMgr = (*CreateSMgr)(*this);
80 ConstraintMgr = (*CreateCMgr)(*this, ExprEng);
81}
82
83
85 for (GDMContextsTy::iterator I=GDMContexts.begin(), E=GDMContexts.end();
86 I!=E; ++I)
87 I->second.second(I->second.first);
88}
89
91 ProgramStateRef state, const StackFrameContext *LCtx,
92 SymbolReaper &SymReaper) {
93
94 // This code essentially performs a "mark-and-sweep" of the VariableBindings.
95 // The roots are any Block-level exprs and Decls that our liveness algorithm
96 // tells us are live. We then see what Decls they may reference, and keep
97 // those around. This code more than likely can be made faster, and the
98 // frequency of which this method is called should be experimented with
99 // for optimum performance.
100 ProgramState NewState = *state;
101
102 NewState.Env = EnvMgr.removeDeadBindings(NewState.Env, SymReaper, state);
103
104 // Clean up the store.
105 StoreRef newStore = StoreMgr->removeDeadBindings(NewState.getStore(), LCtx,
106 SymReaper);
107 NewState.setStore(newStore);
108 SymReaper.setReapedStore(newStore);
109
110 return getPersistentState(NewState);
111}
112
114 SVal V,
115 const LocationContext *LCtx,
116 bool notifyChanges) const {
118 ExprEngine &Eng = Mgr.getOwningEngine();
119 ProgramStateRef State = makeWithStore(Mgr.StoreMgr->Bind(getStore(), LV, V));
120 const MemRegion *MR = LV.getAsRegion();
121
122 if (MR && notifyChanges)
123 return Eng.processRegionChange(State, MR, LCtx);
124
125 return State;
126}
127
130 const LocationContext *LCtx) const {
132 const MemRegion *R = loc.castAs<loc::MemRegionVal>().getRegion();
133 BindResult BindRes = Mgr.StoreMgr->BindDefaultInitial(getStore(), R, V);
134 ProgramStateRef State = makeWithStore(BindRes);
135 return Mgr.getOwningEngine().processRegionChange(State, R, LCtx);
136}
137
141 const MemRegion *R = loc.castAs<loc::MemRegionVal>().getRegion();
142 BindResult BindRes = Mgr.StoreMgr->BindDefaultZero(getStore(), R);
143 ProgramStateRef State = makeWithStore(BindRes);
144 return Mgr.getOwningEngine().processRegionChange(State, R, LCtx);
145}
146
149
151 RegionList Regions, ConstCFGElementRef Elem, unsigned Count,
152 const LocationContext *LCtx, bool CausedByPointerEscape,
154 RegionAndSymbolInvalidationTraits *ITraits) const {
156 for (const MemRegion *Reg : Regions)
157 Values.push_back(loc::MemRegionVal(Reg));
158
159 return invalidateRegions(Values, Elem, Count, LCtx, CausedByPointerEscape, IS,
160 Call, ITraits);
161}
162
164 ValueList Values, ConstCFGElementRef Elem, unsigned Count,
165 const LocationContext *LCtx, bool CausedByPointerEscape,
167 RegionAndSymbolInvalidationTraits *ITraits) const {
168
170 ExprEngine &Eng = Mgr.getOwningEngine();
171
172 InvalidatedSymbols InvalidatedSyms;
173 if (!IS)
174 IS = &InvalidatedSyms;
175
176 RegionAndSymbolInvalidationTraits ITraitsLocal;
177 if (!ITraits)
178 ITraits = &ITraitsLocal;
179
180 StoreManager::InvalidatedRegions TopLevelInvalidated;
182 const StoreRef &NewStore = Mgr.StoreMgr->invalidateRegions(
183 getStore(), Values, Elem, Count, LCtx, Call, *IS, *ITraits,
184 &TopLevelInvalidated, &Invalidated);
185
186 ProgramStateRef NewState = makeWithStore(NewStore);
187
188 if (CausedByPointerEscape) {
189 NewState = Eng.notifyCheckersOfPointerEscape(
190 NewState, IS, TopLevelInvalidated, Call, *ITraits);
191 }
192
193 return Eng.processRegionChanges(NewState, IS, TopLevelInvalidated,
194 Invalidated, LCtx, Call);
195}
196
198 Store OldStore = getStore();
199 const StoreRef &newStore =
200 getStateManager().StoreMgr->killBinding(OldStore, LV);
201
202 if (newStore.getStore() == OldStore)
203 return this;
204
205 return makeWithStore(newStore);
206}
207
208/// We should never form a MemRegion that would wrap a TypedValueRegion of a
209/// reference type. What we actually wanted was to create a MemRegion refering
210/// to the pointee of that reference.
211SVal ProgramState::desugarReference(SVal Val) const {
212 const auto *TyReg = dyn_cast_or_null<TypedValueRegion>(Val.getAsRegion());
213 if (!TyReg || !TyReg->getValueType()->isReferenceType())
214 return Val;
215 return getSVal(TyReg);
216}
217
218/// SymbolicRegions are expected to be wrapped by an ElementRegion as a
219/// canonical representation. As a canonical representation, SymbolicRegions
220/// should be wrapped by ElementRegions before getting a FieldRegion.
221/// See f8643a9b31c4029942f67d4534c9139b45173504 why.
222SVal ProgramState::wrapSymbolicRegion(SVal Val) const {
223 const auto *BaseReg = dyn_cast_or_null<SymbolicRegion>(Val.getAsRegion());
224 if (!BaseReg)
225 return Val;
226
228 QualType ElemTy = BaseReg->getPointeeStaticType();
229 return loc::MemRegionVal{SM.GetElementZeroRegion(BaseReg, ElemTy)};
230}
231
234 const StackFrameContext *CalleeCtx) const {
235 return makeWithStore(
236 getStateManager().StoreMgr->enterStackFrame(getStore(), Call, CalleeCtx));
237}
238
240 const ImplicitParamDecl *SelfDecl = LCtx->getSelfDecl();
241 if (!SelfDecl)
242 return SVal();
243 return getSVal(getRegion(SelfDecl, LCtx));
244}
245
247 // We only want to do fetches from regions that we can actually bind
248 // values. For example, SymbolicRegions of type 'id<...>' cannot
249 // have direct bindings (but their can be bindings on their subregions).
250 if (!R->isBoundable())
251 return UnknownVal();
252
253 if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
254 QualType T = TR->getValueType();
255 if (Loc::isLocType(T) || T->isIntegralOrEnumerationType())
256 return getSVal(R);
257 }
258
259 return UnknownVal();
260}
261
263 SVal V = getRawSVal(location, T);
264
265 // If 'V' is a symbolic value that is *perfectly* constrained to
266 // be a constant value, use that value instead to lessen the burden
267 // on later analysis stages (so we have less symbolic values to reason
268 // about).
269 // We only go into this branch if we can convert the APSInt value we have
270 // to the type of T, which is not always the case (e.g. for void).
271 if (!T.isNull() && (T->isIntegralOrEnumerationType() || Loc::isLocType(T))) {
272 if (SymbolRef sym = V.getAsSymbol()) {
273 if (const llvm::APSInt *Int = getStateManager()
275 .getSymVal(this, sym)) {
276 // FIXME: Because we don't correctly model (yet) sign-extension
277 // and truncation of symbolic values, we need to convert
278 // the integer value to the correct signedness and bitwidth.
279 //
280 // This shows up in the following:
281 //
282 // char foo();
283 // unsigned x = foo();
284 // if (x == 54)
285 // ...
286 //
287 // The symbolic value stored to 'x' is actually the conjured
288 // symbol for the call to foo(); the type of that symbol is 'char',
289 // not unsigned.
290 APSIntPtr NewV = getBasicVals().Convert(T, *Int);
291 if (V.getAs<Loc>())
292 return loc::ConcreteInt(NewV);
293 return nonloc::ConcreteInt(NewV);
294 }
295 }
296 }
297
298 return V;
299}
300
302 const LocationContext *LCtx,
303 SVal V, bool Invalidate) const{
304 Environment NewEnv =
305 getStateManager().EnvMgr.bindExpr(Env, EnvironmentEntry(S, LCtx), V,
306 Invalidate);
307 if (NewEnv == Env)
308 return this;
309
310 ProgramState NewSt = *this;
311 NewSt.Env = NewEnv;
312 return getStateManager().getPersistentState(NewSt);
313}
314
315[[nodiscard]] std::pair<ProgramStateRef, ProgramStateRef>
317 DefinedOrUnknownSVal UpperBound,
318 QualType indexTy) const {
319 if (Idx.isUnknown() || UpperBound.isUnknown())
320 return {this, this};
321
322 // Build an expression for 0 <= Idx < UpperBound.
323 // This is the same as Idx + MIN < UpperBound + MIN, if overflow is allowed.
324 // FIXME: This should probably be part of SValBuilder.
326 SValBuilder &svalBuilder = SM.getSValBuilder();
327 ASTContext &Ctx = svalBuilder.getContext();
328
329 // Get the offset: the minimum value of the array index type.
330 BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
331 if (indexTy.isNull())
332 indexTy = svalBuilder.getArrayIndexType();
333 nonloc::ConcreteInt Min(BVF.getMinValue(indexTy));
334
335 // Adjust the index.
336 SVal newIdx = svalBuilder.evalBinOpNN(this, BO_Add,
337 Idx.castAs<NonLoc>(), Min, indexTy);
338 if (newIdx.isUnknownOrUndef())
339 return {this, this};
340
341 // Adjust the upper bound.
342 SVal newBound =
343 svalBuilder.evalBinOpNN(this, BO_Add, UpperBound.castAs<NonLoc>(),
344 Min, indexTy);
345
346 if (newBound.isUnknownOrUndef())
347 return {this, this};
348
349 // Build the actual comparison.
350 SVal inBound = svalBuilder.evalBinOpNN(this, BO_LT, newIdx.castAs<NonLoc>(),
351 newBound.castAs<NonLoc>(), Ctx.IntTy);
352 if (inBound.isUnknownOrUndef())
353 return {this, this};
354
355 // Finally, let the constraint manager take care of it.
356 ConstraintManager &CM = SM.getConstraintManager();
357 return CM.assumeDual(this, inBound.castAs<DefinedSVal>());
358}
359
361 DefinedOrUnknownSVal UpperBound,
362 bool Assumption,
363 QualType indexTy) const {
364 std::pair<ProgramStateRef, ProgramStateRef> R =
365 assumeInBoundDual(Idx, UpperBound, indexTy);
366 return Assumption ? R.first : R.second;
367}
368
371 if (IsNull.isUnderconstrained())
372 return IsNull;
373 return ConditionTruthVal(!IsNull.getValue());
374}
375
377 return stateMgr->getSValBuilder().areEqual(this, Lhs, Rhs);
378}
379
381 if (V.isZeroConstant())
382 return true;
383
384 if (V.isConstant())
385 return false;
386
387 SymbolRef Sym = V.getAsSymbol(/* IncludeBaseRegion */ true);
388 if (!Sym)
389 return ConditionTruthVal();
390
391 return getStateManager().ConstraintMgr->isNull(this, Sym);
392}
393
395 ProgramState State(this,
396 EnvMgr.getInitialEnvironment(),
397 StoreMgr->getInitialStore(InitLoc),
398 GDMFactory.getEmptyMap());
399
400 return getPersistentState(State);
401}
402
404 ProgramStateRef FromState,
405 ProgramStateRef GDMState) {
406 ProgramState NewState(*FromState);
407 NewState.GDM = GDMState->GDM;
408 return getPersistentState(NewState);
409}
410
412
413 llvm::FoldingSetNodeID ID;
414 State.Profile(ID);
415 void *InsertPos;
416
417 if (ProgramState *I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
418 return I;
419
420 ProgramState *newState = nullptr;
421 if (!freeStates.empty()) {
422 newState = freeStates.back();
423 freeStates.pop_back();
424 }
425 else {
426 newState = Alloc.Allocate<ProgramState>();
427 }
428 new (newState) ProgramState(State);
429 StateSet.InsertNode(newState, InsertPos);
430 return newState;
431}
432
433ProgramStateRef ProgramState::makeWithStore(const StoreRef &store) const {
434 ProgramState NewSt(*this);
435 NewSt.setStore(store);
436 return getStateManager().getPersistentState(NewSt);
437}
438
439ProgramStateRef ProgramState::makeWithStore(const BindResult &BindRes) const {
441 ProgramStateRef State = makeWithStore(BindRes.ResultingStore);
442
443 // We must always notify the checkers for failing binds because otherwise they
444 // may keep stale traits for these symbols.
445 // Eg., Malloc checker may report leaks if we failed to bind that symbol.
446 if (BindRes.FailedToBindValues.empty())
447 return State;
448 return Eng.escapeValues(State, BindRes.FailedToBindValues, PSK_EscapeOnBind);
449}
450
451ProgramStateRef ProgramState::cloneAsPosteriorlyOverconstrained() const {
452 ProgramState NewSt(*this);
453 NewSt.PosteriorlyOverconstrained = true;
454 return getStateManager().getPersistentState(NewSt);
455}
456
457void ProgramState::setStore(const StoreRef &newStore) {
458 Store newStoreStore = newStore.getStore();
459 if (newStoreStore)
460 stateMgr->getStoreManager().incrementReferenceCount(newStoreStore);
461 if (store)
462 stateMgr->getStoreManager().decrementReferenceCount(store);
463 store = newStoreStore;
464}
465
467 Base = desugarReference(Base);
468 Base = wrapSymbolicRegion(Base);
469 return getStateManager().StoreMgr->getLValueField(D, Base);
470}
471
473 StoreManager &SM = *getStateManager().StoreMgr;
474 Base = desugarReference(Base);
475 Base = wrapSymbolicRegion(Base);
476
477 // FIXME: This should work with `SM.getLValueField(D->getAnonField(), Base)`,
478 // but that would break some tests. There is probably a bug somewhere that it
479 // would expose.
480 for (const auto *I : D->chain()) {
481 Base = SM.getLValueField(cast<FieldDecl>(I), Base);
482 }
483 return Base;
484}
485
486//===----------------------------------------------------------------------===//
487// State pretty-printing.
488//===----------------------------------------------------------------------===//
489
490void ProgramState::printJson(raw_ostream &Out, const LocationContext *LCtx,
491 const char *NL, unsigned int Space,
492 bool IsDot) const {
493 Indent(Out, Space, IsDot) << "\"program_state\": {" << NL;
494 ++Space;
495
497
498 // Print the store.
499 Mgr.getStoreManager().printJson(Out, getStore(), NL, Space, IsDot);
500
501 // Print out the environment.
502 Env.printJson(Out, Mgr.getContext(), LCtx, NL, Space, IsDot);
503
504 // Print out the constraints.
505 Mgr.getConstraintManager().printJson(Out, this, NL, Space, IsDot);
506
507 // Print out the tracked dynamic types.
508 printDynamicTypeInfoJson(Out, this, NL, Space, IsDot);
509
510 // Print checker-specific data.
511 Mgr.getOwningEngine().printJson(Out, this, LCtx, NL, Space, IsDot);
512
513 --Space;
514 Indent(Out, Space, IsDot) << '}';
515}
516
517void ProgramState::printDOT(raw_ostream &Out, const LocationContext *LCtx,
518 unsigned int Space) const {
519 printJson(Out, LCtx, /*NL=*/"\\l", Space, /*IsDot=*/true);
520}
521
522LLVM_DUMP_METHOD void ProgramState::dump() const {
523 printJson(llvm::errs());
524}
525
527 return stateMgr->getOwningEngine().getAnalysisManager();
528}
529
530//===----------------------------------------------------------------------===//
531// Generic Data Map.
532//===----------------------------------------------------------------------===//
533
534void *const* ProgramState::FindGDM(void *K) const {
535 return GDM.lookup(K);
536}
537
538void*
540 void *(*CreateContext)(llvm::BumpPtrAllocator&),
541 void (*DeleteContext)(void*)) {
542
543 std::pair<void*, void (*)(void*)>& p = GDMContexts[K];
544 if (!p.first) {
545 p.first = CreateContext(Alloc);
546 p.second = DeleteContext;
547 }
548
549 return p.first;
550}
551
553 ProgramState::GenericDataMap M1 = St->getGDM();
554 ProgramState::GenericDataMap M2 = GDMFactory.add(M1, Key, Data);
555
556 if (M1 == M2)
557 return St;
558
559 ProgramState NewSt = *St;
560 NewSt.GDM = M2;
561 return getPersistentState(NewSt);
562}
563
565 ProgramState::GenericDataMap OldM = state->getGDM();
566 ProgramState::GenericDataMap NewM = GDMFactory.remove(OldM, Key);
567
568 if (NewM == OldM)
569 return state;
570
571 ProgramState NewState = *state;
572 NewState.GDM = NewM;
573 return getPersistentState(NewState);
574}
575
577 bool wasVisited = !visited.insert(val.getCVData()).second;
578 if (wasVisited)
579 return true;
580
581 StoreManager &StoreMgr = state->getStateManager().getStoreManager();
582 // FIXME: We don't really want to use getBaseRegion() here because pointer
583 // arithmetic doesn't apply, but scanReachableSymbols only accepts base
584 // regions right now.
585 const MemRegion *R = val.getRegion()->getBaseRegion();
586 return StoreMgr.scanReachableSymbols(val.getStore(), R, *this);
587}
588
590 for (SVal V : val)
591 if (!scan(V))
592 return false;
593
594 return true;
595}
596
598 for (SymbolRef SubSym : sym->symbols()) {
599 bool wasVisited = !visited.insert(SubSym).second;
600 if (wasVisited)
601 continue;
602
603 if (!visitor.VisitSymbol(SubSym))
604 return false;
605 }
606
607 return true;
608}
609
611 if (std::optional<loc::MemRegionVal> X = val.getAs<loc::MemRegionVal>())
612 return scan(X->getRegion());
613
614 if (std::optional<nonloc::LazyCompoundVal> X =
616 return scan(*X);
617
618 if (std::optional<nonloc::LocAsInteger> X = val.getAs<nonloc::LocAsInteger>())
619 return scan(X->getLoc());
620
621 if (SymbolRef Sym = val.getAsSymbol())
622 return scan(Sym);
623
624 if (std::optional<nonloc::CompoundVal> X = val.getAs<nonloc::CompoundVal>())
625 return scan(*X);
626
627 return true;
628}
629
631 if (isa<MemSpaceRegion>(R))
632 return true;
633
634 bool wasVisited = !visited.insert(R).second;
635 if (wasVisited)
636 return true;
637
638 if (!visitor.VisitMemRegion(R))
639 return false;
640
641 // If this is a symbolic region, visit the symbol for the region.
642 if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
643 if (!visitor.VisitSymbol(SR->getSymbol()))
644 return false;
645
646 // If this is a subregion, also visit the parent regions.
647 if (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
648 const MemRegion *Super = SR->getSuperRegion();
649 if (!scan(Super))
650 return false;
651
652 // When we reach the topmost region, scan all symbols in it.
653 if (isa<MemSpaceRegion>(Super)) {
654 StoreManager &StoreMgr = state->getStateManager().getStoreManager();
655 if (!StoreMgr.scanReachableSymbols(state->getStore(), SR, *this))
656 return false;
657 }
658 }
659
660 // Regions captured by a block are also implicitly reachable.
661 if (const BlockDataRegion *BDR = dyn_cast<BlockDataRegion>(R)) {
662 for (auto Var : BDR->referenced_vars()) {
663 if (!scan(Var.getCapturedRegion()))
664 return false;
665 }
666 }
667
668 return true;
669}
670
672 ScanReachableSymbols S(this, visitor);
673 return S.scan(val);
674}
675
677 llvm::iterator_range<region_iterator> Reachable,
678 SymbolVisitor &visitor) const {
679 ScanReachableSymbols S(this, visitor);
680 for (const MemRegion *R : Reachable) {
681 if (!S.scan(R))
682 return false;
683 }
684 return true;
685}
#define V(N, I)
#define X(type, name)
Definition Value.h:97
#define SM(sm)
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 ...
Definition ASTContext.h:188
CanQualType IntTy
Represents a member of a struct/union/class.
Definition Decl.h:3157
Represents a field injected from an anonymous union/struct into the parent scope.
Definition Decl.h:3464
ArrayRef< NamedDecl * > chain() const
Definition Decl.h:3485
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
const ImplicitParamDecl * getSelfDecl() const
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
It represents a stack frame of the call stack (based on CallEvent).
Stmt - This represents one statement.
Definition Stmt.h:85
A safe wrapper around APSInt objects allocated and owned by BasicValueFactory.
Definition APSIntPtr.h:19
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.
Definition MemRegion.h:706
Manages the lifetime of CallEvent objects.
Definition CallEvent.h:1363
Represents an abstract call to a function or method along a particular path.
Definition CallEvent.h:153
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.
Definition Environment.h:36
Environment bindExpr(Environment Env, const EnvironmentEntry &E, SVal V, bool Invalidate)
Bind a symbolic value to the given environment entry.
An immutable map from EnvironemntEntries to SVals.
Definition Environment.h:56
ProgramStateRef processRegionChange(ProgramStateRef state, const MemRegion *MR, const LocationContext *LCtx)
Definition ExprEngine.h:410
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.
ProgramStateRef escapeValues(ProgramStateRef State, ArrayRef< SVal > Vs, PointerEscapeKind K, const CallEvent *Call=nullptr) const
A simple wrapper when you only need to notify checkers of pointer-escape of some values.
static bool isLocType(QualType T)
Definition SVals.h:262
MemRegion - The root abstract class for all memory regions.
Definition MemRegion.h:98
virtual bool isBoundable() const
Definition MemRegion.h:211
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
ProgramStateRef removeDeadBindingsFromEnvironmentAndStore(ProgramStateRef St, const StackFrameContext *LCtx, SymbolReaper &SymReaper)
ProgramStateRef removeGDM(ProgramStateRef state, void *Key)
void * FindGDMContext(void *index, void *(*CreateContext)(llvm::BumpPtrAllocator &), void(*DeleteContext)(void *))
ProgramStateRef getPersistentStateWithGDM(ProgramStateRef FromState, ProgramStateRef GDMState)
ProgramStateRef addGDM(ProgramStateRef St, void *Key, void *Data)
ProgramStateRef getPersistentState(ProgramState &Impl)
ProgramStateRef getInitialState(const LocationContext *InitLoc)
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
friend class ProgramStateManager
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
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 simplification.
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 invalidateRegions(ArrayRef< const MemRegion * > Regions, ConstCFGElementRef Elem, 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.
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.
Definition MemRegion.h:1657
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.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition SVals.h:56
bool isUnknownOrUndef() const
Definition SVals.h:109
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
Definition SVals.cpp:103
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
Definition SVals.h:87
const MemRegion * getAsRegion() const
Definition SVals.cpp:119
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Definition SVals.h:83
bool isUnknown() const
Definition SVals.h:105
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.
SmallVector< const MemRegion *, 8 > InvalidatedRegions
Definition Store.h:211
virtual void printJson(raw_ostream &Out, Store S, const char *NL, unsigned int Space, bool IsDot) const =0
Store getStore() const
Definition StoreRef.h:46
SubRegion - A region that subsets another larger region.
Definition MemRegion.h:474
Symbolic value.
Definition SymExpr.h:32
llvm::iterator_range< symbol_iterator > symbols() const
Definition SymExpr.h:107
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.
SymbolicRegion - A special, "non-concrete" region.
Definition MemRegion.h:808
TypedValueRegion - An abstract class representing regions having a typed value.
Definition MemRegion.h:563
The simplest example of a concrete compound value is nonloc::CompoundVal, which represents a concrete...
Definition SVals.h:339
Value representing integer constant.
Definition SVals.h:300
While nonloc::CompoundVal covers a few simple use cases, nonloc::LazyCompoundVal is a more performant...
Definition SVals.h:389
LLVM_ATTRIBUTE_RETURNS_NONNULL const LazyCompoundValData * getCVData() const
Definition SVals.h:399
LLVM_ATTRIBUTE_RETURNS_NONNULL const TypedValueRegion * getRegion() const
This function itself is immaterial.
Definition SVals.cpp:193
const void * getStore() const
It might return null.
Definition SVals.cpp:189
@ PSK_EscapeOnBind
A pointer escapes due to binding its value to a location that the analyzer cannot track.
SValBuilder * createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context, ProgramStateManager &stateMgr)
llvm::DenseSet< SymbolRef > InvalidatedSymbols
Definition Store.h:51
void printDynamicTypeInfoJson(raw_ostream &Out, ProgramStateRef State, const char *NL="\n", unsigned int Space=0, bool IsDot=false)
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const SymExpr * SymbolRef
Definition SymExpr.h:133
std::unique_ptr< ConstraintManager >(* ConstraintManagerCreator)(ProgramStateManager &, ExprEngine *)
std::unique_ptr< StoreManager >(* StoreManagerCreator)(ProgramStateManager &)
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.
const void * Store
Store - This opaque type encapsulates an immutable mapping from locations to values.
Definition StoreRef.h:27
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
CFGBlock::ConstCFGElementRef ConstCFGElementRef
Definition CFG.h:1199
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
Definition JsonSupport.h:21
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Definition Address.h:327
llvm::SmallVector< SVal, 0 > FailedToBindValues
Definition Store.h:58
StoreRef ResultingStore
Definition Store.h:54