clang 23.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 StackFrame *SF, SymbolReaper &SymReaper) {
92
93 // This code essentially performs a "mark-and-sweep" of the VariableBindings.
94 // The roots are any Block-level exprs and Decls that our liveness algorithm
95 // tells us are live. We then see what Decls they may reference, and keep
96 // those around. This code more than likely can be made faster, and the
97 // frequency of which this method is called should be experimented with
98 // for optimum performance.
99 ProgramState NewState = *state;
100
101 NewState.Env = EnvMgr.removeDeadBindings(NewState.Env, SymReaper, state);
102
103 // Clean up the store.
104 StoreRef newStore =
105 StoreMgr->removeDeadBindings(NewState.getStore(), SF, SymReaper);
106 NewState.setStore(newStore);
107 SymReaper.setReapedStore(newStore);
108
109 return getPersistentState(NewState);
110}
111
113 bool notifyChanges) const {
115 ExprEngine &Eng = Mgr.getOwningEngine();
116 ProgramStateRef State = makeWithStore(Mgr.StoreMgr->Bind(getStore(), LV, V));
117 const MemRegion *MR = LV.getAsRegion();
118
119 if (MR && notifyChanges)
120 return Eng.processRegionChange(State, MR, SF);
121
122 return State;
123}
124
126 const StackFrame *SF) const {
128 const MemRegion *R = loc.castAs<loc::MemRegionVal>().getRegion();
129 BindResult BindRes = Mgr.StoreMgr->BindDefaultInitial(getStore(), R, V);
130 ProgramStateRef State = makeWithStore(BindRes);
131 return Mgr.getOwningEngine().processRegionChange(State, R, SF);
132}
133
135 const StackFrame *SF) const {
137 const MemRegion *R = loc.castAs<loc::MemRegionVal>().getRegion();
138 BindResult BindRes = Mgr.StoreMgr->BindDefaultZero(getStore(), R);
139 ProgramStateRef State = makeWithStore(BindRes);
140 return Mgr.getOwningEngine().processRegionChange(State, R, SF);
141}
142
145
147 RegionList Regions, ConstCFGElementRef Elem, unsigned Count,
148 const StackFrame *SF, bool CausedByPointerEscape, InvalidatedSymbols *IS,
149 const CallEvent *Call, RegionAndSymbolInvalidationTraits *ITraits) const {
151 for (const MemRegion *Reg : Regions)
152 Values.push_back(loc::MemRegionVal(Reg));
153
154 return invalidateRegions(Values, Elem, Count, SF, CausedByPointerEscape, IS,
155 Call, ITraits);
156}
157
159 ValueList Values, ConstCFGElementRef Elem, unsigned Count,
160 const StackFrame *SF, bool CausedByPointerEscape, InvalidatedSymbols *IS,
161 const CallEvent *Call, RegionAndSymbolInvalidationTraits *ITraits) const {
162
164 ExprEngine &Eng = Mgr.getOwningEngine();
165
166 InvalidatedSymbols InvalidatedSyms;
167 if (!IS)
168 IS = &InvalidatedSyms;
169
170 RegionAndSymbolInvalidationTraits ITraitsLocal;
171 if (!ITraits)
172 ITraits = &ITraitsLocal;
173
174 StoreManager::InvalidatedRegions TopLevelInvalidated;
176 const StoreRef &NewStore = Mgr.StoreMgr->invalidateRegions(
177 getStore(), Values, Elem, Count, SF, Call, *IS, *ITraits,
178 &TopLevelInvalidated, &Invalidated);
179
180 ProgramStateRef NewState = makeWithStore(NewStore);
181
182 if (CausedByPointerEscape) {
183 NewState = Eng.notifyCheckersOfPointerEscape(
184 NewState, IS, TopLevelInvalidated, Call, *ITraits);
185 }
186
187 return Eng.processRegionChanges(NewState, IS, TopLevelInvalidated,
188 Invalidated, SF, Call);
189}
190
192 Store OldStore = getStore();
193 const StoreRef &newStore =
194 getStateManager().StoreMgr->killBinding(OldStore, LV);
195
196 if (newStore.getStore() == OldStore)
197 return this;
198
199 return makeWithStore(newStore);
200}
201
202/// We should never form a MemRegion that would wrap a TypedValueRegion of a
203/// reference type. What we actually wanted was to create a MemRegion refering
204/// to the pointee of that reference.
205SVal ProgramState::desugarReference(SVal Val) const {
206 const auto *TyReg = dyn_cast_or_null<TypedValueRegion>(Val.getAsRegion());
207 if (!TyReg || !TyReg->getValueType()->isReferenceType())
208 return Val;
209 return getSVal(TyReg);
210}
211
212/// SymbolicRegions are expected to be wrapped by an ElementRegion as a
213/// canonical representation. As a canonical representation, SymbolicRegions
214/// should be wrapped by ElementRegions before getting a FieldRegion.
215/// See f8643a9b31c4029942f67d4534c9139b45173504 why.
216SVal ProgramState::wrapSymbolicRegion(SVal Val) const {
217 const auto *BaseReg = dyn_cast_or_null<SymbolicRegion>(Val.getAsRegion());
218 if (!BaseReg)
219 return Val;
220
222 QualType ElemTy = BaseReg->getPointeeStaticType();
223 return loc::MemRegionVal{SM.GetElementZeroRegion(BaseReg, ElemTy)};
224}
225
228 const StackFrame *CalleeCtx) const {
229 return makeWithStore(
230 getStateManager().StoreMgr->enterStackFrame(getStore(), Call, CalleeCtx));
231}
232
234 const ImplicitParamDecl *SelfDecl = SF->getSelfDecl();
235 if (!SelfDecl)
236 return SVal();
237 return getSVal(getRegion(SelfDecl, SF));
238}
239
241 // We only want to do fetches from regions that we can actually bind
242 // values. For example, SymbolicRegions of type 'id<...>' cannot
243 // have direct bindings (but their can be bindings on their subregions).
244 if (!R->isBoundable())
245 return UnknownVal();
246
247 if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
248 QualType T = TR->getValueType();
249 if (Loc::isLocType(T) || T->isIntegralOrEnumerationType())
250 return getSVal(R);
251 }
252
253 return UnknownVal();
254}
255
257 SVal V = getRawSVal(location, T);
258
259 // If 'V' is a symbolic value that is *perfectly* constrained to
260 // be a constant value, use that value instead to lessen the burden
261 // on later analysis stages (so we have less symbolic values to reason
262 // about).
263 // We only go into this branch if we can convert the APSInt value we have
264 // to the type of T, which is not always the case (e.g. for void).
265 if (!T.isNull() && (T->isIntegralOrEnumerationType() || Loc::isLocType(T))) {
266 if (SymbolRef sym = V.getAsSymbol()) {
267 if (const llvm::APSInt *Int = getStateManager()
269 .getSymVal(this, sym)) {
270 // FIXME: Because we don't correctly model (yet) sign-extension
271 // and truncation of symbolic values, we need to convert
272 // the integer value to the correct signedness and bitwidth.
273 //
274 // This shows up in the following:
275 //
276 // char foo();
277 // unsigned x = foo();
278 // if (x == 54)
279 // ...
280 //
281 // The symbolic value stored to 'x' is actually the conjured
282 // symbol for the call to foo(); the type of that symbol is 'char',
283 // not unsigned.
284 APSIntPtr NewV = getBasicVals().Convert(T, *Int);
285 if (V.getAs<Loc>())
286 return loc::ConcreteInt(NewV);
287 return nonloc::ConcreteInt(NewV);
288 }
289 }
290 }
291
292 return V;
293}
294
296 SVal V, bool Invalidate) const {
297 Environment NewEnv = getStateManager().EnvMgr.bindExpr(
298 Env, EnvironmentEntry(E, SF), V, Invalidate);
299 if (NewEnv == Env)
300 return this;
301
302 ProgramState NewSt = *this;
303 NewSt.Env = std::move(NewEnv);
304 return getStateManager().getPersistentState(NewSt);
305}
306
307[[nodiscard]] std::pair<ProgramStateRef, ProgramStateRef>
309 DefinedOrUnknownSVal UpperBound,
310 QualType indexTy) const {
311 if (Idx.isUnknown() || UpperBound.isUnknown())
312 return {this, this};
313
314 // Build an expression for 0 <= Idx < UpperBound.
315 // This is the same as Idx + MIN < UpperBound + MIN, if overflow is allowed.
316 // FIXME: This should probably be part of SValBuilder.
318 SValBuilder &svalBuilder = SM.getSValBuilder();
319 ASTContext &Ctx = svalBuilder.getContext();
320
321 // Get the offset: the minimum value of the array index type.
322 BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
323 if (indexTy.isNull())
324 indexTy = svalBuilder.getArrayIndexType();
325 nonloc::ConcreteInt Min(BVF.getMinValue(indexTy));
326
327 // Adjust the index.
328 SVal newIdx = svalBuilder.evalBinOpNN(this, BO_Add,
329 Idx.castAs<NonLoc>(), Min, indexTy);
330 if (newIdx.isUnknownOrUndef())
331 return {this, this};
332
333 // Adjust the upper bound.
334 SVal newBound =
335 svalBuilder.evalBinOpNN(this, BO_Add, UpperBound.castAs<NonLoc>(),
336 Min, indexTy);
337
338 if (newBound.isUnknownOrUndef())
339 return {this, this};
340
341 // Build the actual comparison.
342 SVal inBound = svalBuilder.evalBinOpNN(this, BO_LT, newIdx.castAs<NonLoc>(),
343 newBound.castAs<NonLoc>(), Ctx.IntTy);
344 if (inBound.isUnknownOrUndef())
345 return {this, this};
346
347 // Finally, let the constraint manager take care of it.
348 ConstraintManager &CM = SM.getConstraintManager();
349 return CM.assumeDual(this, inBound.castAs<DefinedSVal>());
350}
351
353 DefinedOrUnknownSVal UpperBound,
354 bool Assumption,
355 QualType indexTy) const {
356 std::pair<ProgramStateRef, ProgramStateRef> R =
357 assumeInBoundDual(Idx, UpperBound, indexTy);
358 return Assumption ? R.first : R.second;
359}
360
363 if (IsNull.isUnderconstrained())
364 return IsNull;
365 return ConditionTruthVal(!IsNull.getValue());
366}
367
369 return stateMgr->getSValBuilder().areEqual(this, Lhs, Rhs);
370}
371
373 if (V.isZeroConstant())
374 return true;
375
376 if (V.isConstant())
377 return false;
378
379 SymbolRef Sym = V.getAsSymbol(/* IncludeBaseRegion */ true);
380 if (!Sym)
381 return ConditionTruthVal();
382
383 return getStateManager().ConstraintMgr->isNull(this, Sym);
384}
385
387 ProgramState State(this, EnvMgr.getInitialEnvironment(),
388 StoreMgr->getInitialStore(InitSF),
389 GDMFactory.getEmptyMap());
390
391 return getPersistentState(State);
392}
393
395 ProgramStateRef FromState,
396 ProgramStateRef GDMState) {
397 ProgramState NewState(*FromState);
398 NewState.GDM = GDMState->GDM;
399 return getPersistentState(NewState);
400}
401
403
404 llvm::FoldingSetNodeID ID;
405 State.Profile(ID);
406 void *InsertPos;
407
408 if (ProgramState *I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
409 return I;
410
411 ProgramState *newState = nullptr;
412 if (!freeStates.empty()) {
413 newState = freeStates.back();
414 freeStates.pop_back();
415 }
416 else {
417 newState = Alloc.Allocate<ProgramState>();
418 }
419 new (newState) ProgramState(State);
420 StateSet.InsertNode(newState, InsertPos);
421 return newState;
422}
423
424ProgramStateRef ProgramState::makeWithStore(const StoreRef &store) const {
425 ProgramState NewSt(*this);
426 NewSt.setStore(store);
427 return getStateManager().getPersistentState(NewSt);
428}
429
430ProgramStateRef ProgramState::makeWithStore(const BindResult &BindRes) const {
432 ProgramStateRef State = makeWithStore(BindRes.ResultingStore);
433
434 // We must always notify the checkers for failing binds because otherwise they
435 // may keep stale traits for these symbols.
436 // Eg., Malloc checker may report leaks if we failed to bind that symbol.
437 if (BindRes.FailedToBindValues.empty())
438 return State;
439 return Eng.escapeValues(State, BindRes.FailedToBindValues, PSK_EscapeOnBind);
440}
441
442ProgramStateRef ProgramState::cloneAsPosteriorlyOverconstrained() const {
443 ProgramState NewSt(*this);
444 NewSt.PosteriorlyOverconstrained = true;
445 return getStateManager().getPersistentState(NewSt);
446}
447
448void ProgramState::setStore(const StoreRef &newStore) {
449 Store newStoreStore = newStore.getStore();
450 if (newStoreStore)
451 stateMgr->getStoreManager().incrementReferenceCount(newStoreStore);
452 if (store)
453 stateMgr->getStoreManager().decrementReferenceCount(store);
454 store = newStoreStore;
455}
456
458 Base = desugarReference(Base);
459 Base = wrapSymbolicRegion(Base);
460 return getStateManager().StoreMgr->getLValueField(D, Base);
461}
462
464 StoreManager &SM = *getStateManager().StoreMgr;
465 Base = desugarReference(Base);
466 Base = wrapSymbolicRegion(Base);
467
468 // FIXME: This should work with `SM.getLValueField(D->getAnonField(), Base)`,
469 // but that would break some tests. There is probably a bug somewhere that it
470 // would expose.
471 for (const auto *I : D->chain()) {
472 Base = SM.getLValueField(cast<FieldDecl>(I), Base);
473 }
474 return Base;
475}
476
477//===----------------------------------------------------------------------===//
478// State pretty-printing.
479//===----------------------------------------------------------------------===//
480
481void ProgramState::printJson(raw_ostream &Out, const StackFrame *SF,
482 const char *NL, unsigned int Space,
483 bool IsDot) const {
484 Indent(Out, Space, IsDot) << "\"program_state\": {" << NL;
485 ++Space;
486
488
489 // Print the store.
490 Mgr.getStoreManager().printJson(Out, getStore(), NL, Space, IsDot);
491
492 // Print out the environment.
493 Env.printJson(Out, Mgr.getContext(), SF, NL, Space, IsDot);
494
495 // Print out the constraints.
496 Mgr.getConstraintManager().printJson(Out, this, NL, Space, IsDot);
497
498 // Print out the tracked dynamic types.
499 printDynamicTypeInfoJson(Out, this, NL, Space, IsDot);
500
501 // Print checker-specific data.
502 Mgr.getOwningEngine().printJson(Out, this, SF, NL, Space, IsDot);
503
504 --Space;
505 Indent(Out, Space, IsDot) << '}';
506}
507
508void ProgramState::printDOT(raw_ostream &Out, const StackFrame *SF,
509 unsigned int Space) const {
510 printJson(Out, SF, /*NL=*/"\\l", Space, /*IsDot=*/true);
511}
512
513LLVM_DUMP_METHOD void ProgramState::dump() const {
514 printJson(llvm::errs());
515}
516
518 return stateMgr->getOwningEngine().getAnalysisManager();
519}
520
521//===----------------------------------------------------------------------===//
522// Generic Data Map.
523//===----------------------------------------------------------------------===//
524
525void *const *ProgramState::FindGDM(const void *K) const {
526 return GDM.lookup(K);
527}
528
530 const void *K, void *(*CreateContext)(llvm::BumpPtrAllocator &),
531 void (*DeleteContext)(void *)) {
532
533 std::pair<void*, void (*)(void*)>& p = GDMContexts[K];
534 if (!p.first) {
535 p.first = CreateContext(Alloc);
536 p.second = DeleteContext;
537 }
538
539 return p.first;
540}
541
543 void *Data) {
544 ProgramState::GenericDataMap M1 = St->getGDM();
545 ProgramState::GenericDataMap M2 = GDMFactory.add(M1, Key, Data);
546
547 if (M1 == M2)
548 return St;
549
550 ProgramState NewSt = *St;
551 NewSt.GDM = M2;
552 return getPersistentState(NewSt);
553}
554
556 const void *Key) {
557 ProgramState::GenericDataMap OldM = state->getGDM();
558 ProgramState::GenericDataMap NewM = GDMFactory.remove(OldM, Key);
559
560 if (NewM == OldM)
561 return state;
562
563 ProgramState NewState = *state;
564 NewState.GDM = NewM;
565 return getPersistentState(NewState);
566}
567
569 bool wasVisited = !visited.insert(val.getCVData()).second;
570 if (wasVisited)
571 return true;
572
573 StoreManager &StoreMgr = state->getStateManager().getStoreManager();
574 // FIXME: We don't really want to use getBaseRegion() here because pointer
575 // arithmetic doesn't apply, but scanReachableSymbols only accepts base
576 // regions right now.
577 const MemRegion *R = val.getRegion()->getBaseRegion();
578 return StoreMgr.scanReachableSymbols(val.getStore(), R, *this);
579}
580
582 for (SVal V : val)
583 if (!scan(V))
584 return false;
585
586 return true;
587}
588
590 for (SymbolRef SubSym : sym->symbols()) {
591 bool wasVisited = !visited.insert(SubSym).second;
592 if (wasVisited)
593 continue;
594
595 if (!visitor.VisitSymbol(SubSym))
596 return false;
597 }
598
599 return true;
600}
601
603 if (std::optional<loc::MemRegionVal> X = val.getAs<loc::MemRegionVal>())
604 return scan(X->getRegion());
605
606 if (std::optional<nonloc::LazyCompoundVal> X =
608 return scan(*X);
609
610 if (std::optional<nonloc::LocAsInteger> X = val.getAs<nonloc::LocAsInteger>())
611 return scan(X->getLoc());
612
613 if (SymbolRef Sym = val.getAsSymbol())
614 return scan(Sym);
615
616 if (std::optional<nonloc::CompoundVal> X = val.getAs<nonloc::CompoundVal>())
617 return scan(*X);
618
619 return true;
620}
621
623 if (isa<MemSpaceRegion>(R))
624 return true;
625
626 bool wasVisited = !visited.insert(R).second;
627 if (wasVisited)
628 return true;
629
630 if (!visitor.VisitMemRegion(R))
631 return false;
632
633 // If this is a symbolic region, visit the symbol for the region.
634 if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
635 if (!visitor.VisitSymbol(SR->getSymbol()))
636 return false;
637
638 // If this is a subregion, also visit the parent regions.
639 if (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
640 const MemRegion *Super = SR->getSuperRegion();
641 if (!scan(Super))
642 return false;
643
644 // When we reach the topmost region, scan all symbols in it.
645 if (isa<MemSpaceRegion>(Super)) {
646 StoreManager &StoreMgr = state->getStateManager().getStoreManager();
647 if (!StoreMgr.scanReachableSymbols(state->getStore(), SR, *this))
648 return false;
649 }
650 }
651
652 // Regions captured by a block are also implicitly reachable.
653 if (const BlockDataRegion *BDR = dyn_cast<BlockDataRegion>(R)) {
654 for (auto Var : BDR->referenced_vars()) {
655 if (!scan(Var.getCapturedRegion()))
656 return false;
657 }
658 }
659
660 return true;
661}
662
664 ScanReachableSymbols S(this, visitor);
665 return S.scan(val);
666}
667
669 llvm::iterator_range<region_iterator> Reachable,
670 SymbolVisitor &visitor) const {
671 ScanReachableSymbols S(this, visitor);
672 for (const MemRegion *R : Reachable) {
673 if (!S.scan(R))
674 return false;
675 }
676 return true;
677}
#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:226
CanQualType IntTy
This represents one expression.
Definition Expr.h:112
Represents a member of a struct/union/class.
Definition Decl.h:3182
Represents a field injected from an anonymous union/struct into the parent scope.
Definition Decl.h:3489
ArrayRef< NamedDecl * > chain() const
Definition Decl.h:3510
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.
const ImplicitParamDecl * getSelfDecl() const
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:705
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:152
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 StackFrame.
Definition Environment.h:35
Environment bindExpr(Environment Env, const EnvironmentEntry &E, SVal V, bool Invalidate)
Bind a symbolic value to the given environment entry.
An immutable map from EnvironmentEntries to SVals.
Definition Environment.h:55
ProgramStateRef processRegionChanges(ProgramStateRef state, const InvalidatedSymbols *invalidated, ArrayRef< const MemRegion * > ExplicitRegions, ArrayRef< const MemRegion * > Regions, const StackFrame *SF, const CallEvent *Call)
processRegionChanges - Called by ProgramStateManager whenever a change is made to the store.
void printJson(raw_ostream &Out, ProgramStateRef State, const StackFrame *SF, const char *NL, unsigned int Space, bool IsDot) const
printJson - Called by ProgramStateManager to print checker-specific data.
ProgramStateRef processRegionChange(ProgramStateRef state, const MemRegion *MR, const StackFrame *SF)
Definition ExprEngine.h:465
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:97
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
ProgramStateRef getInitialState(const StackFrame *InitSF)
void * FindGDMContext(const void *index, void *(*CreateContext)(llvm::BumpPtrAllocator &), void(*DeleteContext)(void *))
ProgramStateRef removeDeadBindingsFromEnvironmentAndStore(ProgramStateRef St, const StackFrame *SF, SymbolReaper &SymReaper)
ProgramStateRef getPersistentStateWithGDM(ProgramStateRef FromState, ProgramStateRef GDMState)
ProgramStateRef removeGDM(ProgramStateRef state, const void *Key)
ProgramStateRef addGDM(ProgramStateRef St, const void *Key, void *Data)
ProgramStateRef getPersistentState(ProgramState &Impl)
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.
friend class ProgramStateManager
llvm::ImmutableMap< const void *, void * > GenericDataMap
ProgramStateRef bindDefaultInitial(SVal loc, SVal V, const StackFrame *SF) const
Initializes the region of memory represented by loc with an initial value.
ConstraintManager & getConstraintManager() const
Return the ConstraintManager.
LLVM_ATTRIBUTE_RETURNS_NONNULL const VarRegion * getRegion(const VarDecl *D, const StackFrame *SF) const
Utility method for getting regions.
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.
ProgramStateRef bindLoc(Loc location, SVal V, const StackFrame *SF, bool notifyChanges=true) const
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.
ProgramStateRef BindExpr(const Expr *E, const StackFrame *SF, SVal V, bool Invalidate=true) const
Create a new state by binding the value V to the expression E in the state's environment.
ProgramStateRef bindDefaultZero(SVal loc, const StackFrame *SF) const
Performs C++ zero-initialization procedure on the region of memory represented by loc.
SVal getSVal(const Expr *E, const StackFrame *SF) const
Returns the SVal bound to the expression E in the state's environment.
Store getStore() const
Return the store associated with this state.
ConditionTruthVal areEqual(SVal Lhs, SVal Rhs) 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
SVal getSValAsScalarOrLoc(const Expr *E, const StackFrame *SF) const
ProgramStateRef invalidateRegions(ArrayRef< const MemRegion * > Regions, ConstCFGElementRef Elem, unsigned BlockCount, const StackFrame *SF, 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.
void printDOT(raw_ostream &Out, const StackFrame *SF=nullptr, unsigned int Space=0) const
SVal getSelfSVal(const StackFrame *SF) const
Return the value of 'self' if available in the given context.
void printJson(raw_ostream &Out, const StackFrame *SF=nullptr, const char *NL="\n", unsigned int Space=0, bool IsDot=false) const
BasicValueFactory & getBasicVals() const
std::pair< ProgramStateRef, ProgramStateRef > assumeInBoundDual(DefinedOrUnknownSVal idx, DefinedOrUnknownSVal upperBound, QualType IndexType=QualType()) const
void *const * FindGDM(const void *K) const
AnalysisManager & getAnalysisManager() const
ProgramStateRef enterStackFrame(const CallEvent &Call, const StackFrame *CalleeSF) const
enterStackFrame - Returns the state for entry to the given stack frame, preserving the current state.
Information about invalidation for a particular region/symbol.
Definition MemRegion.h:1656
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:210
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:473
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:806
TypedValueRegion - An abstract class representing regions having a typed value.
Definition MemRegion.h:562
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:50
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:1235
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
Definition JsonSupport.h:21
U cast(CodeGen::Address addr)
Definition Address.h:327
llvm::SmallVector< SVal, 0 > FailedToBindValues
Definition Store.h:57
StoreRef ResultingStore
Definition Store.h:53