clang 21.0.0git
ExprEngine.cpp
Go to the documentation of this file.
1//===- ExprEngine.cpp - Path-Sensitive Expression-Level Dataflow ----------===//
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 defines a meta-engine for path-sensitive dataflow analysis that
10// is built on CoreEngine, but provides the boilerplate to execute transfer
11// functions and build the ExplodedGraph at the expression level.
12//
13//===----------------------------------------------------------------------===//
14
18#include "clang/AST/Decl.h"
19#include "clang/AST/DeclBase.h"
20#include "clang/AST/DeclCXX.h"
21#include "clang/AST/DeclObjC.h"
22#include "clang/AST/Expr.h"
23#include "clang/AST/ExprCXX.h"
24#include "clang/AST/ExprObjC.h"
25#include "clang/AST/ParentMap.h"
27#include "clang/AST/Stmt.h"
28#include "clang/AST/StmtCXX.h"
29#include "clang/AST/StmtObjC.h"
30#include "clang/AST/Type.h"
32#include "clang/Analysis/CFG.h"
37#include "clang/Basic/LLVM.h"
64#include "llvm/ADT/APSInt.h"
65#include "llvm/ADT/DenseMap.h"
66#include "llvm/ADT/ImmutableMap.h"
67#include "llvm/ADT/ImmutableSet.h"
68#include "llvm/ADT/STLExtras.h"
69#include "llvm/ADT/SmallVector.h"
70#include "llvm/ADT/Statistic.h"
71#include "llvm/Support/Casting.h"
72#include "llvm/Support/Compiler.h"
73#include "llvm/Support/DOTGraphTraits.h"
74#include "llvm/Support/ErrorHandling.h"
75#include "llvm/Support/GraphWriter.h"
76#include "llvm/Support/SaveAndRestore.h"
77#include "llvm/Support/raw_ostream.h"
78#include <cassert>
79#include <cstdint>
80#include <memory>
81#include <optional>
82#include <string>
83#include <tuple>
84#include <utility>
85#include <vector>
86
87using namespace clang;
88using namespace ento;
89
90#define DEBUG_TYPE "ExprEngine"
91
92STATISTIC(NumRemoveDeadBindings,
93 "The # of times RemoveDeadBindings is called");
94STATISTIC(NumMaxBlockCountReached,
95 "The # of aborted paths due to reaching the maximum block count in "
96 "a top level function");
97STATISTIC(NumMaxBlockCountReachedInInlined,
98 "The # of aborted paths due to reaching the maximum block count in "
99 "an inlined function");
100STATISTIC(NumTimesRetriedWithoutInlining,
101 "The # of times we re-evaluated a call without inlining");
102
103//===----------------------------------------------------------------------===//
104// Internal program state traits.
105//===----------------------------------------------------------------------===//
106
107namespace {
108
109// When modeling a C++ constructor, for a variety of reasons we need to track
110// the location of the object for the duration of its ConstructionContext.
111// ObjectsUnderConstruction maps statements within the construction context
112// to the object's location, so that on every such statement the location
113// could have been retrieved.
114
115/// ConstructedObjectKey is used for being able to find the path-sensitive
116/// memory region of a freshly constructed object while modeling the AST node
117/// that syntactically represents the object that is being constructed.
118/// Semantics of such nodes may sometimes require access to the region that's
119/// not otherwise present in the program state, or to the very fact that
120/// the construction context was present and contained references to these
121/// AST nodes.
122class ConstructedObjectKey {
123 using ConstructedObjectKeyImpl =
124 std::pair<ConstructionContextItem, const LocationContext *>;
125 const ConstructedObjectKeyImpl Impl;
126
127public:
128 explicit ConstructedObjectKey(const ConstructionContextItem &Item,
129 const LocationContext *LC)
130 : Impl(Item, LC) {}
131
132 const ConstructionContextItem &getItem() const { return Impl.first; }
133 const LocationContext *getLocationContext() const { return Impl.second; }
134
135 ASTContext &getASTContext() const {
136 return getLocationContext()->getDecl()->getASTContext();
137 }
138
139 void printJson(llvm::raw_ostream &Out, PrinterHelper *Helper,
140 PrintingPolicy &PP) const {
141 const Stmt *S = getItem().getStmtOrNull();
142 const CXXCtorInitializer *I = nullptr;
143 if (!S)
144 I = getItem().getCXXCtorInitializer();
145
146 if (S)
147 Out << "\"stmt_id\": " << S->getID(getASTContext());
148 else
149 Out << "\"init_id\": " << I->getID(getASTContext());
150
151 // Kind
152 Out << ", \"kind\": \"" << getItem().getKindAsString()
153 << "\", \"argument_index\": ";
154
156 Out << getItem().getIndex();
157 else
158 Out << "null";
159
160 // Pretty-print
161 Out << ", \"pretty\": ";
162
163 if (S) {
164 S->printJson(Out, Helper, PP, /*AddQuotes=*/true);
165 } else {
166 Out << '\"' << I->getAnyMember()->getDeclName() << '\"';
167 }
168 }
169
170 void Profile(llvm::FoldingSetNodeID &ID) const {
171 ID.Add(Impl.first);
172 ID.AddPointer(Impl.second);
173 }
174
175 bool operator==(const ConstructedObjectKey &RHS) const {
176 return Impl == RHS.Impl;
177 }
178
179 bool operator<(const ConstructedObjectKey &RHS) const {
180 return Impl < RHS.Impl;
181 }
182};
183} // namespace
184
185typedef llvm::ImmutableMap<ConstructedObjectKey, SVal>
187REGISTER_TRAIT_WITH_PROGRAMSTATE(ObjectsUnderConstruction,
189
190// This trait is responsible for storing the index of the element that is to be
191// constructed in the next iteration. As a result a CXXConstructExpr is only
192// stored if it is array type. Also the index is the index of the continuous
193// memory region, which is important for multi-dimensional arrays. E.g:: int
194// arr[2][2]; assume arr[1][1] will be the next element under construction, so
195// the index is 3.
196typedef llvm::ImmutableMap<
197 std::pair<const CXXConstructExpr *, const LocationContext *>, unsigned>
198 IndexOfElementToConstructMap;
199REGISTER_TRAIT_WITH_PROGRAMSTATE(IndexOfElementToConstruct,
200 IndexOfElementToConstructMap)
201
202// This trait is responsible for holding our pending ArrayInitLoopExprs.
203// It pairs the LocationContext and the initializer CXXConstructExpr with
204// the size of the array that's being copy initialized.
205typedef llvm::ImmutableMap<
206 std::pair<const CXXConstructExpr *, const LocationContext *>, unsigned>
207 PendingInitLoopMap;
208REGISTER_TRAIT_WITH_PROGRAMSTATE(PendingInitLoop, PendingInitLoopMap)
209
210typedef llvm::ImmutableMap<const LocationContext *, unsigned>
212REGISTER_TRAIT_WITH_PROGRAMSTATE(PendingArrayDestruction,
214
215//===----------------------------------------------------------------------===//
216// Engine construction and deletion.
217//===----------------------------------------------------------------------===//
218
219static const char* TagProviderName = "ExprEngine";
220
222 AnalysisManager &mgr, SetOfConstDecls *VisitedCalleesIn,
223 FunctionSummariesTy *FS, InliningModes HowToInlineIn)
224 : CTU(CTU), IsCTUEnabled(mgr.getAnalyzerOptions().IsNaiveCTUEnabled),
225 AMgr(mgr), AnalysisDeclContexts(mgr.getAnalysisDeclContextManager()),
226 Engine(*this, FS, mgr.getAnalyzerOptions()), G(Engine.getGraph()),
227 StateMgr(getContext(), mgr.getStoreManagerCreator(),
228 mgr.getConstraintManagerCreator(), G.getAllocator(), this),
229 SymMgr(StateMgr.getSymbolManager()), MRMgr(StateMgr.getRegionManager()),
230 svalBuilder(StateMgr.getSValBuilder()), ObjCNoRet(mgr.getASTContext()),
231 BR(mgr, *this), VisitedCallees(VisitedCalleesIn),
232 HowToInline(HowToInlineIn) {
233 unsigned TrimInterval = mgr.options.GraphTrimInterval;
234 if (TrimInterval != 0) {
235 // Enable eager node reclamation when constructing the ExplodedGraph.
236 G.enableNodeReclamation(TrimInterval);
237 }
238}
239
240//===----------------------------------------------------------------------===//
241// Utility methods.
242//===----------------------------------------------------------------------===//
243
245 ProgramStateRef state = StateMgr.getInitialState(InitLoc);
246 const Decl *D = InitLoc->getDecl();
247
248 // Preconditions.
249 // FIXME: It would be nice if we had a more general mechanism to add
250 // such preconditions. Some day.
251 do {
252 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
253 // Precondition: the first argument of 'main' is an integer guaranteed
254 // to be > 0.
255 const IdentifierInfo *II = FD->getIdentifier();
256 if (!II || !(II->getName() == "main" && FD->getNumParams() > 0))
257 break;
258
259 const ParmVarDecl *PD = FD->getParamDecl(0);
260 QualType T = PD->getType();
261 const auto *BT = dyn_cast<BuiltinType>(T);
262 if (!BT || !BT->isInteger())
263 break;
264
265 const MemRegion *R = state->getRegion(PD, InitLoc);
266 if (!R)
267 break;
268
269 SVal V = state->getSVal(loc::MemRegionVal(R));
270 SVal Constraint_untested = evalBinOp(state, BO_GT, V,
271 svalBuilder.makeZeroVal(T),
272 svalBuilder.getConditionType());
273
274 std::optional<DefinedOrUnknownSVal> Constraint =
275 Constraint_untested.getAs<DefinedOrUnknownSVal>();
276
277 if (!Constraint)
278 break;
279
280 if (ProgramStateRef newState = state->assume(*Constraint, true))
281 state = newState;
282 }
283 break;
284 }
285 while (false);
286
287 if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
288 // Precondition: 'self' is always non-null upon entry to an Objective-C
289 // method.
290 const ImplicitParamDecl *SelfD = MD->getSelfDecl();
291 const MemRegion *R = state->getRegion(SelfD, InitLoc);
292 SVal V = state->getSVal(loc::MemRegionVal(R));
293
294 if (std::optional<Loc> LV = V.getAs<Loc>()) {
295 // Assume that the pointer value in 'self' is non-null.
296 state = state->assume(*LV, true);
297 assert(state && "'self' cannot be null");
298 }
299 }
300
301 if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
302 if (MD->isImplicitObjectMemberFunction()) {
303 // Precondition: 'this' is always non-null upon entry to the
304 // top-level function. This is our starting assumption for
305 // analyzing an "open" program.
306 const StackFrameContext *SFC = InitLoc->getStackFrame();
307 if (SFC->getParent() == nullptr) {
308 loc::MemRegionVal L = svalBuilder.getCXXThis(MD, SFC);
309 SVal V = state->getSVal(L);
310 if (std::optional<Loc> LV = V.getAs<Loc>()) {
311 state = state->assume(*LV, true);
312 assert(state && "'this' cannot be null");
313 }
314 }
315 }
316 }
317
318 return state;
319}
320
321ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(
322 ProgramStateRef State, const LocationContext *LC,
323 const Expr *InitWithAdjustments, const Expr *Result,
324 const SubRegion **OutRegionWithAdjustments) {
325 // FIXME: This function is a hack that works around the quirky AST
326 // we're often having with respect to C++ temporaries. If only we modelled
327 // the actual execution order of statements properly in the CFG,
328 // all the hassle with adjustments would not be necessary,
329 // and perhaps the whole function would be removed.
330 SVal InitValWithAdjustments = State->getSVal(InitWithAdjustments, LC);
331 if (!Result) {
332 // If we don't have an explicit result expression, we're in "if needed"
333 // mode. Only create a region if the current value is a NonLoc.
334 if (!isa<NonLoc>(InitValWithAdjustments)) {
335 if (OutRegionWithAdjustments)
336 *OutRegionWithAdjustments = nullptr;
337 return State;
338 }
339 Result = InitWithAdjustments;
340 } else {
341 // We need to create a region no matter what. Make sure we don't try to
342 // stuff a Loc into a non-pointer temporary region.
343 assert(!isa<Loc>(InitValWithAdjustments) ||
344 Loc::isLocType(Result->getType()) ||
345 Result->getType()->isMemberPointerType());
346 }
347
348 ProgramStateManager &StateMgr = State->getStateManager();
349 MemRegionManager &MRMgr = StateMgr.getRegionManager();
350 StoreManager &StoreMgr = StateMgr.getStoreManager();
351
352 // MaterializeTemporaryExpr may appear out of place, after a few field and
353 // base-class accesses have been made to the object, even though semantically
354 // it is the whole object that gets materialized and lifetime-extended.
355 //
356 // For example:
357 //
358 // `-MaterializeTemporaryExpr
359 // `-MemberExpr
360 // `-CXXTemporaryObjectExpr
361 //
362 // instead of the more natural
363 //
364 // `-MemberExpr
365 // `-MaterializeTemporaryExpr
366 // `-CXXTemporaryObjectExpr
367 //
368 // Use the usual methods for obtaining the expression of the base object,
369 // and record the adjustments that we need to make to obtain the sub-object
370 // that the whole expression 'Ex' refers to. This trick is usual,
371 // in the sense that CodeGen takes a similar route.
372
375
376 const Expr *Init = InitWithAdjustments->skipRValueSubobjectAdjustments(
377 CommaLHSs, Adjustments);
378
379 // Take the region for Init, i.e. for the whole object. If we do not remember
380 // the region in which the object originally was constructed, come up with
381 // a new temporary region out of thin air and copy the contents of the object
382 // (which are currently present in the Environment, because Init is an rvalue)
383 // into that region. This is not correct, but it is better than nothing.
384 const TypedValueRegion *TR = nullptr;
385 if (const auto *MT = dyn_cast<MaterializeTemporaryExpr>(Result)) {
386 if (std::optional<SVal> V = getObjectUnderConstruction(State, MT, LC)) {
387 State = finishObjectConstruction(State, MT, LC);
388 State = State->BindExpr(Result, LC, *V);
389 return State;
390 } else if (const ValueDecl *VD = MT->getExtendingDecl()) {
391 StorageDuration SD = MT->getStorageDuration();
392 assert(SD != SD_FullExpression);
393 // If this object is bound to a reference with static storage duration, we
394 // put it in a different region to prevent "address leakage" warnings.
395 if (SD == SD_Static || SD == SD_Thread) {
397 } else {
398 TR = MRMgr.getCXXLifetimeExtendedObjectRegion(Init, VD, LC);
399 }
400 } else {
401 assert(MT->getStorageDuration() == SD_FullExpression);
402 TR = MRMgr.getCXXTempObjectRegion(Init, LC);
403 }
404 } else {
405 TR = MRMgr.getCXXTempObjectRegion(Init, LC);
406 }
407
408 SVal Reg = loc::MemRegionVal(TR);
409 SVal BaseReg = Reg;
410
411 // Make the necessary adjustments to obtain the sub-object.
412 for (const SubobjectAdjustment &Adj : llvm::reverse(Adjustments)) {
413 switch (Adj.Kind) {
415 Reg = StoreMgr.evalDerivedToBase(Reg, Adj.DerivedToBase.BasePath);
416 break;
418 Reg = StoreMgr.getLValueField(Adj.Field, Reg);
419 break;
421 // FIXME: Unimplemented.
422 State = State->invalidateRegions(Reg, InitWithAdjustments,
423 currBldrCtx->blockCount(), LC, true,
424 nullptr, nullptr, nullptr);
425 return State;
426 }
427 }
428
429 // What remains is to copy the value of the object to the new region.
430 // FIXME: In other words, what we should always do is copy value of the
431 // Init expression (which corresponds to the bigger object) to the whole
432 // temporary region TR. However, this value is often no longer present
433 // in the Environment. If it has disappeared, we instead invalidate TR.
434 // Still, what we can do is assign the value of expression Ex (which
435 // corresponds to the sub-object) to the TR's sub-region Reg. At least,
436 // values inside Reg would be correct.
437 SVal InitVal = State->getSVal(Init, LC);
438 if (InitVal.isUnknown()) {
439 InitVal = getSValBuilder().conjureSymbolVal(Result, LC, Init->getType(),
440 currBldrCtx->blockCount());
441 State = State->bindLoc(BaseReg.castAs<Loc>(), InitVal, LC, false);
442
443 // Then we'd need to take the value that certainly exists and bind it
444 // over.
445 if (InitValWithAdjustments.isUnknown()) {
446 // Try to recover some path sensitivity in case we couldn't
447 // compute the value.
448 InitValWithAdjustments = getSValBuilder().conjureSymbolVal(
449 Result, LC, InitWithAdjustments->getType(),
450 currBldrCtx->blockCount());
451 }
452 State =
453 State->bindLoc(Reg.castAs<Loc>(), InitValWithAdjustments, LC, false);
454 } else {
455 State = State->bindLoc(BaseReg.castAs<Loc>(), InitVal, LC, false);
456 }
457
458 // The result expression would now point to the correct sub-region of the
459 // newly created temporary region. Do this last in order to getSVal of Init
460 // correctly in case (Result == Init).
461 if (Result->isGLValue()) {
462 State = State->BindExpr(Result, LC, Reg);
463 } else {
464 State = State->BindExpr(Result, LC, InitValWithAdjustments);
465 }
466
467 // Notify checkers once for two bindLoc()s.
468 State = processRegionChange(State, TR, LC);
469
470 if (OutRegionWithAdjustments)
471 *OutRegionWithAdjustments = cast<SubRegion>(Reg.getAsRegion());
472 return State;
473}
474
475ProgramStateRef ExprEngine::setIndexOfElementToConstruct(
476 ProgramStateRef State, const CXXConstructExpr *E,
477 const LocationContext *LCtx, unsigned Idx) {
478 auto Key = std::make_pair(E, LCtx->getStackFrame());
479
480 assert(!State->contains<IndexOfElementToConstruct>(Key) || Idx > 0);
481
482 return State->set<IndexOfElementToConstruct>(Key, Idx);
483}
484
485std::optional<unsigned>
487 const LocationContext *LCtx) {
488 const unsigned *V = State->get<PendingInitLoop>({E, LCtx->getStackFrame()});
489 return V ? std::make_optional(*V) : std::nullopt;
490}
491
492ProgramStateRef ExprEngine::removePendingInitLoop(ProgramStateRef State,
493 const CXXConstructExpr *E,
494 const LocationContext *LCtx) {
495 auto Key = std::make_pair(E, LCtx->getStackFrame());
496
497 assert(E && State->contains<PendingInitLoop>(Key));
498 return State->remove<PendingInitLoop>(Key);
499}
500
501ProgramStateRef ExprEngine::setPendingInitLoop(ProgramStateRef State,
502 const CXXConstructExpr *E,
503 const LocationContext *LCtx,
504 unsigned Size) {
505 auto Key = std::make_pair(E, LCtx->getStackFrame());
506
507 assert(!State->contains<PendingInitLoop>(Key) && Size > 0);
508
509 return State->set<PendingInitLoop>(Key, Size);
510}
511
512std::optional<unsigned>
514 const CXXConstructExpr *E,
515 const LocationContext *LCtx) {
516 const unsigned *V =
517 State->get<IndexOfElementToConstruct>({E, LCtx->getStackFrame()});
518 return V ? std::make_optional(*V) : std::nullopt;
519}
520
522ExprEngine::removeIndexOfElementToConstruct(ProgramStateRef State,
523 const CXXConstructExpr *E,
524 const LocationContext *LCtx) {
525 auto Key = std::make_pair(E, LCtx->getStackFrame());
526
527 assert(E && State->contains<IndexOfElementToConstruct>(Key));
528 return State->remove<IndexOfElementToConstruct>(Key);
529}
530
531std::optional<unsigned>
533 const LocationContext *LCtx) {
534 assert(LCtx && "LocationContext shouldn't be null!");
535
536 const unsigned *V =
537 State->get<PendingArrayDestruction>(LCtx->getStackFrame());
538 return V ? std::make_optional(*V) : std::nullopt;
539}
540
541ProgramStateRef ExprEngine::setPendingArrayDestruction(
542 ProgramStateRef State, const LocationContext *LCtx, unsigned Idx) {
543 assert(LCtx && "LocationContext shouldn't be null!");
544
545 auto Key = LCtx->getStackFrame();
546
547 return State->set<PendingArrayDestruction>(Key, Idx);
548}
549
551ExprEngine::removePendingArrayDestruction(ProgramStateRef State,
552 const LocationContext *LCtx) {
553 assert(LCtx && "LocationContext shouldn't be null!");
554
555 auto Key = LCtx->getStackFrame();
556
557 assert(LCtx && State->contains<PendingArrayDestruction>(Key));
558 return State->remove<PendingArrayDestruction>(Key);
559}
560
562ExprEngine::addObjectUnderConstruction(ProgramStateRef State,
563 const ConstructionContextItem &Item,
564 const LocationContext *LC, SVal V) {
565 ConstructedObjectKey Key(Item, LC->getStackFrame());
566
567 const Expr *Init = nullptr;
568
569 if (auto DS = dyn_cast_or_null<DeclStmt>(Item.getStmtOrNull())) {
570 if (auto VD = dyn_cast_or_null<VarDecl>(DS->getSingleDecl()))
571 Init = VD->getInit();
572 }
573
574 if (auto LE = dyn_cast_or_null<LambdaExpr>(Item.getStmtOrNull()))
575 Init = *(LE->capture_init_begin() + Item.getIndex());
576
577 if (!Init && !Item.getStmtOrNull())
579
580 // In an ArrayInitLoopExpr the real initializer is returned by
581 // getSubExpr(). Note that AILEs can be nested in case of
582 // multidimesnional arrays.
583 if (const auto *AILE = dyn_cast_or_null<ArrayInitLoopExpr>(Init))
585
586 // FIXME: Currently the state might already contain the marker due to
587 // incorrect handling of temporaries bound to default parameters.
588 // The state will already contain the marker if we construct elements
589 // in an array, as we visit the same statement multiple times before
590 // the array declaration. The marker is removed when we exit the
591 // constructor call.
592 assert((!State->get<ObjectsUnderConstruction>(Key) ||
593 Key.getItem().getKind() ==
595 State->contains<IndexOfElementToConstruct>(
596 {dyn_cast_or_null<CXXConstructExpr>(Init), LC})) &&
597 "The object is already marked as `UnderConstruction`, when it's not "
598 "supposed to!");
599 return State->set<ObjectsUnderConstruction>(Key, V);
600}
601
602std::optional<SVal>
604 const ConstructionContextItem &Item,
605 const LocationContext *LC) {
606 ConstructedObjectKey Key(Item, LC->getStackFrame());
607 const SVal *V = State->get<ObjectsUnderConstruction>(Key);
608 return V ? std::make_optional(*V) : std::nullopt;
609}
610
612ExprEngine::finishObjectConstruction(ProgramStateRef State,
613 const ConstructionContextItem &Item,
614 const LocationContext *LC) {
615 ConstructedObjectKey Key(Item, LC->getStackFrame());
616 assert(State->contains<ObjectsUnderConstruction>(Key));
617 return State->remove<ObjectsUnderConstruction>(Key);
618}
619
620ProgramStateRef ExprEngine::elideDestructor(ProgramStateRef State,
621 const CXXBindTemporaryExpr *BTE,
622 const LocationContext *LC) {
623 ConstructedObjectKey Key({BTE, /*IsElided=*/true}, LC);
624 // FIXME: Currently the state might already contain the marker due to
625 // incorrect handling of temporaries bound to default parameters.
626 return State->set<ObjectsUnderConstruction>(Key, UnknownVal());
627}
628
630ExprEngine::cleanupElidedDestructor(ProgramStateRef State,
631 const CXXBindTemporaryExpr *BTE,
632 const LocationContext *LC) {
633 ConstructedObjectKey Key({BTE, /*IsElided=*/true}, LC);
634 assert(State->contains<ObjectsUnderConstruction>(Key));
635 return State->remove<ObjectsUnderConstruction>(Key);
636}
637
638bool ExprEngine::isDestructorElided(ProgramStateRef State,
639 const CXXBindTemporaryExpr *BTE,
640 const LocationContext *LC) {
641 ConstructedObjectKey Key({BTE, /*IsElided=*/true}, LC);
642 return State->contains<ObjectsUnderConstruction>(Key);
643}
644
645bool ExprEngine::areAllObjectsFullyConstructed(ProgramStateRef State,
646 const LocationContext *FromLC,
647 const LocationContext *ToLC) {
648 const LocationContext *LC = FromLC;
649 while (LC != ToLC) {
650 assert(LC && "ToLC must be a parent of FromLC!");
651 for (auto I : State->get<ObjectsUnderConstruction>())
652 if (I.first.getLocationContext() == LC)
653 return false;
654
655 LC = LC->getParent();
656 }
657 return true;
658}
659
660
661//===----------------------------------------------------------------------===//
662// Top-level transfer function logic (Dispatcher).
663//===----------------------------------------------------------------------===//
664
665/// evalAssume - Called by ConstraintManager. Used to call checker-specific
666/// logic for handling assumptions on symbolic values.
668 SVal cond, bool assumption) {
669 return getCheckerManager().runCheckersForEvalAssume(state, cond, assumption);
670}
671
674 const InvalidatedSymbols *invalidated,
677 const LocationContext *LCtx,
678 const CallEvent *Call) {
679 return getCheckerManager().runCheckersForRegionChanges(state, invalidated,
680 Explicits, Regions,
681 LCtx, Call);
682}
683
684static void
686 const char *NL, const LocationContext *LCtx,
687 unsigned int Space = 0, bool IsDot = false) {
688 PrintingPolicy PP =
690
691 ++Space;
692 bool HasItem = false;
693
694 // Store the last key.
695 const ConstructedObjectKey *LastKey = nullptr;
696 for (const auto &I : State->get<ObjectsUnderConstruction>()) {
697 const ConstructedObjectKey &Key = I.first;
698 if (Key.getLocationContext() != LCtx)
699 continue;
700
701 if (!HasItem) {
702 Out << '[' << NL;
703 HasItem = true;
704 }
705
706 LastKey = &Key;
707 }
708
709 for (const auto &I : State->get<ObjectsUnderConstruction>()) {
710 const ConstructedObjectKey &Key = I.first;
711 SVal Value = I.second;
712 if (Key.getLocationContext() != LCtx)
713 continue;
714
715 Indent(Out, Space, IsDot) << "{ ";
716 Key.printJson(Out, nullptr, PP);
717 Out << ", \"value\": \"" << Value << "\" }";
718
719 if (&Key != LastKey)
720 Out << ',';
721 Out << NL;
722 }
723
724 if (HasItem)
725 Indent(Out, --Space, IsDot) << ']'; // End of "location_context".
726 else {
727 Out << "null ";
728 }
729}
730
732 raw_ostream &Out, ProgramStateRef State, const char *NL,
733 const LocationContext *LCtx, unsigned int Space = 0, bool IsDot = false) {
734 using KeyT = std::pair<const Expr *, const LocationContext *>;
735
736 const auto &Context = LCtx->getAnalysisDeclContext()->getASTContext();
737 PrintingPolicy PP = Context.getPrintingPolicy();
738
739 ++Space;
740 bool HasItem = false;
741
742 // Store the last key.
743 KeyT LastKey;
744 for (const auto &I : State->get<IndexOfElementToConstruct>()) {
745 const KeyT &Key = I.first;
746 if (Key.second != LCtx)
747 continue;
748
749 if (!HasItem) {
750 Out << '[' << NL;
751 HasItem = true;
752 }
753
754 LastKey = Key;
755 }
756
757 for (const auto &I : State->get<IndexOfElementToConstruct>()) {
758 const KeyT &Key = I.first;
759 unsigned Value = I.second;
760 if (Key.second != LCtx)
761 continue;
762
763 Indent(Out, Space, IsDot) << "{ ";
764
765 // Expr
766 const Expr *E = Key.first;
767 Out << "\"stmt_id\": " << E->getID(Context);
768
769 // Kind
770 Out << ", \"kind\": null";
771
772 // Pretty-print
773 Out << ", \"pretty\": ";
774 Out << "\"" << E->getStmtClassName() << ' '
775 << E->getSourceRange().printToString(Context.getSourceManager()) << " '"
777 Out << "'\"";
778
779 Out << ", \"value\": \"Current index: " << Value - 1 << "\" }";
780
781 if (Key != LastKey)
782 Out << ',';
783 Out << NL;
784 }
785
786 if (HasItem)
787 Indent(Out, --Space, IsDot) << ']'; // End of "location_context".
788 else {
789 Out << "null ";
790 }
791}
792
793static void printPendingInitLoopJson(raw_ostream &Out, ProgramStateRef State,
794 const char *NL,
795 const LocationContext *LCtx,
796 unsigned int Space = 0,
797 bool IsDot = false) {
798 using KeyT = std::pair<const CXXConstructExpr *, const LocationContext *>;
799
800 const auto &Context = LCtx->getAnalysisDeclContext()->getASTContext();
801 PrintingPolicy PP = Context.getPrintingPolicy();
802
803 ++Space;
804 bool HasItem = false;
805
806 // Store the last key.
807 KeyT LastKey;
808 for (const auto &I : State->get<PendingInitLoop>()) {
809 const KeyT &Key = I.first;
810 if (Key.second != LCtx)
811 continue;
812
813 if (!HasItem) {
814 Out << '[' << NL;
815 HasItem = true;
816 }
817
818 LastKey = Key;
819 }
820
821 for (const auto &I : State->get<PendingInitLoop>()) {
822 const KeyT &Key = I.first;
823 unsigned Value = I.second;
824 if (Key.second != LCtx)
825 continue;
826
827 Indent(Out, Space, IsDot) << "{ ";
828
829 const CXXConstructExpr *E = Key.first;
830 Out << "\"stmt_id\": " << E->getID(Context);
831
832 Out << ", \"kind\": null";
833 Out << ", \"pretty\": ";
834 Out << '\"' << E->getStmtClassName() << ' '
835 << E->getSourceRange().printToString(Context.getSourceManager()) << " '"
837 Out << "'\"";
838
839 Out << ", \"value\": \"Flattened size: " << Value << "\"}";
840
841 if (Key != LastKey)
842 Out << ',';
843 Out << NL;
844 }
845
846 if (HasItem)
847 Indent(Out, --Space, IsDot) << ']'; // End of "location_context".
848 else {
849 Out << "null ";
850 }
851}
852
853static void
855 const char *NL, const LocationContext *LCtx,
856 unsigned int Space = 0, bool IsDot = false) {
857 using KeyT = const LocationContext *;
858
859 ++Space;
860 bool HasItem = false;
861
862 // Store the last key.
863 KeyT LastKey = nullptr;
864 for (const auto &I : State->get<PendingArrayDestruction>()) {
865 const KeyT &Key = I.first;
866 if (Key != LCtx)
867 continue;
868
869 if (!HasItem) {
870 Out << '[' << NL;
871 HasItem = true;
872 }
873
874 LastKey = Key;
875 }
876
877 for (const auto &I : State->get<PendingArrayDestruction>()) {
878 const KeyT &Key = I.first;
879 if (Key != LCtx)
880 continue;
881
882 Indent(Out, Space, IsDot) << "{ ";
883
884 Out << "\"stmt_id\": null";
885 Out << ", \"kind\": null";
886 Out << ", \"pretty\": \"Current index: \"";
887 Out << ", \"value\": \"" << I.second << "\" }";
888
889 if (Key != LastKey)
890 Out << ',';
891 Out << NL;
892 }
893
894 if (HasItem)
895 Indent(Out, --Space, IsDot) << ']'; // End of "location_context".
896 else {
897 Out << "null ";
898 }
899}
900
901/// A helper function to generalize program state trait printing.
902/// The function invokes Printer as 'Printer(Out, State, NL, LC, Space, IsDot,
903/// std::forward<Args>(args)...)'. \n One possible type for Printer is
904/// 'void()(raw_ostream &, ProgramStateRef, const char *, const LocationContext
905/// *, unsigned int, bool, ...)' \n \param Trait The state trait to be printed.
906/// \param Printer A void function that prints Trait.
907/// \param Args An additional parameter pack that is passed to Print upon
908/// invocation.
909template <typename Trait, typename Printer, typename... Args>
911 raw_ostream &Out, ProgramStateRef State, const LocationContext *LCtx,
912 const char *NL, unsigned int Space, bool IsDot,
913 const char *jsonPropertyName, Printer printer, Args &&...args) {
914
915 using RequiredType =
916 void (*)(raw_ostream &, ProgramStateRef, const char *,
917 const LocationContext *, unsigned int, bool, Args &&...);
918
919 // Try to do as much compile time checking as possible.
920 // FIXME: check for invocable instead of function?
921 static_assert(std::is_function_v<std::remove_pointer_t<Printer>>,
922 "Printer is not a function!");
923 static_assert(std::is_convertible_v<Printer, RequiredType>,
924 "Printer doesn't have the required type!");
925
926 if (LCtx && !State->get<Trait>().isEmpty()) {
927 Indent(Out, Space, IsDot) << '\"' << jsonPropertyName << "\": ";
928 ++Space;
929 Out << '[' << NL;
930 LCtx->printJson(Out, NL, Space, IsDot, [&](const LocationContext *LC) {
931 printer(Out, State, NL, LC, Space, IsDot, std::forward<Args>(args)...);
932 });
933
934 --Space;
935 Indent(Out, Space, IsDot) << "]," << NL; // End of "jsonPropertyName".
936 }
937}
938
939void ExprEngine::printJson(raw_ostream &Out, ProgramStateRef State,
940 const LocationContext *LCtx, const char *NL,
941 unsigned int Space, bool IsDot) const {
942
943 printStateTraitWithLocationContextJson<ObjectsUnderConstruction>(
944 Out, State, LCtx, NL, Space, IsDot, "constructing_objects",
946 printStateTraitWithLocationContextJson<IndexOfElementToConstruct>(
947 Out, State, LCtx, NL, Space, IsDot, "index_of_element",
949 printStateTraitWithLocationContextJson<PendingInitLoop>(
950 Out, State, LCtx, NL, Space, IsDot, "pending_init_loops",
952 printStateTraitWithLocationContextJson<PendingArrayDestruction>(
953 Out, State, LCtx, NL, Space, IsDot, "pending_destructors",
955
956 getCheckerManager().runCheckersForPrintStateJson(Out, State, NL, Space,
957 IsDot);
958}
959
961 // This prints the name of the top-level function if we crash.
964}
965
967 unsigned StmtIdx, NodeBuilderContext *Ctx) {
969 currStmtIdx = StmtIdx;
970 currBldrCtx = Ctx;
971
972 switch (E.getKind()) {
976 ProcessStmt(E.castAs<CFGStmt>().getStmt(), Pred);
977 return;
979 ProcessInitializer(E.castAs<CFGInitializer>(), Pred);
980 return;
983 Pred);
984 return;
990 ProcessImplicitDtor(E.castAs<CFGImplicitDtor>(), Pred);
991 return;
993 ProcessLoopExit(E.castAs<CFGLoopExit>().getLoopStmt(), Pred);
994 return;
999 return;
1000 }
1001}
1002
1004 const Stmt *S,
1005 const ExplodedNode *Pred,
1006 const LocationContext *LC) {
1007 // Are we never purging state values?
1008 if (AMgr.options.AnalysisPurgeOpt == PurgeNone)
1009 return false;
1010
1011 // Is this the beginning of a basic block?
1012 if (Pred->getLocation().getAs<BlockEntrance>())
1013 return true;
1014
1015 // Is this on a non-expression?
1016 if (!isa<Expr>(S))
1017 return true;
1018
1019 // Run before processing a call.
1020 if (CallEvent::isCallStmt(S))
1021 return true;
1022
1023 // Is this an expression that is consumed by another expression? If so,
1024 // postpone cleaning out the state.
1026 return !PM.isConsumedExpr(cast<Expr>(S));
1027}
1028
1030 const Stmt *ReferenceStmt,
1031 const LocationContext *LC,
1032 const Stmt *DiagnosticStmt,
1035 ReferenceStmt == nullptr || isa<ReturnStmt>(ReferenceStmt))
1036 && "PostStmt is not generally supported by the SymbolReaper yet");
1037 assert(LC && "Must pass the current (or expiring) LocationContext");
1038
1039 if (!DiagnosticStmt) {
1040 DiagnosticStmt = ReferenceStmt;
1041 assert(DiagnosticStmt && "Required for clearing a LocationContext");
1042 }
1043
1044 NumRemoveDeadBindings++;
1045 ProgramStateRef CleanedState = Pred->getState();
1046
1047 // LC is the location context being destroyed, but SymbolReaper wants a
1048 // location context that is still live. (If this is the top-level stack
1049 // frame, this will be null.)
1050 if (!ReferenceStmt) {
1052 "Use PostStmtPurgeDeadSymbolsKind for clearing a LocationContext");
1053 LC = LC->getParent();
1054 }
1055
1056 const StackFrameContext *SFC = LC ? LC->getStackFrame() : nullptr;
1057 SymbolReaper SymReaper(SFC, ReferenceStmt, SymMgr, getStoreManager());
1058
1059 for (auto I : CleanedState->get<ObjectsUnderConstruction>()) {
1060 if (SymbolRef Sym = I.second.getAsSymbol())
1061 SymReaper.markLive(Sym);
1062 if (const MemRegion *MR = I.second.getAsRegion())
1063 SymReaper.markLive(MR);
1064 }
1065
1066 getCheckerManager().runCheckersForLiveSymbols(CleanedState, SymReaper);
1067
1068 // Create a state in which dead bindings are removed from the environment
1069 // and the store. TODO: The function should just return new env and store,
1070 // not a new state.
1071 CleanedState = StateMgr.removeDeadBindingsFromEnvironmentAndStore(
1072 CleanedState, SFC, SymReaper);
1073
1074 // Process any special transfer function for dead symbols.
1075 // Call checkers with the non-cleaned state so that they could query the
1076 // values of the soon to be dead symbols.
1077 ExplodedNodeSet CheckedSet;
1078 getCheckerManager().runCheckersForDeadSymbols(CheckedSet, Pred, SymReaper,
1079 DiagnosticStmt, *this, K);
1080
1081 // For each node in CheckedSet, generate CleanedNodes that have the
1082 // environment, the store, and the constraints cleaned up but have the
1083 // user-supplied states as the predecessors.
1084 StmtNodeBuilder Bldr(CheckedSet, Out, *currBldrCtx);
1085 for (const auto I : CheckedSet) {
1086 ProgramStateRef CheckerState = I->getState();
1087
1088 // The constraint manager has not been cleaned up yet, so clean up now.
1089 CheckerState =
1090 getConstraintManager().removeDeadBindings(CheckerState, SymReaper);
1091
1092 assert(StateMgr.haveEqualEnvironments(CheckerState, Pred->getState()) &&
1093 "Checkers are not allowed to modify the Environment as a part of "
1094 "checkDeadSymbols processing.");
1095 assert(StateMgr.haveEqualStores(CheckerState, Pred->getState()) &&
1096 "Checkers are not allowed to modify the Store as a part of "
1097 "checkDeadSymbols processing.");
1098
1099 // Create a state based on CleanedState with CheckerState GDM and
1100 // generate a transition to that state.
1101 ProgramStateRef CleanedCheckerSt =
1102 StateMgr.getPersistentStateWithGDM(CleanedState, CheckerState);
1103 Bldr.generateNode(DiagnosticStmt, I, CleanedCheckerSt, cleanupNodeTag(), K);
1104 }
1105}
1106
1108 static SimpleProgramPointTag cleanupTag(TagProviderName, "Clean Node");
1109 return &cleanupTag;
1110}
1111
1112void ExprEngine::ProcessStmt(const Stmt *currStmt, ExplodedNode *Pred) {
1113 // Reclaim any unnecessary nodes in the ExplodedGraph.
1115
1116 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
1117 currStmt->getBeginLoc(),
1118 "Error evaluating statement");
1119
1120 // Remove dead bindings and symbols.
1121 ExplodedNodeSet CleanedStates;
1122 if (shouldRemoveDeadBindings(AMgr, currStmt, Pred,
1123 Pred->getLocationContext())) {
1124 removeDead(Pred, CleanedStates, currStmt,
1125 Pred->getLocationContext());
1126 } else
1127 CleanedStates.Add(Pred);
1128
1129 // Visit the statement.
1130 ExplodedNodeSet Dst;
1131 for (const auto I : CleanedStates) {
1132 ExplodedNodeSet DstI;
1133 // Visit the statement.
1134 Visit(currStmt, I, DstI);
1135 Dst.insert(DstI);
1136 }
1137
1138 // Enqueue the new nodes onto the work list.
1139 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1140}
1141
1143 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
1144 S->getBeginLoc(),
1145 "Error evaluating end of the loop");
1146 ExplodedNodeSet Dst;
1147 Dst.Add(Pred);
1148 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1149 ProgramStateRef NewState = Pred->getState();
1150
1151 if(AMgr.options.ShouldUnrollLoops)
1152 NewState = processLoopEnd(S, NewState);
1153
1154 LoopExit PP(S, Pred->getLocationContext());
1155 Bldr.generateNode(PP, NewState, Pred);
1156 // Enqueue the new nodes onto the work list.
1157 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1158}
1159
1161 ExplodedNode *Pred) {
1162 const CXXCtorInitializer *BMI = CFGInit.getInitializer();
1163 const Expr *Init = BMI->getInit()->IgnoreImplicit();
1164 const LocationContext *LC = Pred->getLocationContext();
1165
1166 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
1167 BMI->getSourceLocation(),
1168 "Error evaluating initializer");
1169
1170 // We don't clean up dead bindings here.
1171 const auto *stackFrame = cast<StackFrameContext>(Pred->getLocationContext());
1172 const auto *decl = cast<CXXConstructorDecl>(stackFrame->getDecl());
1173
1174 ProgramStateRef State = Pred->getState();
1175 SVal thisVal = State->getSVal(svalBuilder.getCXXThis(decl, stackFrame));
1176
1177 ExplodedNodeSet Tmp;
1178 SVal FieldLoc;
1179
1180 // Evaluate the initializer, if necessary
1181 if (BMI->isAnyMemberInitializer()) {
1182 // Constructors build the object directly in the field,
1183 // but non-objects must be copied in from the initializer.
1184 if (getObjectUnderConstruction(State, BMI, LC)) {
1185 // The field was directly constructed, so there is no need to bind.
1186 // But we still need to stop tracking the object under construction.
1187 State = finishObjectConstruction(State, BMI, LC);
1188 NodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
1189 PostStore PS(Init, LC, /*Loc*/ nullptr, /*tag*/ nullptr);
1190 Bldr.generateNode(PS, State, Pred);
1191 } else {
1192 const ValueDecl *Field;
1193 if (BMI->isIndirectMemberInitializer()) {
1194 Field = BMI->getIndirectMember();
1195 FieldLoc = State->getLValue(BMI->getIndirectMember(), thisVal);
1196 } else {
1197 Field = BMI->getMember();
1198 FieldLoc = State->getLValue(BMI->getMember(), thisVal);
1199 }
1200
1201 SVal InitVal;
1202 if (Init->getType()->isArrayType()) {
1203 // Handle arrays of trivial type. We can represent this with a
1204 // primitive load/copy from the base array region.
1205 const ArraySubscriptExpr *ASE;
1206 while ((ASE = dyn_cast<ArraySubscriptExpr>(Init)))
1207 Init = ASE->getBase()->IgnoreImplicit();
1208
1209 InitVal = State->getSVal(Init, stackFrame);
1210
1211 // If we fail to get the value for some reason, use a symbolic value.
1212 if (InitVal.isUnknownOrUndef()) {
1213 SValBuilder &SVB = getSValBuilder();
1214 InitVal = SVB.conjureSymbolVal(BMI->getInit(), stackFrame,
1215 Field->getType(),
1216 currBldrCtx->blockCount());
1217 }
1218 } else {
1219 InitVal = State->getSVal(BMI->getInit(), stackFrame);
1220 }
1221
1222 PostInitializer PP(BMI, FieldLoc.getAsRegion(), stackFrame);
1223 evalBind(Tmp, Init, Pred, FieldLoc, InitVal, /*isInit=*/true, &PP);
1224 }
1225 } else if (BMI->isBaseInitializer() && isa<InitListExpr>(Init)) {
1226 // When the base class is initialized with an initialization list and the
1227 // base class does not have a ctor, there will not be a CXXConstructExpr to
1228 // initialize the base region. Hence, we need to make the bind for it.
1230 thisVal, QualType(BMI->getBaseClass(), 0), BMI->isBaseVirtual());
1231 SVal InitVal = State->getSVal(Init, stackFrame);
1232 evalBind(Tmp, Init, Pred, BaseLoc, InitVal, /*isInit=*/true);
1233 } else {
1234 assert(BMI->isBaseInitializer() || BMI->isDelegatingInitializer());
1235 Tmp.insert(Pred);
1236 // We already did all the work when visiting the CXXConstructExpr.
1237 }
1238
1239 // Construct PostInitializer nodes whether the state changed or not,
1240 // so that the diagnostics don't get confused.
1241 PostInitializer PP(BMI, FieldLoc.getAsRegion(), stackFrame);
1242 ExplodedNodeSet Dst;
1243 NodeBuilder Bldr(Tmp, Dst, *currBldrCtx);
1244 for (const auto I : Tmp) {
1245 ProgramStateRef State = I->getState();
1246 Bldr.generateNode(PP, State, I);
1247 }
1248
1249 // Enqueue the new nodes onto the work list.
1250 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1251}
1252
1253std::pair<ProgramStateRef, uint64_t>
1254ExprEngine::prepareStateForArrayDestruction(const ProgramStateRef State,
1255 const MemRegion *Region,
1256 const QualType &ElementTy,
1257 const LocationContext *LCtx,
1258 SVal *ElementCountVal) {
1259 assert(Region != nullptr && "Not-null region expected");
1260
1261 QualType Ty = ElementTy.getDesugaredType(getContext());
1262 while (const auto *NTy = dyn_cast<ArrayType>(Ty))
1263 Ty = NTy->getElementType().getDesugaredType(getContext());
1264
1265 auto ElementCount = getDynamicElementCount(State, Region, svalBuilder, Ty);
1266
1267 if (ElementCountVal)
1268 *ElementCountVal = ElementCount;
1269
1270 // Note: the destructors are called in reverse order.
1271 unsigned Idx = 0;
1272 if (auto OptionalIdx = getPendingArrayDestruction(State, LCtx)) {
1273 Idx = *OptionalIdx;
1274 } else {
1275 // The element count is either unknown, or an SVal that's not an integer.
1276 if (!ElementCount.isConstant())
1277 return {State, 0};
1278
1279 Idx = ElementCount.getAsInteger()->getLimitedValue();
1280 }
1281
1282 if (Idx == 0)
1283 return {State, 0};
1284
1285 --Idx;
1286
1287 return {setPendingArrayDestruction(State, LCtx, Idx), Idx};
1288}
1289
1291 ExplodedNode *Pred) {
1292 ExplodedNodeSet Dst;
1293 switch (D.getKind()) {
1295 ProcessAutomaticObjDtor(D.castAs<CFGAutomaticObjDtor>(), Pred, Dst);
1296 break;
1298 ProcessBaseDtor(D.castAs<CFGBaseDtor>(), Pred, Dst);
1299 break;
1301 ProcessMemberDtor(D.castAs<CFGMemberDtor>(), Pred, Dst);
1302 break;
1304 ProcessTemporaryDtor(D.castAs<CFGTemporaryDtor>(), Pred, Dst);
1305 break;
1307 ProcessDeleteDtor(D.castAs<CFGDeleteDtor>(), Pred, Dst);
1308 break;
1309 default:
1310 llvm_unreachable("Unexpected dtor kind.");
1311 }
1312
1313 // Enqueue the new nodes onto the work list.
1314 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1315}
1316
1318 ExplodedNode *Pred) {
1319 ExplodedNodeSet Dst;
1321 AnalyzerOptions &Opts = AMgr.options;
1322 // TODO: We're not evaluating allocators for all cases just yet as
1323 // we're not handling the return value correctly, which causes false
1324 // positives when the alpha.cplusplus.NewDeleteLeaks check is on.
1325 if (Opts.MayInlineCXXAllocator)
1326 VisitCXXNewAllocatorCall(NE, Pred, Dst);
1327 else {
1328 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1329 const LocationContext *LCtx = Pred->getLocationContext();
1330 PostImplicitCall PP(NE->getOperatorNew(), NE->getBeginLoc(), LCtx,
1332 Bldr.generateNode(PP, Pred->getState(), Pred);
1333 }
1334 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1335}
1336
1338 ExplodedNode *Pred,
1339 ExplodedNodeSet &Dst) {
1340 const auto *DtorDecl = Dtor.getDestructorDecl(getContext());
1341 const VarDecl *varDecl = Dtor.getVarDecl();
1342 QualType varType = varDecl->getType();
1343
1344 ProgramStateRef state = Pred->getState();
1345 const LocationContext *LCtx = Pred->getLocationContext();
1346
1347 SVal dest = state->getLValue(varDecl, LCtx);
1348 const MemRegion *Region = dest.castAs<loc::MemRegionVal>().getRegion();
1349
1350 if (varType->isReferenceType()) {
1351 const MemRegion *ValueRegion = state->getSVal(Region).getAsRegion();
1352 if (!ValueRegion) {
1353 // FIXME: This should not happen. The language guarantees a presence
1354 // of a valid initializer here, so the reference shall not be undefined.
1355 // It seems that we're calling destructors over variables that
1356 // were not initialized yet.
1357 return;
1358 }
1359 Region = ValueRegion->getBaseRegion();
1360 varType = cast<TypedValueRegion>(Region)->getValueType();
1361 }
1362
1363 unsigned Idx = 0;
1364 if (isa<ArrayType>(varType)) {
1365 SVal ElementCount;
1366 std::tie(state, Idx) = prepareStateForArrayDestruction(
1367 state, Region, varType, LCtx, &ElementCount);
1368
1369 if (ElementCount.isConstant()) {
1370 uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();
1371 assert(ArrayLength &&
1372 "An automatic dtor for a 0 length array shouldn't be triggered!");
1373
1374 // Still handle this case if we don't have assertions enabled.
1375 if (!ArrayLength) {
1376 static SimpleProgramPointTag PT(
1377 "ExprEngine", "Skipping automatic 0 length array destruction, "
1378 "which shouldn't be in the CFG.");
1379 PostImplicitCall PP(DtorDecl, varDecl->getLocation(), LCtx,
1380 getCFGElementRef(), &PT);
1381 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1382 Bldr.generateSink(PP, Pred->getState(), Pred);
1383 return;
1384 }
1385 }
1386 }
1387
1388 EvalCallOptions CallOpts;
1389 Region = makeElementRegion(state, loc::MemRegionVal(Region), varType,
1390 CallOpts.IsArrayCtorOrDtor, Idx)
1391 .getAsRegion();
1392
1393 NodeBuilder Bldr(Pred, Dst, getBuilderContext());
1394
1395 static SimpleProgramPointTag PT("ExprEngine",
1396 "Prepare for object destruction");
1397 PreImplicitCall PP(DtorDecl, varDecl->getLocation(), LCtx, getCFGElementRef(),
1398 &PT);
1399 Pred = Bldr.generateNode(PP, state, Pred);
1400
1401 if (!Pred)
1402 return;
1403 Bldr.takeNodes(Pred);
1404
1405 VisitCXXDestructor(varType, Region, Dtor.getTriggerStmt(),
1406 /*IsBase=*/false, Pred, Dst, CallOpts);
1407}
1408
1410 ExplodedNode *Pred,
1411 ExplodedNodeSet &Dst) {
1412 ProgramStateRef State = Pred->getState();
1413 const LocationContext *LCtx = Pred->getLocationContext();
1414 const CXXDeleteExpr *DE = Dtor.getDeleteExpr();
1415 const Stmt *Arg = DE->getArgument();
1416 QualType DTy = DE->getDestroyedType();
1417 SVal ArgVal = State->getSVal(Arg, LCtx);
1418
1419 // If the argument to delete is known to be a null value,
1420 // don't run destructor.
1421 if (State->isNull(ArgVal).isConstrainedTrue()) {
1423 const CXXRecordDecl *RD = BTy->getAsCXXRecordDecl();
1424 const CXXDestructorDecl *Dtor = RD->getDestructor();
1425
1426 PostImplicitCall PP(Dtor, DE->getBeginLoc(), LCtx, getCFGElementRef());
1427 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1428 Bldr.generateNode(PP, Pred->getState(), Pred);
1429 return;
1430 }
1431
1432 auto getDtorDecl = [](const QualType &DTy) {
1433 const CXXRecordDecl *RD = DTy->getAsCXXRecordDecl();
1434 return RD->getDestructor();
1435 };
1436
1437 unsigned Idx = 0;
1438 EvalCallOptions CallOpts;
1439 const MemRegion *ArgR = ArgVal.getAsRegion();
1440
1441 if (DE->isArrayForm()) {
1442 CallOpts.IsArrayCtorOrDtor = true;
1443 // Yes, it may even be a multi-dimensional array.
1444 while (const auto *AT = getContext().getAsArrayType(DTy))
1445 DTy = AT->getElementType();
1446
1447 if (ArgR) {
1448 SVal ElementCount;
1449 std::tie(State, Idx) = prepareStateForArrayDestruction(
1450 State, ArgR, DTy, LCtx, &ElementCount);
1451
1452 // If we're about to destruct a 0 length array, don't run any of the
1453 // destructors.
1454 if (ElementCount.isConstant() &&
1455 ElementCount.getAsInteger()->getLimitedValue() == 0) {
1456
1457 static SimpleProgramPointTag PT(
1458 "ExprEngine", "Skipping 0 length array delete destruction");
1459 PostImplicitCall PP(getDtorDecl(DTy), DE->getBeginLoc(), LCtx,
1460 getCFGElementRef(), &PT);
1461 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1462 Bldr.generateNode(PP, Pred->getState(), Pred);
1463 return;
1464 }
1465
1466 ArgR = State->getLValue(DTy, svalBuilder.makeArrayIndex(Idx), ArgVal)
1467 .getAsRegion();
1468 }
1469 }
1470
1471 NodeBuilder Bldr(Pred, Dst, getBuilderContext());
1472 static SimpleProgramPointTag PT("ExprEngine",
1473 "Prepare for object destruction");
1474 PreImplicitCall PP(getDtorDecl(DTy), DE->getBeginLoc(), LCtx,
1475 getCFGElementRef(), &PT);
1476 Pred = Bldr.generateNode(PP, State, Pred);
1477
1478 if (!Pred)
1479 return;
1480 Bldr.takeNodes(Pred);
1481
1482 VisitCXXDestructor(DTy, ArgR, DE, /*IsBase=*/false, Pred, Dst, CallOpts);
1483}
1484
1486 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
1487 const LocationContext *LCtx = Pred->getLocationContext();
1488
1489 const auto *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl());
1490 Loc ThisPtr = getSValBuilder().getCXXThis(CurDtor,
1491 LCtx->getStackFrame());
1492 SVal ThisVal = Pred->getState()->getSVal(ThisPtr);
1493
1494 // Create the base object region.
1495 const CXXBaseSpecifier *Base = D.getBaseSpecifier();
1496 QualType BaseTy = Base->getType();
1497 SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy,
1498 Base->isVirtual());
1499
1500 EvalCallOptions CallOpts;
1501 VisitCXXDestructor(BaseTy, BaseVal.getAsRegion(), CurDtor->getBody(),
1502 /*IsBase=*/true, Pred, Dst, CallOpts);
1503}
1504
1506 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
1507 const auto *DtorDecl = D.getDestructorDecl(getContext());
1508 const FieldDecl *Member = D.getFieldDecl();
1509 QualType T = Member->getType();
1510 ProgramStateRef State = Pred->getState();
1511 const LocationContext *LCtx = Pred->getLocationContext();
1512
1513 const auto *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl());
1514 Loc ThisStorageLoc =
1515 getSValBuilder().getCXXThis(CurDtor, LCtx->getStackFrame());
1516 Loc ThisLoc = State->getSVal(ThisStorageLoc).castAs<Loc>();
1517 SVal FieldVal = State->getLValue(Member, ThisLoc);
1518
1519 unsigned Idx = 0;
1520 if (isa<ArrayType>(T)) {
1521 SVal ElementCount;
1522 std::tie(State, Idx) = prepareStateForArrayDestruction(
1523 State, FieldVal.getAsRegion(), T, LCtx, &ElementCount);
1524
1525 if (ElementCount.isConstant()) {
1526 uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();
1527 assert(ArrayLength &&
1528 "A member dtor for a 0 length array shouldn't be triggered!");
1529
1530 // Still handle this case if we don't have assertions enabled.
1531 if (!ArrayLength) {
1532 static SimpleProgramPointTag PT(
1533 "ExprEngine", "Skipping member 0 length array destruction, which "
1534 "shouldn't be in the CFG.");
1535 PostImplicitCall PP(DtorDecl, Member->getLocation(), LCtx,
1536 getCFGElementRef(), &PT);
1537 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1538 Bldr.generateSink(PP, Pred->getState(), Pred);
1539 return;
1540 }
1541 }
1542 }
1543
1544 EvalCallOptions CallOpts;
1545 FieldVal =
1546 makeElementRegion(State, FieldVal, T, CallOpts.IsArrayCtorOrDtor, Idx);
1547
1548 NodeBuilder Bldr(Pred, Dst, getBuilderContext());
1549
1550 static SimpleProgramPointTag PT("ExprEngine",
1551 "Prepare for object destruction");
1552 PreImplicitCall PP(DtorDecl, Member->getLocation(), LCtx, getCFGElementRef(),
1553 &PT);
1554 Pred = Bldr.generateNode(PP, State, Pred);
1555
1556 if (!Pred)
1557 return;
1558 Bldr.takeNodes(Pred);
1559
1560 VisitCXXDestructor(T, FieldVal.getAsRegion(), CurDtor->getBody(),
1561 /*IsBase=*/false, Pred, Dst, CallOpts);
1562}
1563
1565 ExplodedNode *Pred,
1566 ExplodedNodeSet &Dst) {
1567 const CXXBindTemporaryExpr *BTE = D.getBindTemporaryExpr();
1568 ProgramStateRef State = Pred->getState();
1569 const LocationContext *LC = Pred->getLocationContext();
1570 const MemRegion *MR = nullptr;
1571
1572 if (std::optional<SVal> V = getObjectUnderConstruction(
1573 State, D.getBindTemporaryExpr(), Pred->getLocationContext())) {
1574 // FIXME: Currently we insert temporary destructors for default parameters,
1575 // but we don't insert the constructors, so the entry in
1576 // ObjectsUnderConstruction may be missing.
1577 State = finishObjectConstruction(State, D.getBindTemporaryExpr(),
1578 Pred->getLocationContext());
1579 MR = V->getAsRegion();
1580 }
1581
1582 // If copy elision has occurred, and the constructor corresponding to the
1583 // destructor was elided, we need to skip the destructor as well.
1584 if (isDestructorElided(State, BTE, LC)) {
1585 State = cleanupElidedDestructor(State, BTE, LC);
1586 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1587 PostImplicitCall PP(D.getDestructorDecl(getContext()),
1588 D.getBindTemporaryExpr()->getBeginLoc(),
1590 Bldr.generateNode(PP, State, Pred);
1591 return;
1592 }
1593
1594 ExplodedNodeSet CleanDtorState;
1595 StmtNodeBuilder StmtBldr(Pred, CleanDtorState, *currBldrCtx);
1596 StmtBldr.generateNode(D.getBindTemporaryExpr(), Pred, State);
1597
1598 QualType T = D.getBindTemporaryExpr()->getSubExpr()->getType();
1599 // FIXME: Currently CleanDtorState can be empty here due to temporaries being
1600 // bound to default parameters.
1601 assert(CleanDtorState.size() <= 1);
1602 ExplodedNode *CleanPred =
1603 CleanDtorState.empty() ? Pred : *CleanDtorState.begin();
1604
1605 EvalCallOptions CallOpts;
1606 CallOpts.IsTemporaryCtorOrDtor = true;
1607 if (!MR) {
1608 // FIXME: If we have no MR, we still need to unwrap the array to avoid
1609 // destroying the whole array at once.
1610 //
1611 // For this case there is no universal solution as there is no way to
1612 // directly create an array of temporary objects. There are some expressions
1613 // however which can create temporary objects and have an array type.
1614 //
1615 // E.g.: std::initializer_list<S>{S(), S()};
1616 //
1617 // The expression above has a type of 'const struct S[2]' but it's a single
1618 // 'std::initializer_list<>'. The destructors of the 2 temporary 'S()'
1619 // objects will be called anyway, because they are 2 separate objects in 2
1620 // separate clusters, i.e.: not an array.
1621 //
1622 // Now the 'std::initializer_list<>' is not an array either even though it
1623 // has the type of an array. The point is, we only want to invoke the
1624 // destructor for the initializer list once not twice or so.
1625 while (const ArrayType *AT = getContext().getAsArrayType(T)) {
1626 T = AT->getElementType();
1627
1628 // FIXME: Enable this flag once we handle this case properly.
1629 // CallOpts.IsArrayCtorOrDtor = true;
1630 }
1631 } else {
1632 // FIXME: We'd eventually need to makeElementRegion() trick here,
1633 // but for now we don't have the respective construction contexts,
1634 // so MR would always be null in this case. Do nothing for now.
1635 }
1636 VisitCXXDestructor(T, MR, D.getBindTemporaryExpr(),
1637 /*IsBase=*/false, CleanPred, Dst, CallOpts);
1638}
1639
1641 NodeBuilderContext &BldCtx,
1642 ExplodedNode *Pred,
1643 ExplodedNodeSet &Dst,
1644 const CFGBlock *DstT,
1645 const CFGBlock *DstF) {
1646 BranchNodeBuilder TempDtorBuilder(Pred, Dst, BldCtx, DstT, DstF);
1647 ProgramStateRef State = Pred->getState();
1648 const LocationContext *LC = Pred->getLocationContext();
1649 if (getObjectUnderConstruction(State, BTE, LC)) {
1650 TempDtorBuilder.generateNode(State, true, Pred);
1651 } else {
1652 TempDtorBuilder.generateNode(State, false, Pred);
1653 }
1654}
1655
1657 ExplodedNodeSet &PreVisit,
1658 ExplodedNodeSet &Dst) {
1659 // This is a fallback solution in case we didn't have a construction
1660 // context when we were constructing the temporary. Otherwise the map should
1661 // have been populated there.
1662 if (!getAnalysisManager().options.ShouldIncludeTemporaryDtorsInCFG) {
1663 // In case we don't have temporary destructors in the CFG, do not mark
1664 // the initialization - we would otherwise never clean it up.
1665 Dst = PreVisit;
1666 return;
1667 }
1668 StmtNodeBuilder StmtBldr(PreVisit, Dst, *currBldrCtx);
1669 for (ExplodedNode *Node : PreVisit) {
1670 ProgramStateRef State = Node->getState();
1671 const LocationContext *LC = Node->getLocationContext();
1672 if (!getObjectUnderConstruction(State, BTE, LC)) {
1673 // FIXME: Currently the state might also already contain the marker due to
1674 // incorrect handling of temporaries bound to default parameters; for
1675 // those, we currently skip the CXXBindTemporaryExpr but rely on adding
1676 // temporary destructor nodes.
1677 State = addObjectUnderConstruction(State, BTE, LC, UnknownVal());
1678 }
1679 StmtBldr.generateNode(BTE, Node, State);
1680 }
1681}
1682
1683ProgramStateRef ExprEngine::escapeValues(ProgramStateRef State,
1684 ArrayRef<SVal> Vs,
1686 const CallEvent *Call) const {
1687 class CollectReachableSymbolsCallback final : public SymbolVisitor {
1688 InvalidatedSymbols &Symbols;
1689
1690 public:
1691 explicit CollectReachableSymbolsCallback(InvalidatedSymbols &Symbols)
1692 : Symbols(Symbols) {}
1693
1694 const InvalidatedSymbols &getSymbols() const { return Symbols; }
1695
1696 bool VisitSymbol(SymbolRef Sym) override {
1697 Symbols.insert(Sym);
1698 return true;
1699 }
1700 };
1701 InvalidatedSymbols Symbols;
1702 CollectReachableSymbolsCallback CallBack(Symbols);
1703 for (SVal V : Vs)
1704 State->scanReachableSymbols(V, CallBack);
1705
1707 State, CallBack.getSymbols(), Call, K, nullptr);
1708}
1709
1711 ExplodedNodeSet &DstTop) {
1712 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
1713 S->getBeginLoc(), "Error evaluating statement");
1714 ExplodedNodeSet Dst;
1715 StmtNodeBuilder Bldr(Pred, DstTop, *currBldrCtx);
1716
1717 assert(!isa<Expr>(S) || S == cast<Expr>(S)->IgnoreParens());
1718
1719 switch (S->getStmtClass()) {
1720 // C++, OpenMP and ARC stuff we don't support yet.
1721 case Stmt::CXXDependentScopeMemberExprClass:
1722 case Stmt::CXXTryStmtClass:
1723 case Stmt::CXXTypeidExprClass:
1724 case Stmt::CXXUuidofExprClass:
1725 case Stmt::CXXFoldExprClass:
1726 case Stmt::MSPropertyRefExprClass:
1727 case Stmt::MSPropertySubscriptExprClass:
1728 case Stmt::CXXUnresolvedConstructExprClass:
1729 case Stmt::DependentScopeDeclRefExprClass:
1730 case Stmt::ArrayTypeTraitExprClass:
1731 case Stmt::ExpressionTraitExprClass:
1732 case Stmt::UnresolvedLookupExprClass:
1733 case Stmt::UnresolvedMemberExprClass:
1734 case Stmt::TypoExprClass:
1735 case Stmt::RecoveryExprClass:
1736 case Stmt::CXXNoexceptExprClass:
1737 case Stmt::PackExpansionExprClass:
1738 case Stmt::PackIndexingExprClass:
1739 case Stmt::SubstNonTypeTemplateParmPackExprClass:
1740 case Stmt::FunctionParmPackExprClass:
1741 case Stmt::CoroutineBodyStmtClass:
1742 case Stmt::CoawaitExprClass:
1743 case Stmt::DependentCoawaitExprClass:
1744 case Stmt::CoreturnStmtClass:
1745 case Stmt::CoyieldExprClass:
1746 case Stmt::ResolvedUnexpandedPackExprClass:
1747 case Stmt::SEHTryStmtClass:
1748 case Stmt::SEHExceptStmtClass:
1749 case Stmt::SEHLeaveStmtClass:
1750 case Stmt::SEHFinallyStmtClass:
1751 case Stmt::OMPCanonicalLoopClass:
1752 case Stmt::OMPParallelDirectiveClass:
1753 case Stmt::OMPSimdDirectiveClass:
1754 case Stmt::OMPForDirectiveClass:
1755 case Stmt::OMPForSimdDirectiveClass:
1756 case Stmt::OMPSectionsDirectiveClass:
1757 case Stmt::OMPSectionDirectiveClass:
1758 case Stmt::OMPScopeDirectiveClass:
1759 case Stmt::OMPSingleDirectiveClass:
1760 case Stmt::OMPMasterDirectiveClass:
1761 case Stmt::OMPCriticalDirectiveClass:
1762 case Stmt::OMPParallelForDirectiveClass:
1763 case Stmt::OMPParallelForSimdDirectiveClass:
1764 case Stmt::OMPParallelSectionsDirectiveClass:
1765 case Stmt::OMPParallelMasterDirectiveClass:
1766 case Stmt::OMPParallelMaskedDirectiveClass:
1767 case Stmt::OMPTaskDirectiveClass:
1768 case Stmt::OMPTaskyieldDirectiveClass:
1769 case Stmt::OMPBarrierDirectiveClass:
1770 case Stmt::OMPTaskwaitDirectiveClass:
1771 case Stmt::OMPErrorDirectiveClass:
1772 case Stmt::OMPTaskgroupDirectiveClass:
1773 case Stmt::OMPFlushDirectiveClass:
1774 case Stmt::OMPDepobjDirectiveClass:
1775 case Stmt::OMPScanDirectiveClass:
1776 case Stmt::OMPOrderedDirectiveClass:
1777 case Stmt::OMPAtomicDirectiveClass:
1778 case Stmt::OMPAssumeDirectiveClass:
1779 case Stmt::OMPTargetDirectiveClass:
1780 case Stmt::OMPTargetDataDirectiveClass:
1781 case Stmt::OMPTargetEnterDataDirectiveClass:
1782 case Stmt::OMPTargetExitDataDirectiveClass:
1783 case Stmt::OMPTargetParallelDirectiveClass:
1784 case Stmt::OMPTargetParallelForDirectiveClass:
1785 case Stmt::OMPTargetUpdateDirectiveClass:
1786 case Stmt::OMPTeamsDirectiveClass:
1787 case Stmt::OMPCancellationPointDirectiveClass:
1788 case Stmt::OMPCancelDirectiveClass:
1789 case Stmt::OMPTaskLoopDirectiveClass:
1790 case Stmt::OMPTaskLoopSimdDirectiveClass:
1791 case Stmt::OMPMasterTaskLoopDirectiveClass:
1792 case Stmt::OMPMaskedTaskLoopDirectiveClass:
1793 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
1794 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
1795 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
1796 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
1797 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
1798 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
1799 case Stmt::OMPDistributeDirectiveClass:
1800 case Stmt::OMPDistributeParallelForDirectiveClass:
1801 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
1802 case Stmt::OMPDistributeSimdDirectiveClass:
1803 case Stmt::OMPTargetParallelForSimdDirectiveClass:
1804 case Stmt::OMPTargetSimdDirectiveClass:
1805 case Stmt::OMPTeamsDistributeDirectiveClass:
1806 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
1807 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
1808 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
1809 case Stmt::OMPTargetTeamsDirectiveClass:
1810 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
1811 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
1812 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
1813 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
1814 case Stmt::OMPReverseDirectiveClass:
1815 case Stmt::OMPTileDirectiveClass:
1816 case Stmt::OMPInterchangeDirectiveClass:
1817 case Stmt::OMPInteropDirectiveClass:
1818 case Stmt::OMPDispatchDirectiveClass:
1819 case Stmt::OMPMaskedDirectiveClass:
1820 case Stmt::OMPGenericLoopDirectiveClass:
1821 case Stmt::OMPTeamsGenericLoopDirectiveClass:
1822 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
1823 case Stmt::OMPParallelGenericLoopDirectiveClass:
1824 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
1825 case Stmt::CapturedStmtClass:
1826 case Stmt::SYCLKernelCallStmtClass:
1827 case Stmt::OpenACCComputeConstructClass:
1828 case Stmt::OpenACCLoopConstructClass:
1829 case Stmt::OpenACCCombinedConstructClass:
1830 case Stmt::OpenACCDataConstructClass:
1831 case Stmt::OpenACCEnterDataConstructClass:
1832 case Stmt::OpenACCExitDataConstructClass:
1833 case Stmt::OpenACCHostDataConstructClass:
1834 case Stmt::OpenACCWaitConstructClass:
1835 case Stmt::OpenACCInitConstructClass:
1836 case Stmt::OpenACCShutdownConstructClass:
1837 case Stmt::OpenACCSetConstructClass:
1838 case Stmt::OpenACCUpdateConstructClass:
1839 case Stmt::OpenACCAtomicConstructClass:
1840 case Stmt::OMPUnrollDirectiveClass:
1841 case Stmt::OMPMetaDirectiveClass:
1842 case Stmt::HLSLOutArgExprClass: {
1843 const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
1844 Engine.addAbortedBlock(node, currBldrCtx->getBlock());
1845 break;
1846 }
1847
1848 case Stmt::ParenExprClass:
1849 llvm_unreachable("ParenExprs already handled.");
1850 case Stmt::GenericSelectionExprClass:
1851 llvm_unreachable("GenericSelectionExprs already handled.");
1852 // Cases that should never be evaluated simply because they shouldn't
1853 // appear in the CFG.
1854 case Stmt::BreakStmtClass:
1855 case Stmt::CaseStmtClass:
1856 case Stmt::CompoundStmtClass:
1857 case Stmt::ContinueStmtClass:
1858 case Stmt::CXXForRangeStmtClass:
1859 case Stmt::DefaultStmtClass:
1860 case Stmt::DoStmtClass:
1861 case Stmt::ForStmtClass:
1862 case Stmt::GotoStmtClass:
1863 case Stmt::IfStmtClass:
1864 case Stmt::IndirectGotoStmtClass:
1865 case Stmt::LabelStmtClass:
1866 case Stmt::NoStmtClass:
1867 case Stmt::NullStmtClass:
1868 case Stmt::SwitchStmtClass:
1869 case Stmt::WhileStmtClass:
1870 case Expr::MSDependentExistsStmtClass:
1871 llvm_unreachable("Stmt should not be in analyzer evaluation loop");
1872 case Stmt::ImplicitValueInitExprClass:
1873 // These nodes are shared in the CFG and would case caching out.
1874 // Moreover, no additional evaluation required for them, the
1875 // analyzer can reconstruct these values from the AST.
1876 llvm_unreachable("Should be pruned from CFG");
1877
1878 case Stmt::ObjCSubscriptRefExprClass:
1879 case Stmt::ObjCPropertyRefExprClass:
1880 llvm_unreachable("These are handled by PseudoObjectExpr");
1881
1882 case Stmt::GNUNullExprClass: {
1883 // GNU __null is a pointer-width integer, not an actual pointer.
1884 ProgramStateRef state = Pred->getState();
1885 state = state->BindExpr(
1886 S, Pred->getLocationContext(),
1887 svalBuilder.makeIntValWithWidth(getContext().VoidPtrTy, 0));
1888 Bldr.generateNode(S, Pred, state);
1889 break;
1890 }
1891
1892 case Stmt::ObjCAtSynchronizedStmtClass:
1893 Bldr.takeNodes(Pred);
1894 VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S), Pred, Dst);
1895 Bldr.addNodes(Dst);
1896 break;
1897
1898 case Expr::ConstantExprClass:
1899 case Stmt::ExprWithCleanupsClass:
1900 // Handled due to fully linearised CFG.
1901 break;
1902
1903 case Stmt::CXXBindTemporaryExprClass: {
1904 Bldr.takeNodes(Pred);
1905 ExplodedNodeSet PreVisit;
1906 getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
1907 ExplodedNodeSet Next;
1908 VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), PreVisit, Next);
1909 getCheckerManager().runCheckersForPostStmt(Dst, Next, S, *this);
1910 Bldr.addNodes(Dst);
1911 break;
1912 }
1913
1914 case Stmt::ArrayInitLoopExprClass:
1915 Bldr.takeNodes(Pred);
1916 VisitArrayInitLoopExpr(cast<ArrayInitLoopExpr>(S), Pred, Dst);
1917 Bldr.addNodes(Dst);
1918 break;
1919 // Cases not handled yet; but will handle some day.
1920 case Stmt::DesignatedInitExprClass:
1921 case Stmt::DesignatedInitUpdateExprClass:
1922 case Stmt::ArrayInitIndexExprClass:
1923 case Stmt::ExtVectorElementExprClass:
1924 case Stmt::ImaginaryLiteralClass:
1925 case Stmt::ObjCAtCatchStmtClass:
1926 case Stmt::ObjCAtFinallyStmtClass:
1927 case Stmt::ObjCAtTryStmtClass:
1928 case Stmt::ObjCAutoreleasePoolStmtClass:
1929 case Stmt::ObjCEncodeExprClass:
1930 case Stmt::ObjCIsaExprClass:
1931 case Stmt::ObjCProtocolExprClass:
1932 case Stmt::ObjCSelectorExprClass:
1933 case Stmt::ParenListExprClass:
1934 case Stmt::ShuffleVectorExprClass:
1935 case Stmt::ConvertVectorExprClass:
1936 case Stmt::VAArgExprClass:
1937 case Stmt::CUDAKernelCallExprClass:
1938 case Stmt::OpaqueValueExprClass:
1939 case Stmt::AsTypeExprClass:
1940 case Stmt::ConceptSpecializationExprClass:
1941 case Stmt::CXXRewrittenBinaryOperatorClass:
1942 case Stmt::RequiresExprClass:
1943 case Expr::CXXParenListInitExprClass:
1944 case Stmt::EmbedExprClass:
1945 // Fall through.
1946
1947 // Cases we intentionally don't evaluate, since they don't need
1948 // to be explicitly evaluated.
1949 case Stmt::PredefinedExprClass:
1950 case Stmt::AddrLabelExprClass:
1951 case Stmt::AttributedStmtClass:
1952 case Stmt::IntegerLiteralClass:
1953 case Stmt::FixedPointLiteralClass:
1954 case Stmt::CharacterLiteralClass:
1955 case Stmt::CXXScalarValueInitExprClass:
1956 case Stmt::CXXBoolLiteralExprClass:
1957 case Stmt::ObjCBoolLiteralExprClass:
1958 case Stmt::ObjCAvailabilityCheckExprClass:
1959 case Stmt::FloatingLiteralClass:
1960 case Stmt::NoInitExprClass:
1961 case Stmt::SizeOfPackExprClass:
1962 case Stmt::StringLiteralClass:
1963 case Stmt::SourceLocExprClass:
1964 case Stmt::ObjCStringLiteralClass:
1965 case Stmt::CXXPseudoDestructorExprClass:
1966 case Stmt::SubstNonTypeTemplateParmExprClass:
1967 case Stmt::CXXNullPtrLiteralExprClass:
1968 case Stmt::ArraySectionExprClass:
1969 case Stmt::OMPArrayShapingExprClass:
1970 case Stmt::OMPIteratorExprClass:
1971 case Stmt::SYCLUniqueStableNameExprClass:
1972 case Stmt::OpenACCAsteriskSizeExprClass:
1973 case Stmt::TypeTraitExprClass: {
1974 Bldr.takeNodes(Pred);
1975 ExplodedNodeSet preVisit;
1976 getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
1977 getCheckerManager().runCheckersForPostStmt(Dst, preVisit, S, *this);
1978 Bldr.addNodes(Dst);
1979 break;
1980 }
1981
1982 case Stmt::CXXDefaultArgExprClass:
1983 case Stmt::CXXDefaultInitExprClass: {
1984 Bldr.takeNodes(Pred);
1985 ExplodedNodeSet PreVisit;
1986 getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
1987
1988 ExplodedNodeSet Tmp;
1989 StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
1990
1991 const Expr *ArgE;
1992 if (const auto *DefE = dyn_cast<CXXDefaultArgExpr>(S))
1993 ArgE = DefE->getExpr();
1994 else if (const auto *DefE = dyn_cast<CXXDefaultInitExpr>(S))
1995 ArgE = DefE->getExpr();
1996 else
1997 llvm_unreachable("unknown constant wrapper kind");
1998
1999 bool IsTemporary = false;
2000 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(ArgE)) {
2001 ArgE = MTE->getSubExpr();
2002 IsTemporary = true;
2003 }
2004
2005 std::optional<SVal> ConstantVal = svalBuilder.getConstantVal(ArgE);
2006 if (!ConstantVal)
2007 ConstantVal = UnknownVal();
2008
2009 const LocationContext *LCtx = Pred->getLocationContext();
2010 for (const auto I : PreVisit) {
2011 ProgramStateRef State = I->getState();
2012 State = State->BindExpr(S, LCtx, *ConstantVal);
2013 if (IsTemporary)
2014 State = createTemporaryRegionIfNeeded(State, LCtx,
2015 cast<Expr>(S),
2016 cast<Expr>(S));
2017 Bldr2.generateNode(S, I, State);
2018 }
2019
2020 getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
2021 Bldr.addNodes(Dst);
2022 break;
2023 }
2024
2025 // Cases we evaluate as opaque expressions, conjuring a symbol.
2026 case Stmt::CXXStdInitializerListExprClass:
2027 case Expr::ObjCArrayLiteralClass:
2028 case Expr::ObjCDictionaryLiteralClass:
2029 case Expr::ObjCBoxedExprClass: {
2030 Bldr.takeNodes(Pred);
2031
2032 ExplodedNodeSet preVisit;
2033 getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
2034
2035 ExplodedNodeSet Tmp;
2036 StmtNodeBuilder Bldr2(preVisit, Tmp, *currBldrCtx);
2037
2038 const auto *Ex = cast<Expr>(S);
2039 QualType resultType = Ex->getType();
2040
2041 for (const auto N : preVisit) {
2042 const LocationContext *LCtx = N->getLocationContext();
2043 SVal result = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
2044 resultType,
2045 currBldrCtx->blockCount());
2046 ProgramStateRef State = N->getState()->BindExpr(Ex, LCtx, result);
2047
2048 // Escape pointers passed into the list, unless it's an ObjC boxed
2049 // expression which is not a boxable C structure.
2050 if (!(isa<ObjCBoxedExpr>(Ex) &&
2051 !cast<ObjCBoxedExpr>(Ex)->getSubExpr()
2052 ->getType()->isRecordType()))
2053 for (auto Child : Ex->children()) {
2054 assert(Child);
2055 SVal Val = State->getSVal(Child, LCtx);
2056 State = escapeValues(State, Val, PSK_EscapeOther);
2057 }
2058
2059 Bldr2.generateNode(S, N, State);
2060 }
2061
2062 getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
2063 Bldr.addNodes(Dst);
2064 break;
2065 }
2066
2067 case Stmt::ArraySubscriptExprClass:
2068 Bldr.takeNodes(Pred);
2069 VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Pred, Dst);
2070 Bldr.addNodes(Dst);
2071 break;
2072
2073 case Stmt::MatrixSubscriptExprClass:
2074 llvm_unreachable("Support for MatrixSubscriptExpr is not implemented.");
2075 break;
2076
2077 case Stmt::GCCAsmStmtClass: {
2078 Bldr.takeNodes(Pred);
2079 ExplodedNodeSet PreVisit;
2080 getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
2082 for (ExplodedNode *const N : PreVisit)
2083 VisitGCCAsmStmt(cast<GCCAsmStmt>(S), N, PostVisit);
2085 Bldr.addNodes(Dst);
2086 break;
2087 }
2088
2089 case Stmt::MSAsmStmtClass:
2090 Bldr.takeNodes(Pred);
2091 VisitMSAsmStmt(cast<MSAsmStmt>(S), Pred, Dst);
2092 Bldr.addNodes(Dst);
2093 break;
2094
2095 case Stmt::BlockExprClass:
2096 Bldr.takeNodes(Pred);
2097 VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst);
2098 Bldr.addNodes(Dst);
2099 break;
2100
2101 case Stmt::LambdaExprClass:
2102 if (AMgr.options.ShouldInlineLambdas) {
2103 Bldr.takeNodes(Pred);
2104 VisitLambdaExpr(cast<LambdaExpr>(S), Pred, Dst);
2105 Bldr.addNodes(Dst);
2106 } else {
2107 const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
2108 Engine.addAbortedBlock(node, currBldrCtx->getBlock());
2109 }
2110 break;
2111
2112 case Stmt::BinaryOperatorClass: {
2113 const auto *B = cast<BinaryOperator>(S);
2114 if (B->isLogicalOp()) {
2115 Bldr.takeNodes(Pred);
2116 VisitLogicalExpr(B, Pred, Dst);
2117 Bldr.addNodes(Dst);
2118 break;
2119 }
2120 else if (B->getOpcode() == BO_Comma) {
2121 ProgramStateRef state = Pred->getState();
2122 Bldr.generateNode(B, Pred,
2123 state->BindExpr(B, Pred->getLocationContext(),
2124 state->getSVal(B->getRHS(),
2125 Pred->getLocationContext())));
2126 break;
2127 }
2128
2129 Bldr.takeNodes(Pred);
2130
2131 if (AMgr.options.ShouldEagerlyAssume &&
2132 (B->isRelationalOp() || B->isEqualityOp())) {
2133 ExplodedNodeSet Tmp;
2134 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);
2135 evalEagerlyAssumeBifurcation(Dst, Tmp, cast<Expr>(S));
2136 }
2137 else
2138 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
2139
2140 Bldr.addNodes(Dst);
2141 break;
2142 }
2143
2144 case Stmt::CXXOperatorCallExprClass: {
2145 const auto *OCE = cast<CXXOperatorCallExpr>(S);
2146
2147 // For instance method operators, make sure the 'this' argument has a
2148 // valid region.
2149 const Decl *Callee = OCE->getCalleeDecl();
2150 if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(Callee)) {
2151 if (MD->isImplicitObjectMemberFunction()) {
2152 ProgramStateRef State = Pred->getState();
2153 const LocationContext *LCtx = Pred->getLocationContext();
2154 ProgramStateRef NewState =
2155 createTemporaryRegionIfNeeded(State, LCtx, OCE->getArg(0));
2156 if (NewState != State) {
2157 Pred = Bldr.generateNode(OCE, Pred, NewState, /*tag=*/nullptr,
2159 // Did we cache out?
2160 if (!Pred)
2161 break;
2162 }
2163 }
2164 }
2165 [[fallthrough]];
2166 }
2167
2168 case Stmt::CallExprClass:
2169 case Stmt::CXXMemberCallExprClass:
2170 case Stmt::UserDefinedLiteralClass:
2171 Bldr.takeNodes(Pred);
2172 VisitCallExpr(cast<CallExpr>(S), Pred, Dst);
2173 Bldr.addNodes(Dst);
2174 break;
2175
2176 case Stmt::CXXCatchStmtClass:
2177 Bldr.takeNodes(Pred);
2178 VisitCXXCatchStmt(cast<CXXCatchStmt>(S), Pred, Dst);
2179 Bldr.addNodes(Dst);
2180 break;
2181
2182 case Stmt::CXXTemporaryObjectExprClass:
2183 case Stmt::CXXConstructExprClass:
2184 Bldr.takeNodes(Pred);
2185 VisitCXXConstructExpr(cast<CXXConstructExpr>(S), Pred, Dst);
2186 Bldr.addNodes(Dst);
2187 break;
2188
2189 case Stmt::CXXInheritedCtorInitExprClass:
2190 Bldr.takeNodes(Pred);
2191 VisitCXXInheritedCtorInitExpr(cast<CXXInheritedCtorInitExpr>(S), Pred,
2192 Dst);
2193 Bldr.addNodes(Dst);
2194 break;
2195
2196 case Stmt::CXXNewExprClass: {
2197 Bldr.takeNodes(Pred);
2198
2199 ExplodedNodeSet PreVisit;
2200 getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
2201
2203 for (const auto i : PreVisit)
2204 VisitCXXNewExpr(cast<CXXNewExpr>(S), i, PostVisit);
2205
2207 Bldr.addNodes(Dst);
2208 break;
2209 }
2210
2211 case Stmt::CXXDeleteExprClass: {
2212 Bldr.takeNodes(Pred);
2213 ExplodedNodeSet PreVisit;
2214 const auto *CDE = cast<CXXDeleteExpr>(S);
2215 getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
2217 getCheckerManager().runCheckersForPostStmt(PostVisit, PreVisit, S, *this);
2218
2219 for (const auto i : PostVisit)
2220 VisitCXXDeleteExpr(CDE, i, Dst);
2221
2222 Bldr.addNodes(Dst);
2223 break;
2224 }
2225 // FIXME: ChooseExpr is really a constant. We need to fix
2226 // the CFG do not model them as explicit control-flow.
2227
2228 case Stmt::ChooseExprClass: { // __builtin_choose_expr
2229 Bldr.takeNodes(Pred);
2230 const auto *C = cast<ChooseExpr>(S);
2231 VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
2232 Bldr.addNodes(Dst);
2233 break;
2234 }
2235
2236 case Stmt::CompoundAssignOperatorClass:
2237 Bldr.takeNodes(Pred);
2238 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
2239 Bldr.addNodes(Dst);
2240 break;
2241
2242 case Stmt::CompoundLiteralExprClass:
2243 Bldr.takeNodes(Pred);
2244 VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(S), Pred, Dst);
2245 Bldr.addNodes(Dst);
2246 break;
2247
2248 case Stmt::BinaryConditionalOperatorClass:
2249 case Stmt::ConditionalOperatorClass: { // '?' operator
2250 Bldr.takeNodes(Pred);
2251 const auto *C = cast<AbstractConditionalOperator>(S);
2252 VisitGuardedExpr(C, C->getTrueExpr(), C->getFalseExpr(), Pred, Dst);
2253 Bldr.addNodes(Dst);
2254 break;
2255 }
2256
2257 case Stmt::CXXThisExprClass:
2258 Bldr.takeNodes(Pred);
2259 VisitCXXThisExpr(cast<CXXThisExpr>(S), Pred, Dst);
2260 Bldr.addNodes(Dst);
2261 break;
2262
2263 case Stmt::DeclRefExprClass: {
2264 Bldr.takeNodes(Pred);
2265 const auto *DE = cast<DeclRefExpr>(S);
2266 VisitCommonDeclRefExpr(DE, DE->getDecl(), Pred, Dst);
2267 Bldr.addNodes(Dst);
2268 break;
2269 }
2270
2271 case Stmt::DeclStmtClass:
2272 Bldr.takeNodes(Pred);
2273 VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
2274 Bldr.addNodes(Dst);
2275 break;
2276
2277 case Stmt::ImplicitCastExprClass:
2278 case Stmt::CStyleCastExprClass:
2279 case Stmt::CXXStaticCastExprClass:
2280 case Stmt::CXXDynamicCastExprClass:
2281 case Stmt::CXXReinterpretCastExprClass:
2282 case Stmt::CXXConstCastExprClass:
2283 case Stmt::CXXFunctionalCastExprClass:
2284 case Stmt::BuiltinBitCastExprClass:
2285 case Stmt::ObjCBridgedCastExprClass:
2286 case Stmt::CXXAddrspaceCastExprClass: {
2287 Bldr.takeNodes(Pred);
2288 const auto *C = cast<CastExpr>(S);
2289 ExplodedNodeSet dstExpr;
2290 VisitCast(C, C->getSubExpr(), Pred, dstExpr);
2291
2292 // Handle the postvisit checks.
2293 getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, C, *this);
2294 Bldr.addNodes(Dst);
2295 break;
2296 }
2297
2298 case Expr::MaterializeTemporaryExprClass: {
2299 Bldr.takeNodes(Pred);
2300 const auto *MTE = cast<MaterializeTemporaryExpr>(S);
2301 ExplodedNodeSet dstPrevisit;
2302 getCheckerManager().runCheckersForPreStmt(dstPrevisit, Pred, MTE, *this);
2303 ExplodedNodeSet dstExpr;
2304 for (const auto i : dstPrevisit)
2305 CreateCXXTemporaryObject(MTE, i, dstExpr);
2306 getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, MTE, *this);
2307 Bldr.addNodes(Dst);
2308 break;
2309 }
2310
2311 case Stmt::InitListExprClass:
2312 Bldr.takeNodes(Pred);
2313 VisitInitListExpr(cast<InitListExpr>(S), Pred, Dst);
2314 Bldr.addNodes(Dst);
2315 break;
2316
2317 case Stmt::MemberExprClass:
2318 Bldr.takeNodes(Pred);
2319 VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst);
2320 Bldr.addNodes(Dst);
2321 break;
2322
2323 case Stmt::AtomicExprClass:
2324 Bldr.takeNodes(Pred);
2325 VisitAtomicExpr(cast<AtomicExpr>(S), Pred, Dst);
2326 Bldr.addNodes(Dst);
2327 break;
2328
2329 case Stmt::ObjCIvarRefExprClass:
2330 Bldr.takeNodes(Pred);
2331 VisitLvalObjCIvarRefExpr(cast<ObjCIvarRefExpr>(S), Pred, Dst);
2332 Bldr.addNodes(Dst);
2333 break;
2334
2335 case Stmt::ObjCForCollectionStmtClass:
2336 Bldr.takeNodes(Pred);
2337 VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S), Pred, Dst);
2338 Bldr.addNodes(Dst);
2339 break;
2340
2341 case Stmt::ObjCMessageExprClass:
2342 Bldr.takeNodes(Pred);
2343 VisitObjCMessage(cast<ObjCMessageExpr>(S), Pred, Dst);
2344 Bldr.addNodes(Dst);
2345 break;
2346
2347 case Stmt::ObjCAtThrowStmtClass:
2348 case Stmt::CXXThrowExprClass:
2349 // FIXME: This is not complete. We basically treat @throw as
2350 // an abort.
2351 Bldr.generateSink(S, Pred, Pred->getState());
2352 break;
2353
2354 case Stmt::ReturnStmtClass:
2355 Bldr.takeNodes(Pred);
2356 VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst);
2357 Bldr.addNodes(Dst);
2358 break;
2359
2360 case Stmt::OffsetOfExprClass: {
2361 Bldr.takeNodes(Pred);
2362 ExplodedNodeSet PreVisit;
2363 getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
2364
2366 for (const auto Node : PreVisit)
2367 VisitOffsetOfExpr(cast<OffsetOfExpr>(S), Node, PostVisit);
2368
2370 Bldr.addNodes(Dst);
2371 break;
2372 }
2373
2374 case Stmt::UnaryExprOrTypeTraitExprClass:
2375 Bldr.takeNodes(Pred);
2376 VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
2377 Pred, Dst);
2378 Bldr.addNodes(Dst);
2379 break;
2380
2381 case Stmt::StmtExprClass: {
2382 const auto *SE = cast<StmtExpr>(S);
2383
2384 if (SE->getSubStmt()->body_empty()) {
2385 // Empty statement expression.
2386 assert(SE->getType() == getContext().VoidTy
2387 && "Empty statement expression must have void type.");
2388 break;
2389 }
2390
2391 if (const auto *LastExpr =
2392 dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
2393 ProgramStateRef state = Pred->getState();
2394 Bldr.generateNode(SE, Pred,
2395 state->BindExpr(SE, Pred->getLocationContext(),
2396 state->getSVal(LastExpr,
2397 Pred->getLocationContext())));
2398 }
2399 break;
2400 }
2401
2402 case Stmt::UnaryOperatorClass: {
2403 Bldr.takeNodes(Pred);
2404 const auto *U = cast<UnaryOperator>(S);
2405 if (AMgr.options.ShouldEagerlyAssume && (U->getOpcode() == UO_LNot)) {
2406 ExplodedNodeSet Tmp;
2407 VisitUnaryOperator(U, Pred, Tmp);
2409 }
2410 else
2411 VisitUnaryOperator(U, Pred, Dst);
2412 Bldr.addNodes(Dst);
2413 break;
2414 }
2415
2416 case Stmt::PseudoObjectExprClass: {
2417 Bldr.takeNodes(Pred);
2418 ProgramStateRef state = Pred->getState();
2419 const auto *PE = cast<PseudoObjectExpr>(S);
2420 if (const Expr *Result = PE->getResultExpr()) {
2421 SVal V = state->getSVal(Result, Pred->getLocationContext());
2422 Bldr.generateNode(S, Pred,
2423 state->BindExpr(S, Pred->getLocationContext(), V));
2424 }
2425 else
2426 Bldr.generateNode(S, Pred,
2427 state->BindExpr(S, Pred->getLocationContext(),
2428 UnknownVal()));
2429
2430 Bldr.addNodes(Dst);
2431 break;
2432 }
2433
2434 case Expr::ObjCIndirectCopyRestoreExprClass: {
2435 // ObjCIndirectCopyRestoreExpr implies passing a temporary for
2436 // correctness of lifetime management. Due to limited analysis
2437 // of ARC, this is implemented as direct arg passing.
2438 Bldr.takeNodes(Pred);
2439 ProgramStateRef state = Pred->getState();
2440 const auto *OIE = cast<ObjCIndirectCopyRestoreExpr>(S);
2441 const Expr *E = OIE->getSubExpr();
2442 SVal V = state->getSVal(E, Pred->getLocationContext());
2443 Bldr.generateNode(S, Pred,
2444 state->BindExpr(S, Pred->getLocationContext(), V));
2445 Bldr.addNodes(Dst);
2446 break;
2447 }
2448 }
2449}
2450
2451bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
2452 const LocationContext *CalleeLC) {
2453 const StackFrameContext *CalleeSF = CalleeLC->getStackFrame();
2454 const StackFrameContext *CallerSF = CalleeSF->getParent()->getStackFrame();
2455 assert(CalleeSF && CallerSF);
2456 ExplodedNode *BeforeProcessingCall = nullptr;
2457 const Stmt *CE = CalleeSF->getCallSite();
2458
2459 // Find the first node before we started processing the call expression.
2460 while (N) {
2461 ProgramPoint L = N->getLocation();
2462 BeforeProcessingCall = N;
2463 N = N->pred_empty() ? nullptr : *(N->pred_begin());
2464
2465 // Skip the nodes corresponding to the inlined code.
2466 if (L.getStackFrame() != CallerSF)
2467 continue;
2468 // We reached the caller. Find the node right before we started
2469 // processing the call.
2470 if (L.isPurgeKind())
2471 continue;
2472 if (L.getAs<PreImplicitCall>())
2473 continue;
2474 if (L.getAs<CallEnter>())
2475 continue;
2476 if (std::optional<StmtPoint> SP = L.getAs<StmtPoint>())
2477 if (SP->getStmt() == CE)
2478 continue;
2479 break;
2480 }
2481
2482 if (!BeforeProcessingCall)
2483 return false;
2484
2485 // TODO: Clean up the unneeded nodes.
2486
2487 // Build an Epsilon node from which we will restart the analyzes.
2488 // Note that CE is permitted to be NULL!
2489 static SimpleProgramPointTag PT("ExprEngine", "Replay without inlining");
2490 ProgramPoint NewNodeLoc = EpsilonPoint(
2491 BeforeProcessingCall->getLocationContext(), CE, nullptr, &PT);
2492 // Add the special flag to GDM to signal retrying with no inlining.
2493 // Note, changing the state ensures that we are not going to cache out.
2494 ProgramStateRef NewNodeState = BeforeProcessingCall->getState();
2495 NewNodeState =
2496 NewNodeState->set<ReplayWithoutInlining>(const_cast<Stmt *>(CE));
2497
2498 // Make the new node a successor of BeforeProcessingCall.
2499 bool IsNew = false;
2500 ExplodedNode *NewNode = G.getNode(NewNodeLoc, NewNodeState, false, &IsNew);
2501 // We cached out at this point. Caching out is common due to us backtracking
2502 // from the inlined function, which might spawn several paths.
2503 if (!IsNew)
2504 return true;
2505
2506 NewNode->addPredecessor(BeforeProcessingCall, G);
2507
2508 // Add the new node to the work list.
2509 Engine.enqueueStmtNode(NewNode, CalleeSF->getCallSiteBlock(),
2510 CalleeSF->getIndex());
2511 NumTimesRetriedWithoutInlining++;
2512 return true;
2513}
2514
2515/// Block entrance. (Update counters).
2517 NodeBuilderWithSinks &nodeBuilder,
2518 ExplodedNode *Pred) {
2520 // If we reach a loop which has a known bound (and meets
2521 // other constraints) then consider completely unrolling it.
2522 if(AMgr.options.ShouldUnrollLoops) {
2523 unsigned maxBlockVisitOnPath = AMgr.options.maxBlockVisitOnPath;
2524 const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminatorStmt();
2525 if (Term) {
2526 ProgramStateRef NewState = updateLoopStack(Term, AMgr.getASTContext(),
2527 Pred, maxBlockVisitOnPath);
2528 if (NewState != Pred->getState()) {
2529 ExplodedNode *UpdatedNode = nodeBuilder.generateNode(NewState, Pred);
2530 if (!UpdatedNode)
2531 return;
2532 Pred = UpdatedNode;
2533 }
2534 }
2535 // Is we are inside an unrolled loop then no need the check the counters.
2536 if(isUnrolledState(Pred->getState()))
2537 return;
2538 }
2539
2540 // If this block is terminated by a loop and it has already been visited the
2541 // maximum number of times, widen the loop.
2542 unsigned int BlockCount = nodeBuilder.getContext().blockCount();
2543 if (BlockCount == AMgr.options.maxBlockVisitOnPath - 1 &&
2544 AMgr.options.ShouldWidenLoops) {
2545 const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminatorStmt();
2546 if (!isa_and_nonnull<ForStmt, WhileStmt, DoStmt, CXXForRangeStmt>(Term))
2547 return;
2548 // Widen.
2549 const LocationContext *LCtx = Pred->getLocationContext();
2550 ProgramStateRef WidenedState =
2551 getWidenedLoopState(Pred->getState(), LCtx, BlockCount, Term);
2552 nodeBuilder.generateNode(WidenedState, Pred);
2553 return;
2554 }
2555
2556 // FIXME: Refactor this into a checker.
2557 if (BlockCount >= AMgr.options.maxBlockVisitOnPath) {
2558 static SimpleProgramPointTag tag(TagProviderName, "Block count exceeded");
2559 const ExplodedNode *Sink =
2560 nodeBuilder.generateSink(Pred->getState(), Pred, &tag);
2561
2562 // Check if we stopped at the top level function or not.
2563 // Root node should have the location context of the top most function.
2564 const LocationContext *CalleeLC = Pred->getLocation().getLocationContext();
2565 const LocationContext *CalleeSF = CalleeLC->getStackFrame();
2566 const LocationContext *RootLC =
2567 (*G.roots_begin())->getLocation().getLocationContext();
2568 if (RootLC->getStackFrame() != CalleeSF) {
2569 Engine.FunctionSummaries->markReachedMaxBlockCount(CalleeSF->getDecl());
2570
2571 // Re-run the call evaluation without inlining it, by storing the
2572 // no-inlining policy in the state and enqueuing the new work item on
2573 // the list. Replay should almost never fail. Use the stats to catch it
2574 // if it does.
2575 if ((!AMgr.options.NoRetryExhausted &&
2576 replayWithoutInlining(Pred, CalleeLC)))
2577 return;
2578 NumMaxBlockCountReachedInInlined++;
2579 } else
2580 NumMaxBlockCountReached++;
2581
2582 // Make sink nodes as exhausted(for stats) only if retry failed.
2583 Engine.blocksExhausted.push_back(std::make_pair(L, Sink));
2584 }
2585}
2586
2587//===----------------------------------------------------------------------===//
2588// Branch processing.
2589//===----------------------------------------------------------------------===//
2590
2591/// RecoverCastedSymbol - A helper function for ProcessBranch that is used
2592/// to try to recover some path-sensitivity for casts of symbolic
2593/// integers that promote their values (which are currently not tracked well).
2594/// This function returns the SVal bound to Condition->IgnoreCasts if all the
2595// cast(s) did was sign-extend the original value.
2597 const Stmt *Condition,
2598 const LocationContext *LCtx,
2599 ASTContext &Ctx) {
2600
2601 const auto *Ex = dyn_cast<Expr>(Condition);
2602 if (!Ex)
2603 return UnknownVal();
2604
2605 uint64_t bits = 0;
2606 bool bitsInit = false;
2607
2608 while (const auto *CE = dyn_cast<CastExpr>(Ex)) {
2609 QualType T = CE->getType();
2610
2612 return UnknownVal();
2613
2614 uint64_t newBits = Ctx.getTypeSize(T);
2615 if (!bitsInit || newBits < bits) {
2616 bitsInit = true;
2617 bits = newBits;
2618 }
2619
2620 Ex = CE->getSubExpr();
2621 }
2622
2623 // We reached a non-cast. Is it a symbolic value?
2624 QualType T = Ex->getType();
2625
2626 if (!bitsInit || !T->isIntegralOrEnumerationType() ||
2627 Ctx.getTypeSize(T) > bits)
2628 return UnknownVal();
2629
2630 return state->getSVal(Ex, LCtx);
2631}
2632
2633#ifndef NDEBUG
2634static const Stmt *getRightmostLeaf(const Stmt *Condition) {
2635 while (Condition) {
2636 const auto *BO = dyn_cast<BinaryOperator>(Condition);
2637 if (!BO || !BO->isLogicalOp()) {
2638 return Condition;
2639 }
2640 Condition = BO->getRHS()->IgnoreParens();
2641 }
2642 return nullptr;
2643}
2644#endif
2645
2646// Returns the condition the branch at the end of 'B' depends on and whose value
2647// has been evaluated within 'B'.
2648// In most cases, the terminator condition of 'B' will be evaluated fully in
2649// the last statement of 'B'; in those cases, the resolved condition is the
2650// given 'Condition'.
2651// If the condition of the branch is a logical binary operator tree, the CFG is
2652// optimized: in that case, we know that the expression formed by all but the
2653// rightmost leaf of the logical binary operator tree must be true, and thus
2654// the branch condition is at this point equivalent to the truth value of that
2655// rightmost leaf; the CFG block thus only evaluates this rightmost leaf
2656// expression in its final statement. As the full condition in that case was
2657// not evaluated, and is thus not in the SVal cache, we need to use that leaf
2658// expression to evaluate the truth value of the condition in the current state
2659// space.
2661 const CFGBlock *B) {
2662 if (const auto *Ex = dyn_cast<Expr>(Condition))
2663 Condition = Ex->IgnoreParens();
2664
2665 const auto *BO = dyn_cast<BinaryOperator>(Condition);
2666 if (!BO || !BO->isLogicalOp())
2667 return Condition;
2668
2669 assert(B->getTerminator().isStmtBranch() &&
2670 "Other kinds of branches are handled separately!");
2671
2672 // For logical operations, we still have the case where some branches
2673 // use the traditional "merge" approach and others sink the branch
2674 // directly into the basic blocks representing the logical operation.
2675 // We need to distinguish between those two cases here.
2676
2677 // The invariants are still shifting, but it is possible that the
2678 // last element in a CFGBlock is not a CFGStmt. Look for the last
2679 // CFGStmt as the value of the condition.
2680 for (CFGElement Elem : llvm::reverse(*B)) {
2681 std::optional<CFGStmt> CS = Elem.getAs<CFGStmt>();
2682 if (!CS)
2683 continue;
2684 const Stmt *LastStmt = CS->getStmt();
2685 assert(LastStmt == Condition || LastStmt == getRightmostLeaf(Condition));
2686 return LastStmt;
2687 }
2688 llvm_unreachable("could not resolve condition");
2689}
2690
2692 std::pair<const ObjCForCollectionStmt *, const LocationContext *>;
2693
2694REGISTER_MAP_WITH_PROGRAMSTATE(ObjCForHasMoreIterations, ObjCForLctxPair, bool)
2695
2696ProgramStateRef ExprEngine::setWhetherHasMoreIteration(
2697 ProgramStateRef State, const ObjCForCollectionStmt *O,
2698 const LocationContext *LC, bool HasMoreIteraton) {
2699 assert(!State->contains<ObjCForHasMoreIterations>({O, LC}));
2700 return State->set<ObjCForHasMoreIterations>({O, LC}, HasMoreIteraton);
2701}
2702
2705 const ObjCForCollectionStmt *O,
2706 const LocationContext *LC) {
2707 assert(State->contains<ObjCForHasMoreIterations>({O, LC}));
2708 return State->remove<ObjCForHasMoreIterations>({O, LC});
2709}
2710
2712 const ObjCForCollectionStmt *O,
2713 const LocationContext *LC) {
2714 assert(State->contains<ObjCForHasMoreIterations>({O, LC}));
2715 return *State->get<ObjCForHasMoreIterations>({O, LC});
2716}
2717
2718/// Split the state on whether there are any more iterations left for this loop.
2719/// Returns a (HasMoreIteration, HasNoMoreIteration) pair, or std::nullopt when
2720/// the acquisition of the loop condition value failed.
2721static std::optional<std::pair<ProgramStateRef, ProgramStateRef>>
2723 ProgramStateRef State = N->getState();
2724 if (const auto *ObjCFor = dyn_cast<ObjCForCollectionStmt>(Condition)) {
2725 bool HasMoreIteraton =
2727 // Checkers have already ran on branch conditions, so the current
2728 // information as to whether the loop has more iteration becomes outdated
2729 // after this point.
2730 State = ExprEngine::removeIterationState(State, ObjCFor,
2731 N->getLocationContext());
2732 if (HasMoreIteraton)
2733 return std::pair<ProgramStateRef, ProgramStateRef>{State, nullptr};
2734 else
2735 return std::pair<ProgramStateRef, ProgramStateRef>{nullptr, State};
2736 }
2737 SVal X = State->getSVal(Condition, N->getLocationContext());
2738
2739 if (X.isUnknownOrUndef()) {
2740 // Give it a chance to recover from unknown.
2741 if (const auto *Ex = dyn_cast<Expr>(Condition)) {
2742 if (Ex->getType()->isIntegralOrEnumerationType()) {
2743 // Try to recover some path-sensitivity. Right now casts of symbolic
2744 // integers that promote their values are currently not tracked well.
2745 // If 'Condition' is such an expression, try and recover the
2746 // underlying value and use that instead.
2747 SVal recovered =
2749 N->getState()->getStateManager().getContext());
2750
2751 if (!recovered.isUnknown()) {
2752 X = recovered;
2753 }
2754 }
2755 }
2756 }
2757
2758 // If the condition is still unknown, give up.
2759 if (X.isUnknownOrUndef())
2760 return std::nullopt;
2761
2762 DefinedSVal V = X.castAs<DefinedSVal>();
2763
2764 ProgramStateRef StTrue, StFalse;
2765 return State->assume(V);
2766}
2767
2769 const Stmt *Condition, NodeBuilderContext &BldCtx, ExplodedNode *Pred,
2770 ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF,
2771 std::optional<unsigned> IterationsCompletedInLoop) {
2772 assert((!Condition || !isa<CXXBindTemporaryExpr>(Condition)) &&
2773 "CXXBindTemporaryExprs are handled by processBindTemporary.");
2774 const LocationContext *LCtx = Pred->getLocationContext();
2775 PrettyStackTraceLocationContext StackCrashInfo(LCtx);
2776 currBldrCtx = &BldCtx;
2777
2778 // Check for NULL conditions; e.g. "for(;;)"
2779 if (!Condition) {
2780 BranchNodeBuilder NullCondBldr(Pred, Dst, BldCtx, DstT, DstF);
2781 NullCondBldr.generateNode(Pred->getState(), true, Pred);
2782 return;
2783 }
2784
2785 if (const auto *Ex = dyn_cast<Expr>(Condition))
2786 Condition = Ex->IgnoreParens();
2787
2789 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
2790 Condition->getBeginLoc(),
2791 "Error evaluating branch");
2792
2793 ExplodedNodeSet CheckersOutSet;
2795 Pred, *this);
2796 // We generated only sinks.
2797 if (CheckersOutSet.empty())
2798 return;
2799
2800 BranchNodeBuilder Builder(CheckersOutSet, Dst, BldCtx, DstT, DstF);
2801 for (ExplodedNode *PredN : CheckersOutSet) {
2802 if (PredN->isSink())
2803 continue;
2804
2805 ProgramStateRef PrevState = PredN->getState();
2806
2807 ProgramStateRef StTrue = PrevState, StFalse = PrevState;
2808 if (const auto KnownCondValueAssumption = assumeCondition(Condition, PredN))
2809 std::tie(StTrue, StFalse) = *KnownCondValueAssumption;
2810
2811 if (StTrue && StFalse)
2812 assert(!isa<ObjCForCollectionStmt>(Condition));
2813
2814 if (StTrue) {
2815 // If we are processing a loop condition where two iterations have
2816 // already been completed and the false branch is also feasible, then
2817 // don't assume a third iteration because it is a redundant execution
2818 // path (unlikely to be different from earlier loop exits) and can cause
2819 // false positives if e.g. the loop iterates over a two-element structure
2820 // with an opaque condition.
2821 //
2822 // The iteration count "2" is hardcoded because it's the natural limit:
2823 // * the fact that the programmer wrote a loop (and not just an `if`)
2824 // implies that they thought that the loop body might be executed twice;
2825 // * however, there are situations where the programmer knows that there
2826 // are at most two iterations but writes a loop that appears to be
2827 // generic, because there is no special syntax for "loop with at most
2828 // two iterations". (This pattern is common in FFMPEG and appears in
2829 // many other projects as well.)
2830 bool CompletedTwoIterations = IterationsCompletedInLoop.value_or(0) >= 2;
2831 bool FalseAlsoFeasible =
2832 StFalse ||
2833 didEagerlyAssumeBifurcateAt(PrevState, dyn_cast<Expr>(Condition));
2834 bool SkipTrueBranch = CompletedTwoIterations && FalseAlsoFeasible;
2835
2836 // FIXME: This "don't assume third iteration" heuristic partially
2837 // conflicts with the widen-loop analysis option (which is off by
2838 // default). If we intend to support and stabilize the loop widening,
2839 // we must ensure that it 'plays nicely' with this logic.
2840 if (!SkipTrueBranch || AMgr.options.ShouldWidenLoops)
2841 Builder.generateNode(StTrue, true, PredN);
2842 }
2843
2844 if (StFalse)
2845 Builder.generateNode(StFalse, false, PredN);
2846 }
2847 currBldrCtx = nullptr;
2848}
2849
2850/// The GDM component containing the set of global variables which have been
2851/// previously initialized with explicit initializers.
2853 llvm::ImmutableSet<const VarDecl *>)
2854
2856 NodeBuilderContext &BuilderCtx,
2857 ExplodedNode *Pred,
2858 ExplodedNodeSet &Dst,
2859 const CFGBlock *DstT,
2860 const CFGBlock *DstF) {
2862 currBldrCtx = &BuilderCtx;
2863
2864 const auto *VD = cast<VarDecl>(DS->getSingleDecl());
2865 ProgramStateRef state = Pred->getState();
2866 bool initHasRun = state->contains<InitializedGlobalsSet>(VD);
2867 BranchNodeBuilder Builder(Pred, Dst, BuilderCtx, DstT, DstF);
2868
2869 if (!initHasRun) {
2870 state = state->add<InitializedGlobalsSet>(VD);
2871 }
2872
2873 Builder.generateNode(state, initHasRun, Pred);
2874
2875 currBldrCtx = nullptr;
2876}
2877
2878/// processIndirectGoto - Called by CoreEngine. Used to generate successor
2879/// nodes by processing the 'effects' of a computed goto jump.
2881 ProgramStateRef state = builder.getState();
2882 SVal V = state->getSVal(builder.getTarget(), builder.getLocationContext());
2883
2884 // Three possibilities:
2885 //
2886 // (1) We know the computed label.
2887 // (2) The label is NULL (or some other constant), or Undefined.
2888 // (3) We have no clue about the label. Dispatch to all targets.
2889 //
2890
2891 using iterator = IndirectGotoNodeBuilder::iterator;
2892
2893 if (std::optional<loc::GotoLabel> LV = V.getAs<loc::GotoLabel>()) {
2894 const LabelDecl *L = LV->getLabel();
2895
2896 for (iterator Succ : builder) {
2897 if (Succ.getLabel() == L) {
2898 builder.generateNode(Succ, state);
2899 return;
2900 }
2901 }
2902
2903 llvm_unreachable("No block with label.");
2904 }
2905
2906 if (isa<UndefinedVal, loc::ConcreteInt>(V)) {
2907 // Dispatch to the first target and mark it as a sink.
2908 //ExplodedNode* N = builder.generateNode(builder.begin(), state, true);
2909 // FIXME: add checker visit.
2910 // UndefBranches.insert(N);
2911 return;
2912 }
2913
2914 // This is really a catch-all. We don't support symbolics yet.
2915 // FIXME: Implement dispatch for symbolic pointers.
2916
2917 for (iterator Succ : builder)
2918 builder.generateNode(Succ, state);
2919}
2920
2922 ExplodedNode *Pred,
2923 ExplodedNodeSet &Dst,
2924 const BlockEdge &L) {
2925 SaveAndRestore<const NodeBuilderContext *> NodeContextRAII(currBldrCtx, &BC);
2926 getCheckerManager().runCheckersForBeginFunction(Dst, L, Pred, *this);
2927}
2928
2929/// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path
2930/// nodes when the control reaches the end of a function.
2932 ExplodedNode *Pred,
2933 const ReturnStmt *RS) {
2934 ProgramStateRef State = Pred->getState();
2935
2936 if (!Pred->getStackFrame()->inTopFrame())
2937 State = finishArgumentConstruction(
2938 State, *getStateManager().getCallEventManager().getCaller(
2939 Pred->getStackFrame(), Pred->getState()));
2940
2941 // FIXME: We currently cannot assert that temporaries are clear, because
2942 // lifetime extended temporaries are not always modelled correctly. In some
2943 // cases when we materialize the temporary, we do
2944 // createTemporaryRegionIfNeeded(), and the region changes, and also the
2945 // respective destructor becomes automatic from temporary. So for now clean up
2946 // the state manually before asserting. Ideally, this braced block of code
2947 // should go away.
2948 {
2949 const LocationContext *FromLC = Pred->getLocationContext();
2950 const LocationContext *ToLC = FromLC->getStackFrame()->getParent();
2951 const LocationContext *LC = FromLC;
2952 while (LC != ToLC) {
2953 assert(LC && "ToLC must be a parent of FromLC!");
2954 for (auto I : State->get<ObjectsUnderConstruction>())
2955 if (I.first.getLocationContext() == LC) {
2956 // The comment above only pardons us for not cleaning up a
2957 // temporary destructor. If any other statements are found here,
2958 // it must be a separate problem.
2959 assert(I.first.getItem().getKind() ==
2961 I.first.getItem().getKind() ==
2963 State = State->remove<ObjectsUnderConstruction>(I.first);
2964 }
2965 LC = LC->getParent();
2966 }
2967 }
2968
2969 // Perform the transition with cleanups.
2970 if (State != Pred->getState()) {
2971 ExplodedNodeSet PostCleanup;
2972 NodeBuilder Bldr(Pred, PostCleanup, BC);
2973 Pred = Bldr.generateNode(Pred->getLocation(), State, Pred);
2974 if (!Pred) {
2975 // The node with clean temporaries already exists. We might have reached
2976 // it on a path on which we initialize different temporaries.
2977 return;
2978 }
2979 }
2980
2981 assert(areAllObjectsFullyConstructed(Pred->getState(),
2982 Pred->getLocationContext(),
2983 Pred->getStackFrame()->getParent()));
2984
2986
2987 ExplodedNodeSet Dst;
2988 if (Pred->getLocationContext()->inTopFrame()) {
2989 // Remove dead symbols.
2990 ExplodedNodeSet AfterRemovedDead;
2991 removeDeadOnEndOfFunction(BC, Pred, AfterRemovedDead);
2992
2993 // Notify checkers.
2994 for (const auto I : AfterRemovedDead)
2995 getCheckerManager().runCheckersForEndFunction(BC, Dst, I, *this, RS);
2996 } else {
2997 getCheckerManager().runCheckersForEndFunction(BC, Dst, Pred, *this, RS);
2998 }
2999
3000 Engine.enqueueEndOfFunction(Dst, RS);
3001}
3002
3003/// ProcessSwitch - Called by CoreEngine. Used to generate successor
3004/// nodes by processing the 'effects' of a switch statement.
3006 using iterator = SwitchNodeBuilder::iterator;
3007
3008 ProgramStateRef state = builder.getState();
3009 const Expr *CondE = builder.getCondition();
3010 SVal CondV_untested = state->getSVal(CondE, builder.getLocationContext());
3011
3012 if (CondV_untested.isUndef()) {
3013 //ExplodedNode* N = builder.generateDefaultCaseNode(state, true);
3014 // FIXME: add checker
3015 //UndefBranches.insert(N);
3016
3017 return;
3018 }
3019 DefinedOrUnknownSVal CondV = CondV_untested.castAs<DefinedOrUnknownSVal>();
3020
3021 ProgramStateRef DefaultSt = state;
3022
3023 iterator I = builder.begin(), EI = builder.end();
3024 bool defaultIsFeasible = I == EI;
3025
3026 for ( ; I != EI; ++I) {
3027 // Successor may be pruned out during CFG construction.
3028 if (!I.getBlock())
3029 continue;
3030
3031 const CaseStmt *Case = I.getCase();
3032
3033 // Evaluate the LHS of the case value.
3034 llvm::APSInt V1 = Case->getLHS()->EvaluateKnownConstInt(getContext());
3035 assert(V1.getBitWidth() == getContext().getIntWidth(CondE->getType()));
3036
3037 // Get the RHS of the case, if it exists.
3038 llvm::APSInt V2;
3039 if (const Expr *E = Case->getRHS())
3041 else
3042 V2 = V1;
3043
3044 ProgramStateRef StateCase;
3045 if (std::optional<NonLoc> NL = CondV.getAs<NonLoc>())
3046 std::tie(StateCase, DefaultSt) =
3047 DefaultSt->assumeInclusiveRange(*NL, V1, V2);
3048 else // UnknownVal
3049 StateCase = DefaultSt;
3050
3051 if (StateCase)
3052 builder.generateCaseStmtNode(I, StateCase);
3053
3054 // Now "assume" that the case doesn't match. Add this state
3055 // to the default state (if it is feasible).
3056 if (DefaultSt)
3057 defaultIsFeasible = true;
3058 else {
3059 defaultIsFeasible = false;
3060 break;
3061 }
3062 }
3063
3064 if (!defaultIsFeasible)
3065 return;
3066
3067 // If we have switch(enum value), the default branch is not
3068 // feasible if all of the enum constants not covered by 'case:' statements
3069 // are not feasible values for the switch condition.
3070 //
3071 // Note that this isn't as accurate as it could be. Even if there isn't
3072 // a case for a particular enum value as long as that enum value isn't
3073 // feasible then it shouldn't be considered for making 'default:' reachable.
3074 const SwitchStmt *SS = builder.getSwitch();
3075 const Expr *CondExpr = SS->getCond()->IgnoreParenImpCasts();
3076 if (CondExpr->getType()->getAs<EnumType>()) {
3077 if (SS->isAllEnumCasesCovered())
3078 return;
3079 }
3080
3081 builder.generateDefaultCaseNode(DefaultSt);
3082}
3083
3084//===----------------------------------------------------------------------===//
3085// Transfer functions: Loads and stores.
3086//===----------------------------------------------------------------------===//
3087
3089 ExplodedNode *Pred,
3090 ExplodedNodeSet &Dst) {
3091 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
3092
3093 ProgramStateRef state = Pred->getState();
3094 const LocationContext *LCtx = Pred->getLocationContext();
3095
3096 if (const auto *VD = dyn_cast<VarDecl>(D)) {
3097 // C permits "extern void v", and if you cast the address to a valid type,
3098 // you can even do things with it. We simply pretend
3099 assert(Ex->isGLValue() || VD->getType()->isVoidType());
3100 const LocationContext *LocCtxt = Pred->getLocationContext();
3101 const Decl *D = LocCtxt->getDecl();
3102 const auto *MD = dyn_cast_or_null<CXXMethodDecl>(D);
3103 const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
3104 std::optional<std::pair<SVal, QualType>> VInfo;
3105
3106 if (AMgr.options.ShouldInlineLambdas && DeclRefEx &&
3107 DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
3108 MD->getParent()->isLambda()) {
3109 // Lookup the field of the lambda.
3110 const CXXRecordDecl *CXXRec = MD->getParent();
3111 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
3112 FieldDecl *LambdaThisCaptureField;
3113 CXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField);
3114
3115 // Sema follows a sequence of complex rules to determine whether the
3116 // variable should be captured.
3117 if (const FieldDecl *FD = LambdaCaptureFields[VD]) {
3118 Loc CXXThis =
3119 svalBuilder.getCXXThis(MD, LocCtxt->getStackFrame());
3120 SVal CXXThisVal = state->getSVal(CXXThis);
3121 VInfo = std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType());
3122 }
3123 }
3124
3125 if (!VInfo)
3126 VInfo = std::make_pair(state->getLValue(VD, LocCtxt), VD->getType());
3127
3128 SVal V = VInfo->first;
3129 bool IsReference = VInfo->second->isReferenceType();
3130
3131 // For references, the 'lvalue' is the pointer address stored in the
3132 // reference region.
3133 if (IsReference) {
3134 if (const MemRegion *R = V.getAsRegion())
3135 V = state->getSVal(R);
3136 else
3137 V = UnknownVal();
3138 }
3139
3140 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
3142 return;
3143 }
3144 if (const auto *ED = dyn_cast<EnumConstantDecl>(D)) {
3145 assert(!Ex->isGLValue());
3146 SVal V = svalBuilder.makeIntVal(ED->getInitVal());
3147 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V));
3148 return;
3149 }
3150 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
3151 SVal V = svalBuilder.getFunctionPointer(FD);
3152 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
3154 return;
3155 }
3156 if (isa<FieldDecl, IndirectFieldDecl>(D)) {
3157 // Delegate all work related to pointer to members to the surrounding
3158 // operator&.
3159 return;
3160 }
3161 if (const auto *BD = dyn_cast<BindingDecl>(D)) {
3162 const auto *DD = cast<DecompositionDecl>(BD->getDecomposedDecl());
3163
3164 SVal Base = state->getLValue(DD, LCtx);
3165 if (DD->getType()->isReferenceType()) {
3166 if (const MemRegion *R = Base.getAsRegion())
3167 Base = state->getSVal(R);
3168 else
3169 Base = UnknownVal();
3170 }
3171
3172 SVal V = UnknownVal();
3173
3174 // Handle binding to data members
3175 if (const auto *ME = dyn_cast<MemberExpr>(BD->getBinding())) {
3176 const auto *Field = cast<FieldDecl>(ME->getMemberDecl());
3177 V = state->getLValue(Field, Base);
3178 }
3179 // Handle binding to arrays
3180 else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(BD->getBinding())) {
3181 SVal Idx = state->getSVal(ASE->getIdx(), LCtx);
3182
3183 // Note: the index of an element in a structured binding is automatically
3184 // created and it is a unique identifier of the specific element. Thus it
3185 // cannot be a value that varies at runtime.
3186 assert(Idx.isConstant() && "BindingDecl array index is not a constant!");
3187
3188 V = state->getLValue(BD->getType(), Idx, Base);
3189 }
3190 // Handle binding to tuple-like structures
3191 else if (const auto *HV = BD->getHoldingVar()) {
3192 V = state->getLValue(HV, LCtx);
3193
3194 if (HV->getType()->isReferenceType()) {
3195 if (const MemRegion *R = V.getAsRegion())
3196 V = state->getSVal(R);
3197 else
3198 V = UnknownVal();
3199 }
3200 } else
3201 llvm_unreachable("An unknown case of structured binding encountered!");
3202
3203 // In case of tuple-like types the references are already handled, so we
3204 // don't want to handle them again.
3205 if (BD->getType()->isReferenceType() && !BD->getHoldingVar()) {
3206 if (const MemRegion *R = V.getAsRegion())
3207 V = state->getSVal(R);
3208 else
3209 V = UnknownVal();
3210 }
3211
3212 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
3214
3215 return;
3216 }
3217
3218 if (const auto *TPO = dyn_cast<TemplateParamObjectDecl>(D)) {
3219 // FIXME: We should meaningfully implement this.
3220 (void)TPO;
3221 return;
3222 }
3223
3224 llvm_unreachable("Support for this Decl not implemented.");
3225}
3226
3227/// VisitArrayInitLoopExpr - Transfer function for array init loop.
3229 ExplodedNode *Pred,
3230 ExplodedNodeSet &Dst) {
3231 ExplodedNodeSet CheckerPreStmt;
3232 getCheckerManager().runCheckersForPreStmt(CheckerPreStmt, Pred, Ex, *this);
3233
3234 ExplodedNodeSet EvalSet;
3235 StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);
3236
3237 const Expr *Arr = Ex->getCommonExpr()->getSourceExpr();
3238
3239 for (auto *Node : CheckerPreStmt) {
3240
3241 // The constructor visitior has already taken care of everything.
3242 if (isa<CXXConstructExpr>(Ex->getSubExpr()))
3243 break;
3244
3245 const LocationContext *LCtx = Node->getLocationContext();
3246 ProgramStateRef state = Node->getState();
3247
3248 SVal Base = UnknownVal();
3249
3250 // As in case of this expression the sub-expressions are not visited by any
3251 // other transfer functions, they are handled by matching their AST.
3252
3253 // Case of implicit copy or move ctor of object with array member
3254 //
3255 // Note: ExprEngine::VisitMemberExpr is not able to bind the array to the
3256 // environment.
3257 //
3258 // struct S {
3259 // int arr[2];
3260 // };
3261 //
3262 //
3263 // S a;
3264 // S b = a;
3265 //
3266 // The AST in case of a *copy constructor* looks like this:
3267 // ArrayInitLoopExpr
3268 // |-OpaqueValueExpr
3269 // | `-MemberExpr <-- match this
3270 // | `-DeclRefExpr
3271 // ` ...
3272 //
3273 //
3274 // S c;
3275 // S d = std::move(d);
3276 //
3277 // In case of a *move constructor* the resulting AST looks like:
3278 // ArrayInitLoopExpr
3279 // |-OpaqueValueExpr
3280 // | `-MemberExpr <-- match this first
3281 // | `-CXXStaticCastExpr <-- match this after
3282 // | `-DeclRefExpr
3283 // ` ...
3284 if (const auto *ME = dyn_cast<MemberExpr>(Arr)) {
3285 Expr *MEBase = ME->getBase();
3286
3287 // Move ctor
3288 if (auto CXXSCE = dyn_cast<CXXStaticCastExpr>(MEBase)) {
3289 MEBase = CXXSCE->getSubExpr();
3290 }
3291
3292 auto ObjDeclExpr = cast<DeclRefExpr>(MEBase);
3293 SVal Obj = state->getLValue(cast<VarDecl>(ObjDeclExpr->getDecl()), LCtx);
3294
3295 Base = state->getLValue(cast<FieldDecl>(ME->getMemberDecl()), Obj);
3296 }
3297
3298 // Case of lambda capture and decomposition declaration
3299 //
3300 // int arr[2];
3301 //
3302 // [arr]{ int a = arr[0]; }();
3303 // auto[a, b] = arr;
3304 //
3305 // In both of these cases the AST looks like the following:
3306 // ArrayInitLoopExpr
3307 // |-OpaqueValueExpr
3308 // | `-DeclRefExpr <-- match this
3309 // ` ...
3310 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arr))
3311 Base = state->getLValue(cast<VarDecl>(DRE->getDecl()), LCtx);
3312
3313 // Create a lazy compound value to the original array
3314 if (const MemRegion *R = Base.getAsRegion())
3315 Base = state->getSVal(R);
3316 else
3317 Base = UnknownVal();
3318
3319 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, Base));
3320 }
3321
3322 getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, Ex, *this);
3323}
3324
3325/// VisitArraySubscriptExpr - Transfer function for array accesses
3327 ExplodedNode *Pred,
3328 ExplodedNodeSet &Dst){
3329 const Expr *Base = A->getBase()->IgnoreParens();
3330 const Expr *Idx = A->getIdx()->IgnoreParens();
3331
3332 ExplodedNodeSet CheckerPreStmt;
3333 getCheckerManager().runCheckersForPreStmt(CheckerPreStmt, Pred, A, *this);
3334
3335 ExplodedNodeSet EvalSet;
3336 StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);
3337
3338 bool IsVectorType = A->getBase()->getType()->isVectorType();
3339
3340 // The "like" case is for situations where C standard prohibits the type to
3341 // be an lvalue, e.g. taking the address of a subscript of an expression of
3342 // type "void *".
3343 bool IsGLValueLike = A->isGLValue() ||
3344 (A->getType().isCForbiddenLValueType() && !AMgr.getLangOpts().CPlusPlus);
3345
3346 for (auto *Node : CheckerPreStmt) {
3347 const LocationContext *LCtx = Node->getLocationContext();
3348 ProgramStateRef state = Node->getState();
3349
3350 if (IsGLValueLike) {
3351 QualType T = A->getType();
3352
3353 // One of the forbidden LValue types! We still need to have sensible
3354 // symbolic locations to represent this stuff. Note that arithmetic on
3355 // void pointers is a GCC extension.
3356 if (T->isVoidType())
3357 T = getContext().CharTy;
3358
3359 SVal V = state->getLValue(T,
3360 state->getSVal(Idx, LCtx),
3361 state->getSVal(Base, LCtx));
3362 Bldr.generateNode(A, Node, state->BindExpr(A, LCtx, V), nullptr,
3364 } else if (IsVectorType) {
3365 // FIXME: non-glvalue vector reads are not modelled.
3366 Bldr.generateNode(A, Node, state, nullptr);
3367 } else {
3368 llvm_unreachable("Array subscript should be an lValue when not \
3369a vector and not a forbidden lvalue type");
3370 }
3371 }
3372
3373 getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, A, *this);
3374}
3375
3376/// VisitMemberExpr - Transfer function for member expressions.
3378 ExplodedNodeSet &Dst) {
3379 // FIXME: Prechecks eventually go in ::Visit().
3380 ExplodedNodeSet CheckedSet;
3381 getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, M, *this);
3382
3383 ExplodedNodeSet EvalSet;
3385
3386 // Handle static member variables and enum constants accessed via
3387 // member syntax.
3388 if (isa<VarDecl, EnumConstantDecl>(Member)) {
3389 for (const auto I : CheckedSet)
3390 VisitCommonDeclRefExpr(M, Member, I, EvalSet);
3391 } else {
3392 StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx);
3393 ExplodedNodeSet Tmp;
3394
3395 for (const auto I : CheckedSet) {
3396 ProgramStateRef state = I->getState();
3397 const LocationContext *LCtx = I->getLocationContext();
3398 Expr *BaseExpr = M->getBase();
3399
3400 // Handle C++ method calls.
3401 if (const auto *MD = dyn_cast<CXXMethodDecl>(Member)) {
3402 if (MD->isImplicitObjectMemberFunction())
3403 state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr);
3404
3405 SVal MDVal = svalBuilder.getFunctionPointer(MD);
3406 state = state->BindExpr(M, LCtx, MDVal);
3407
3408 Bldr.generateNode(M, I, state);
3409 continue;
3410 }
3411
3412 // Handle regular struct fields / member variables.
3413 const SubRegion *MR = nullptr;
3414 state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr,
3415 /*Result=*/nullptr,
3416 /*OutRegionWithAdjustments=*/&MR);
3417 SVal baseExprVal =
3418 MR ? loc::MemRegionVal(MR) : state->getSVal(BaseExpr, LCtx);
3419
3420 // FIXME: Copied from RegionStoreManager::bind()
3421 if (const auto *SR =
3422 dyn_cast_or_null<SymbolicRegion>(baseExprVal.getAsRegion())) {
3423 QualType T = SR->getPointeeStaticType();
3424 baseExprVal =
3425 loc::MemRegionVal(getStoreManager().GetElementZeroRegion(SR, T));
3426 }
3427
3428 const auto *field = cast<FieldDecl>(Member);
3429 SVal L = state->getLValue(field, baseExprVal);
3430
3431 if (M->isGLValue() || M->getType()->isArrayType()) {
3432 // We special-case rvalues of array type because the analyzer cannot
3433 // reason about them, since we expect all regions to be wrapped in Locs.
3434 // We instead treat these as lvalues and assume that they will decay to
3435 // pointers as soon as they are used.
3436 if (!M->isGLValue()) {
3437 assert(M->getType()->isArrayType());
3438 const auto *PE =
3439 dyn_cast<ImplicitCastExpr>(I->getParentMap().getParentIgnoreParens(M));
3440 if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {
3441 llvm_unreachable("should always be wrapped in ArrayToPointerDecay");
3442 }
3443 }
3444
3445 if (field->getType()->isReferenceType()) {
3446 if (const MemRegion *R = L.getAsRegion())
3447 L = state->getSVal(R);
3448 else
3449 L = UnknownVal();
3450 }
3451
3452 Bldr.generateNode(M, I, state->BindExpr(M, LCtx, L), nullptr,
3454 } else {
3455 Bldr.takeNodes(I);
3456 evalLoad(Tmp, M, M, I, state, L);
3457 Bldr.addNodes(Tmp);
3458 }
3459 }
3460 }
3461
3462 getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, M, *this);
3463}
3464
3466 ExplodedNodeSet &Dst) {
3467 ExplodedNodeSet AfterPreSet;
3468 getCheckerManager().runCheckersForPreStmt(AfterPreSet, Pred, AE, *this);
3469
3470 // For now, treat all the arguments to C11 atomics as escaping.
3471 // FIXME: Ideally we should model the behavior of the atomics precisely here.
3472
3473 ExplodedNodeSet AfterInvalidateSet;
3474 StmtNodeBuilder Bldr(AfterPreSet, AfterInvalidateSet, *currBldrCtx);
3475
3476 for (const auto I : AfterPreSet) {
3477 ProgramStateRef State = I->getState();
3478 const LocationContext *LCtx = I->getLocationContext();
3479
3480 SmallVector<SVal, 8> ValuesToInvalidate;
3481 for (unsigned SI = 0, Count = AE->getNumSubExprs(); SI != Count; SI++) {
3482 const Expr *SubExpr = AE->getSubExprs()[SI];
3483 SVal SubExprVal = State->getSVal(SubExpr, LCtx);
3484 ValuesToInvalidate.push_back(SubExprVal);
3485 }
3486
3487 State = State->invalidateRegions(ValuesToInvalidate, AE,
3488 currBldrCtx->blockCount(),
3489 LCtx,
3490 /*CausedByPointerEscape*/true,
3491 /*Symbols=*/nullptr);
3492
3493 SVal ResultVal = UnknownVal();
3494 State = State->BindExpr(AE, LCtx, ResultVal);
3495 Bldr.generateNode(AE, I, State, nullptr,
3497 }
3498
3499 getCheckerManager().runCheckersForPostStmt(Dst, AfterInvalidateSet, AE, *this);
3500}
3501
3502// A value escapes in four possible cases:
3503// (1) We are binding to something that is not a memory region.
3504// (2) We are binding to a MemRegion that does not have stack storage.
3505// (3) We are binding to a top-level parameter region with a non-trivial
3506// destructor. We won't see the destructor during analysis, but it's there.
3507// (4) We are binding to a MemRegion with stack storage that the store
3508// does not understand.
3510 ProgramStateRef State, ArrayRef<std::pair<SVal, SVal>> LocAndVals,
3511 const LocationContext *LCtx, PointerEscapeKind Kind,
3512 const CallEvent *Call) {
3513 SmallVector<SVal, 8> Escaped;
3514 for (const std::pair<SVal, SVal> &LocAndVal : LocAndVals) {
3515 // Cases (1) and (2).
3516 const MemRegion *MR = LocAndVal.first.getAsRegion();
3517 if (!MR ||
3518 !isa<StackSpaceRegion, StaticGlobalSpaceRegion>(MR->getMemorySpace())) {
3519 Escaped.push_back(LocAndVal.second);
3520 continue;
3521 }
3522
3523 // Case (3).
3524 if (const auto *VR = dyn_cast<VarRegion>(MR->getBaseRegion()))
3525 if (VR->hasStackParametersStorage() && VR->getStackFrame()->inTopFrame())
3526 if (const auto *RD = VR->getValueType()->getAsCXXRecordDecl())
3527 if (!RD->hasTrivialDestructor()) {
3528 Escaped.push_back(LocAndVal.second);
3529 continue;
3530 }
3531
3532 // Case (4): in order to test that, generate a new state with the binding
3533 // added. If it is the same state, then it escapes (since the store cannot
3534 // represent the binding).
3535 // Do this only if we know that the store is not supposed to generate the
3536 // same state.
3537 SVal StoredVal = State->getSVal(MR);
3538 if (StoredVal != LocAndVal.second)
3539 if (State ==
3540 (State->bindLoc(loc::MemRegionVal(MR), LocAndVal.second, LCtx)))
3541 Escaped.push_back(LocAndVal.second);
3542 }
3543
3544 if (Escaped.empty())
3545 return State;
3546
3547 return escapeValues(State, Escaped, Kind, Call);
3548}
3549
3552 SVal Val, const LocationContext *LCtx) {
3553 std::pair<SVal, SVal> LocAndVal(Loc, Val);
3554 return processPointerEscapedOnBind(State, LocAndVal, LCtx, PSK_EscapeOnBind,
3555 nullptr);
3556}
3557
3560 const InvalidatedSymbols *Invalidated,
3561 ArrayRef<const MemRegion *> ExplicitRegions,
3562 const CallEvent *Call,
3564 if (!Invalidated || Invalidated->empty())
3565 return State;
3566
3567 if (!Call)
3569 *Invalidated,
3570 nullptr,
3572 &ITraits);
3573
3574 // If the symbols were invalidated by a call, we want to find out which ones
3575 // were invalidated directly due to being arguments to the call.
3576 InvalidatedSymbols SymbolsDirectlyInvalidated;
3577 for (const auto I : ExplicitRegions) {
3578 if (const SymbolicRegion *R = I->StripCasts()->getAs<SymbolicRegion>())
3579 SymbolsDirectlyInvalidated.insert(R->getSymbol());
3580 }
3581
3582 InvalidatedSymbols SymbolsIndirectlyInvalidated;
3583 for (const auto &sym : *Invalidated) {
3584 if (SymbolsDirectlyInvalidated.count(sym))
3585 continue;
3586 SymbolsIndirectlyInvalidated.insert(sym);
3587 }
3588
3589 if (!SymbolsDirectlyInvalidated.empty())
3591 SymbolsDirectlyInvalidated, Call, PSK_DirectEscapeOnCall, &ITraits);
3592
3593 // Notify about the symbols that get indirectly invalidated by the call.
3594 if (!SymbolsIndirectlyInvalidated.empty())
3596 SymbolsIndirectlyInvalidated, Call, PSK_IndirectEscapeOnCall, &ITraits);
3597
3598 return State;
3599}
3600
3601/// evalBind - Handle the semantics of binding a value to a specific location.
3602/// This method is used by evalStore and (soon) VisitDeclStmt, and others.
3603void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
3604 ExplodedNode *Pred,
3605 SVal location, SVal Val,
3606 bool atDeclInit, const ProgramPoint *PP) {
3607 const LocationContext *LC = Pred->getLocationContext();
3608 PostStmt PS(StoreE, LC);
3609 if (!PP)
3610 PP = &PS;
3611
3612 // Do a previsit of the bind.
3613 ExplodedNodeSet CheckedSet;
3614 getCheckerManager().runCheckersForBind(CheckedSet, Pred, location, Val,
3615 StoreE, *this, *PP);
3616
3617 StmtNodeBuilder Bldr(CheckedSet, Dst, *currBldrCtx);
3618
3619 // If the location is not a 'Loc', it will already be handled by
3620 // the checkers. There is nothing left to do.
3621 if (!isa<Loc>(location)) {
3622 const ProgramPoint L = PostStore(StoreE, LC, /*Loc*/nullptr,
3623 /*tag*/nullptr);
3624 ProgramStateRef state = Pred->getState();
3625 state = processPointerEscapedOnBind(state, location, Val, LC);
3626 Bldr.generateNode(L, state, Pred);
3627 return;
3628 }
3629
3630 for (const auto PredI : CheckedSet) {
3631 ProgramStateRef state = PredI->getState();
3632
3633 state = processPointerEscapedOnBind(state, location, Val, LC);
3634
3635 // When binding the value, pass on the hint that this is a initialization.
3636 // For initializations, we do not need to inform clients of region
3637 // changes.
3638 state = state->bindLoc(location.castAs<Loc>(),
3639 Val, LC, /* notifyChanges = */ !atDeclInit);
3640
3641 const MemRegion *LocReg = nullptr;
3642 if (std::optional<loc::MemRegionVal> LocRegVal =
3643 location.getAs<loc::MemRegionVal>()) {
3644 LocReg = LocRegVal->getRegion();
3645 }
3646
3647 const ProgramPoint L = PostStore(StoreE, LC, LocReg, nullptr);
3648 Bldr.generateNode(L, state, PredI);
3649 }
3650}
3651
3652/// evalStore - Handle the semantics of a store via an assignment.
3653/// @param Dst The node set to store generated state nodes
3654/// @param AssignE The assignment expression if the store happens in an
3655/// assignment.
3656/// @param LocationE The location expression that is stored to.
3657/// @param state The current simulation state
3658/// @param location The location to store the value
3659/// @param Val The value to be stored
3661 const Expr *LocationE,
3662 ExplodedNode *Pred,
3663 ProgramStateRef state, SVal location, SVal Val,
3664 const ProgramPointTag *tag) {
3665 // Proceed with the store. We use AssignE as the anchor for the PostStore
3666 // ProgramPoint if it is non-NULL, and LocationE otherwise.
3667 const Expr *StoreE = AssignE ? AssignE : LocationE;
3668
3669 // Evaluate the location (checks for bad dereferences).
3670 ExplodedNodeSet Tmp;
3671 evalLocation(Tmp, AssignE, LocationE, Pred, state, location, false);
3672
3673 if (Tmp.empty())
3674 return;
3675
3676 if (location.isUndef())
3677 return;
3678
3679 for (const auto I : Tmp)
3680 evalBind(Dst, StoreE, I, location, Val, false);
3681}
3682
3684 const Expr *NodeEx,
3685 const Expr *BoundEx,
3686 ExplodedNode *Pred,
3687 ProgramStateRef state,
3688 SVal location,
3689 const ProgramPointTag *tag,
3690 QualType LoadTy) {
3691 assert(!isa<NonLoc>(location) && "location cannot be a NonLoc.");
3692 assert(NodeEx);
3693 assert(BoundEx);
3694 // Evaluate the location (checks for bad dereferences).
3695 ExplodedNodeSet Tmp;
3696 evalLocation(Tmp, NodeEx, BoundEx, Pred, state, location, true);
3697 if (Tmp.empty())
3698 return;
3699
3700 StmtNodeBuilder Bldr(Tmp, Dst, *currBldrCtx);
3701 if (location.isUndef())
3702 return;
3703
3704 // Proceed with the load.
3705 for (const auto I : Tmp) {
3706 state = I->getState();
3707 const LocationContext *LCtx = I->getLocationContext();
3708
3709 SVal V = UnknownVal();
3710 if (location.isValid()) {
3711 if (LoadTy.isNull())
3712 LoadTy = BoundEx->getType();
3713 V = state->getSVal(location.castAs<Loc>(), LoadTy);
3714 }
3715
3716 Bldr.generateNode(NodeEx, I, state->BindExpr(BoundEx, LCtx, V), tag,
3718 }
3719}
3720
3721void ExprEngine::evalLocation(ExplodedNodeSet &Dst,
3722 const Stmt *NodeEx,
3723 const Stmt *BoundEx,
3724 ExplodedNode *Pred,
3725 ProgramStateRef state,
3726 SVal location,
3727 bool isLoad) {
3728 StmtNodeBuilder BldrTop(Pred, Dst, *currBldrCtx);
3729 // Early checks for performance reason.
3730 if (location.isUnknown()) {
3731 return;
3732 }
3733
3734 ExplodedNodeSet Src;
3735 BldrTop.takeNodes(Pred);
3736 StmtNodeBuilder Bldr(Pred, Src, *currBldrCtx);
3737 if (Pred->getState() != state) {
3738 // Associate this new state with an ExplodedNode.
3739 // FIXME: If I pass null tag, the graph is incorrect, e.g for
3740 // int *p;
3741 // p = 0;
3742 // *p = 0xDEADBEEF;
3743 // "p = 0" is not noted as "Null pointer value stored to 'p'" but
3744 // instead "int *p" is noted as
3745 // "Variable 'p' initialized to a null pointer value"
3746
3747 static SimpleProgramPointTag tag(TagProviderName, "Location");
3748 Bldr.generateNode(NodeEx, Pred, state, &tag);
3749 }
3750 ExplodedNodeSet Tmp;
3751 getCheckerManager().runCheckersForLocation(Tmp, Src, location, isLoad,
3752 NodeEx, BoundEx, *this);
3753 BldrTop.addNodes(Tmp);
3754}
3755
3756std::pair<const ProgramPointTag *, const ProgramPointTag *>
3758 static SimpleProgramPointTag TrueTag(TagProviderName, "Eagerly Assume True"),
3759 FalseTag(TagProviderName, "Eagerly Assume False");
3760
3761 return std::make_pair(&TrueTag, &FalseTag);
3762}
3763
3764/// If the last EagerlyAssume attempt was successful (i.e. the true and false
3765/// cases were both feasible), this state trait stores the expression where it
3766/// happened; otherwise this holds nullptr.
3767REGISTER_TRAIT_WITH_PROGRAMSTATE(LastEagerlyAssumeExprIfSuccessful,
3768 const Expr *)
3769
3771 ExplodedNodeSet &Src,
3772 const Expr *Ex) {
3773 StmtNodeBuilder Bldr(Src, Dst, *currBldrCtx);
3774
3775 for (ExplodedNode *Pred : Src) {
3776 // Test if the previous node was as the same expression. This can happen
3777 // when the expression fails to evaluate to anything meaningful and
3778 // (as an optimization) we don't generate a node.
3779 ProgramPoint P = Pred->getLocation();
3780 if (!P.getAs<PostStmt>() || P.castAs<PostStmt>().getStmt() != Ex) {
3781 continue;
3782 }
3783
3784 ProgramStateRef State = Pred->getState();
3785 State = State->set<LastEagerlyAssumeExprIfSuccessful>(nullptr);
3786 SVal V = State->getSVal(Ex, Pred->getLocationContext());
3787 std::optional<nonloc::SymbolVal> SEV = V.getAs<nonloc::SymbolVal>();
3788 if (SEV && SEV->isExpression()) {
3789 const auto &[TrueTag, FalseTag] = getEagerlyAssumeBifurcationTags();
3790
3791 auto [StateTrue, StateFalse] = State->assume(*SEV);
3792
3793 if (StateTrue && StateFalse) {
3794 StateTrue = StateTrue->set<LastEagerlyAssumeExprIfSuccessful>(Ex);
3795 StateFalse = StateFalse->set<LastEagerlyAssumeExprIfSuccessful>(Ex);
3796 }
3797
3798 // First assume that the condition is true.
3799 if (StateTrue) {
3800 SVal Val = svalBuilder.makeIntVal(1U, Ex->getType());
3801 StateTrue = StateTrue->BindExpr(Ex, Pred->getLocationContext(), Val);
3802 Bldr.generateNode(Ex, Pred, StateTrue, TrueTag);
3803 }
3804
3805 // Next, assume that the condition is false.
3806 if (StateFalse) {
3807 SVal Val = svalBuilder.makeIntVal(0U, Ex->getType());
3808 StateFalse = StateFalse->BindExpr(Ex, Pred->getLocationContext(), Val);
3809 Bldr.generateNode(Ex, Pred, StateFalse, FalseTag);
3810 }
3811 }
3812 }
3813}
3814
3816 const Expr *Ex) const {
3817 return Ex && State->get<LastEagerlyAssumeExprIfSuccessful>() == Ex;
3818}
3819
3821 ExplodedNodeSet &Dst) {
3822 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
3823 // We have processed both the inputs and the outputs. All of the outputs
3824 // should evaluate to Locs. Nuke all of their values.
3825
3826 // FIXME: Some day in the future it would be nice to allow a "plug-in"
3827 // which interprets the inline asm and stores proper results in the
3828 // outputs.
3829
3830 ProgramStateRef state = Pred->getState();
3831
3832 for (const Expr *O : A->outputs()) {
3833 SVal X = state->getSVal(O, Pred->getLocationContext());
3834 assert(!isa<NonLoc>(X)); // Should be an Lval, or unknown, undef.
3835
3836 if (std::optional<Loc> LV = X.getAs<Loc>())
3837 state = state->invalidateRegions(*LV, A, currBldrCtx->blockCount(),
3838 Pred->getLocationContext(),
3839 /*CausedByPointerEscape=*/true);
3840 }
3841
3842 // Do not reason about locations passed inside inline assembly.
3843 for (const Expr *I : A->inputs()) {
3844 SVal X = state->getSVal(I, Pred->getLocationContext());
3845
3846 if (std::optional<Loc> LV = X.getAs<Loc>())
3847 state = state->invalidateRegions(*LV, A, currBldrCtx->blockCount(),
3848 Pred->getLocationContext(),
3849 /*CausedByPointerEscape=*/true);
3850 }
3851
3852 Bldr.generateNode(A, Pred, state);
3853}
3854
3856 ExplodedNodeSet &Dst) {
3857 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
3858 Bldr.generateNode(A, Pred, Pred->getState());
3859}
3860
3861//===----------------------------------------------------------------------===//
3862// Visualization.
3863//===----------------------------------------------------------------------===//
3864
3865namespace llvm {
3866
3867template<>
3868struct DOTGraphTraits<ExplodedGraph*> : public DefaultDOTGraphTraits {
3869 DOTGraphTraits (bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
3870
3871 static bool nodeHasBugReport(const ExplodedNode *N) {
3872 BugReporter &BR = static_cast<ExprEngine &>(
3873 N->getState()->getStateManager().getOwningEngine()).getBugReporter();
3874
3875 for (const auto &Class : BR.equivalenceClasses()) {
3876 for (const auto &Report : Class.getReports()) {
3877 const auto *PR = dyn_cast<PathSensitiveBugReport>(Report.get());
3878 if (!PR)
3879 continue;
3880 const ExplodedNode *EN = PR->getErrorNode();
3881 if (EN->getState() == N->getState() &&
3882 EN->getLocation() == N->getLocation())
3883 return true;
3884 }
3885 }
3886 return false;
3887 }
3888
3889 /// \p PreCallback: callback before break.
3890 /// \p PostCallback: callback after break.
3891 /// \p Stop: stop iteration if returns @c true
3892 /// \return Whether @c Stop ever returned @c true.
3894 const ExplodedNode *N,
3895 llvm::function_ref<void(const ExplodedNode *)> PreCallback,
3896 llvm::function_ref<void(const ExplodedNode *)> PostCallback,
3897 llvm::function_ref<bool(const ExplodedNode *)> Stop) {
3898 while (true) {
3899 PreCallback(N);
3900 if (Stop(N))
3901 return true;
3902
3903 if (N->succ_size() != 1 || !isNodeHidden(N->getFirstSucc(), nullptr))
3904 break;
3905 PostCallback(N);
3906
3907 N = N->getFirstSucc();
3908 }
3909 return false;
3910 }
3911
3912 static bool isNodeHidden(const ExplodedNode *N, const ExplodedGraph *G) {
3913 return N->isTrivial();
3914 }
3915
3916 static std::string getNodeLabel(const ExplodedNode *N, ExplodedGraph *G){
3917 std::string Buf;
3918 llvm::raw_string_ostream Out(Buf);
3919
3920 const bool IsDot = true;
3921 const unsigned int Space = 1;
3922 ProgramStateRef State = N->getState();
3923
3924 Out << "{ \"state_id\": " << State->getID()
3925 << ",\\l";
3926
3927 Indent(Out, Space, IsDot) << "\"program_points\": [\\l";
3928
3929 // Dump program point for all the previously skipped nodes.
3930 traverseHiddenNodes(
3931 N,
3932 [&](const ExplodedNode *OtherNode) {
3933 Indent(Out, Space + 1, IsDot) << "{ ";
3934 OtherNode->getLocation().printJson(Out, /*NL=*/"\\l");
3935 Out << ", \"tag\": ";
3936 if (const ProgramPointTag *Tag = OtherNode->getLocation().getTag())
3937 Out << '\"' << Tag->getTagDescription() << '\"';
3938 else
3939 Out << "null";
3940 Out << ", \"node_id\": " << OtherNode->getID() <<
3941 ", \"is_sink\": " << OtherNode->isSink() <<
3942 ", \"has_report\": " << nodeHasBugReport(OtherNode) << " }";
3943 },
3944 // Adds a comma and a new-line between each program point.
3945 [&](const ExplodedNode *) { Out << ",\\l"; },
3946 [&](const ExplodedNode *) { return false; });
3947
3948 Out << "\\l"; // Adds a new-line to the last program point.
3949 Indent(Out, Space, IsDot) << "],\\l";
3950
3951 State->printDOT(Out, N->getLocationContext(), Space);
3952
3953 Out << "\\l}\\l";
3954 return Buf;
3955 }
3956};
3957
3958} // namespace llvm
3959
3960void ExprEngine::ViewGraph(bool trim) {
3961 std::string Filename = DumpGraph(trim);
3962 llvm::DisplayGraph(Filename, false, llvm::GraphProgram::DOT);
3963}
3964
3966 std::string Filename = DumpGraph(Nodes);
3967 llvm::DisplayGraph(Filename, false, llvm::GraphProgram::DOT);
3968}
3969
3970std::string ExprEngine::DumpGraph(bool trim, StringRef Filename) {
3971 if (trim) {
3972 std::vector<const ExplodedNode *> Src;
3973
3974 // Iterate through the reports and get their nodes.
3975 for (const auto &Class : BR.equivalenceClasses()) {
3976 const auto *R =
3977 dyn_cast<PathSensitiveBugReport>(Class.getReports()[0].get());
3978 if (!R)
3979 continue;
3980 const auto *N = const_cast<ExplodedNode *>(R->getErrorNode());
3981 Src.push_back(N);
3982 }
3983 return DumpGraph(Src, Filename);
3984 }
3985
3986 return llvm::WriteGraph(&G, "ExprEngine", /*ShortNames=*/false,
3987 /*Title=*/"Exploded Graph",
3988 /*Filename=*/std::string(Filename));
3989}
3990
3992 StringRef Filename) {
3993 std::unique_ptr<ExplodedGraph> TrimmedG(G.trim(Nodes));
3994
3995 if (!TrimmedG.get()) {
3996 llvm::errs() << "warning: Trimmed ExplodedGraph is empty.\n";
3997 return "";
3998 }
3999
4000 return llvm::WriteGraph(TrimmedG.get(), "TrimmedExprEngine",
4001 /*ShortNames=*/false,
4002 /*Title=*/"Trimmed Exploded Graph",
4003 /*Filename=*/std::string(Filename));
4004}
4005
4007 static int index = 0;
4008 return &index;
4009}
4010
4011void ExprEngine::anchor() { }
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3460
BoundNodesTreeBuilder Nodes
DynTypedNode Node
StringRef P
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
static const MemRegion * getRegion(const CallEvent &Call, const MutexDescriptor &Descriptor, bool IsLock)
const Decl * D
Expr * E
static Decl::Kind getKind(const Decl *D)
Definition: DeclBase.cpp:1181
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
static const Stmt * getRightmostLeaf(const Stmt *Condition)
std::pair< const ObjCForCollectionStmt *, const LocationContext * > ObjCForLctxPair
static SVal RecoverCastedSymbol(ProgramStateRef state, const Stmt *Condition, const LocationContext *LCtx, ASTContext &Ctx)
RecoverCastedSymbol - A helper function for ProcessBranch that is used to try to recover some path-se...
static void printObjectsUnderConstructionJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
Definition: ExprEngine.cpp:685
static void printIndicesOfElementsToConstructJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
Definition: ExprEngine.cpp:731
static void printStateTraitWithLocationContextJson(raw_ostream &Out, ProgramStateRef State, const LocationContext *LCtx, const char *NL, unsigned int Space, bool IsDot, const char *jsonPropertyName, Printer printer, Args &&...args)
A helper function to generalize program state trait printing.
Definition: ExprEngine.cpp:910
static void printPendingArrayDestructionsJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
Definition: ExprEngine.cpp:854
static bool shouldRemoveDeadBindings(AnalysisManager &AMgr, const Stmt *S, const ExplodedNode *Pred, const LocationContext *LC)
static const Stmt * ResolveCondition(const Stmt *Condition, const CFGBlock *B)
REGISTER_TRAIT_WITH_PROGRAMSTATE(ObjectsUnderConstruction, ObjectsUnderConstructionMap) typedef llvm REGISTER_TRAIT_WITH_PROGRAMSTATE(IndexOfElementToConstruct, IndexOfElementToConstructMap) typedef llvm typedef llvm::ImmutableMap< const LocationContext *, unsigned > PendingArrayDestructionMap
Definition: ExprEngine.cpp:199
static void printPendingInitLoopJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
Definition: ExprEngine.cpp:793
llvm::ImmutableMap< ConstructedObjectKey, SVal > ObjectsUnderConstructionMap
Definition: ExprEngine.cpp:186
static std::optional< std::pair< ProgramStateRef, ProgramStateRef > > assumeCondition(const Stmt *Condition, ExplodedNode *N)
Split the state on whether there are any more iterations left for this loop.
STATISTIC(NumRemoveDeadBindings, "The # of times RemoveDeadBindings is called")
StringRef Filename
Definition: Format.cpp:3056
bool PostVisit
Definition: HTMLLogger.cpp:154
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
#define X(type, name)
Definition: Value.h:144
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::LangOptions interface.
This header contains the declarations of functions which are used to decide which loops should be com...
This header contains the declarations of functions which are used to widen loops which do not otherwi...
Defines the PrettyStackTraceEntry class, which is used to make crashes give more contextual informati...
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type)
Declares a program state trait for type Type called Name, and introduce a type named NameTy.
static bool isRecordType(QualType T)
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
Defines various enumerations that describe declaration and type specifiers.
Defines the Objective-C statement AST node classes.
C Language Family Type Representation.
__device__ int
#define bool
Definition: amdgpuintrin.h:20
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
SourceManager & getSourceManager()
Definition: ASTContext.h:741
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CanQualType CharTy
Definition: ASTContext.h:1162
const clang::PrintingPolicy & getPrintingPolicy() const
Definition: ASTContext.h:733
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2489
ASTContext & getASTContext() const
Stores options for the analyzer from the command line.
unsigned NoRetryExhausted
Do not re-analyze paths leading to exhausted nodes with a different strategy.
unsigned maxBlockVisitOnPath
The maximum number of times the analyzer visits a block.
AnalysisPurgeMode AnalysisPurgeOpt
Represents a loop initializing the elements of an array.
Definition: Expr.h:5752
OpaqueValueExpr * getCommonExpr() const
Get the common subexpression shared by all initializations (the source array).
Definition: Expr.h:5767
Expr * getSubExpr() const
Get the initializer to use for each array element.
Definition: Expr.h:5772
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2718
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: Type.h:3578
outputs_range outputs()
Definition: Stmt.h:3260
inputs_range inputs()
Definition: Stmt.h:3231
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
Definition: Expr.h:6678
Expr ** getSubExprs()
Definition: Expr.h:6755
static unsigned getNumSubExprs(AtomicOp Op)
Determine the number of arguments the specified atomic builtin should have.
Definition: Expr.cpp:5074
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
Definition: CFG.h:417
const VarDecl * getVarDecl() const
Definition: CFG.h:422
const Stmt * getTriggerStmt() const
Definition: CFG.h:427
Represents C++ object destructor implicitly generated for base object in destructor.
Definition: CFG.h:468
Represents a single basic block in a source-level CFG.
Definition: CFG.h:604
CFGTerminator getTerminator() const
Definition: CFG.h:1079
Stmt * getTerminatorStmt()
Definition: CFG.h:1081
Represents C++ object destructor generated from a call to delete.
Definition: CFG.h:442
const CXXDeleteExpr * getDeleteExpr() const
Definition: CFG.h:452
Represents a top-level expression in a basic block.
Definition: CFG.h:55
@ CleanupFunction
Definition: CFG.h:79
@ LifetimeEnds
Definition: CFG.h:63
@ CXXRecordTypedCall
Definition: CFG.h:68
@ AutomaticObjectDtor
Definition: CFG.h:72
@ TemporaryDtor
Definition: CFG.h:76
@ NewAllocator
Definition: CFG.h:62
Represents C++ object destructor implicitly generated by compiler on various occasions.
Definition: CFG.h:366
const CXXDestructorDecl * getDestructorDecl(ASTContext &astContext) const
Definition: CFG.cpp:5295
Represents C++ base or member initializer from constructor's initialization list.
Definition: CFG.h:227
CXXCtorInitializer * getInitializer() const
Definition: CFG.h:232
Represents the point where a loop ends.
Definition: CFG.h:273
const Stmt * getLoopStmt() const
Definition: CFG.h:277
Represents C++ object destructor implicitly generated for member object in destructor.
Definition: CFG.h:489
Represents C++ allocator call.
Definition: CFG.h:247
const CXXNewExpr * getAllocatorExpr() const
Definition: CFG.h:253
const Stmt * getStmt() const
Definition: CFG.h:138
Represents C++ object destructor implicitly generated at the end of full expression for temporary obj...
Definition: CFG.h:510
bool isStmtBranch() const
Definition: CFG.h:567
Represents a base class of a C++ class.
Definition: DeclCXX.h:146
Represents binding an expression to a temporary.
Definition: ExprCXX.h:1491
Represents a call to a C++ constructor.
Definition: ExprCXX.h:1546
Represents a C++ base or member initializer.
Definition: DeclCXX.h:2357
FieldDecl * getMember() const
If this is a member initializer, returns the declaration of the non-static data member being initiali...
Definition: DeclCXX.h:2497
bool isDelegatingInitializer() const
Determine whether this initializer is creating a delegating constructor.
Definition: DeclCXX.h:2457
Expr * getInit() const
Get the initializer.
Definition: DeclCXX.h:2559
SourceLocation getSourceLocation() const
Determine the source location of the initializer.
Definition: DeclCXX.cpp:2796
bool isAnyMemberInitializer() const
Definition: DeclCXX.h:2437
bool isBaseInitializer() const
Determine whether this initializer is initializing a base class.
Definition: DeclCXX.h:2429
bool isIndirectMemberInitializer() const
Definition: DeclCXX.h:2441
int64_t getID(const ASTContext &Context) const
Definition: DeclCXX.cpp:2777
const Type * getBaseClass() const
If this is a base class initializer, returns the type of the base class.
Definition: DeclCXX.cpp:2789
FieldDecl * getAnyMember() const
Definition: DeclCXX.h:2503
IndirectFieldDecl * getIndirectMember() const
Definition: DeclCXX.h:2511
bool isBaseVirtual() const
Returns whether the base is virtual or not.
Definition: DeclCXX.h:2483
Represents a delete expression for memory deallocation and destructor calls, e.g.
Definition: ExprCXX.h:2498
bool isArrayForm() const
Definition: ExprCXX.h:2524
SourceLocation getBeginLoc() const
Definition: ExprCXX.h:2548
Expr * getArgument()
Definition: ExprCXX.h:2539
QualType getDestroyedType() const
Retrieve the type being destroyed.
Definition: ExprCXX.cpp:337
Represents a C++ destructor within a class.
Definition: DeclCXX.h:2856
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Definition: ExprCXX.h:2241
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
void getCaptureFields(llvm::DenseMap< const ValueDecl *, FieldDecl * > &Captures, FieldDecl *&ThisCapture) const
For a closure type, retrieve the mapping from captured variables and this to the non-static data memb...
Definition: DeclCXX.cpp:1747
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
Definition: DeclCXX.cpp:2083
Represents a point when we begin processing an inlined call.
Definition: ProgramPoint.h:628
CaseStmt - Represent a case statement.
Definition: Stmt.h:1828
Expr * getLHS()
Definition: Stmt.h:1915
Expr * getRHS()
Definition: Stmt.h:1927
Represents a single point (AST node) in the program that requires attention during construction of an...
unsigned getIndex() const
If a single trigger statement triggers multiple constructors, they are usually being enumerated.
const CXXCtorInitializer * getCXXCtorInitializer() const
The construction site is not necessarily a statement.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2107
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1265
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1519
const Decl * getSingleDecl() const
Definition: Stmt.h:1534
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:434
Kind getKind() const
Definition: DeclBase.h:445
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
Definition: Type.h:6104
This is a meta program point, which should be skipped by all the diagnostic reasoning etc.
Definition: ProgramPoint.h:730
This represents one expression.
Definition: Expr.h:110
const Expr * skipRValueSubobjectAdjustments(SmallVectorImpl< const Expr * > &CommaLHS, SmallVectorImpl< SubobjectAdjustment > &Adjustments) const
Walk outwards from an expression we want to bind a reference to and find the expression whose lifetim...
Definition: Expr.cpp:82
bool isGLValue() const
Definition: Expr.h:280
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3096
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3084
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3092
QualType getType() const
Definition: Expr.h:142
Represents a member of a struct/union/class.
Definition: Decl.h:3033
This represents a GCC inline-assembly statement extension.
Definition: Stmt.h:3286
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
Represents the declaration of a label.
Definition: Decl.h:503
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
const Decl * getDecl() const
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
const LocationContext * getParent() const
It might return null.
const StackFrameContext * getStackFrame() const
virtual bool inTopFrame() const
void printJson(raw_ostream &Out, const char *NL="\n", unsigned int Space=0, bool IsDot=false, std::function< void(const LocationContext *)> printMoreInfoPerContext=[](const LocationContext *) {}) const
Prints out the call stack in json format.
Represents a point when we exit a loop.
Definition: ProgramPoint.h:711
This represents a Microsoft inline-assembly statement extension.
Definition: Stmt.h:3509
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3236
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition: Expr.h:3319
Expr * getBase() const
Definition: Expr.h:3313
This represents a decl that may have a name.
Definition: Decl.h:253
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:319
Represents Objective-C's collection statement.
Definition: StmtObjC.h:23
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition: Expr.h:1223
bool isConsumedExpr(Expr *E) const
Definition: ParentMap.cpp:181
Represents a parameter to a function.
Definition: Decl.h:1725
Represents a program point just after an implicit call event.
Definition: ProgramPoint.h:597
Represents a program point after a store evaluation.
Definition: ProgramPoint.h:426
Represents a program point just before an implicit call event.
Definition: ProgramPoint.h:579
If a crash happens while one of these objects are live, the message is printed out along with the spe...
ProgramPoints can be "tagged" as representing points specific to a given analysis entity.
Definition: ProgramPoint.h:38
const ProgramPointTag * getTag() const
Definition: ProgramPoint.h:173
bool isPurgeKind()
Is this a program point corresponding to purge/removal of dead symbols and bindings.
Definition: ProgramPoint.h:167
void printJson(llvm::raw_ostream &Out, const char *NL="\n") const
const StackFrameContext * getStackFrame() const
Definition: ProgramPoint.h:179
std::optional< T > getAs() const
Convert to the specified ProgramPoint type, returning std::nullopt if this ProgramPoint is not of the...
Definition: ProgramPoint.h:147
const LocationContext * getLocationContext() const
Definition: ProgramPoint.h:175
A (possibly-)qualified type.
Definition: Type.h:929
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
Definition: Type.h:1291
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:996
SplitQualType split() const
Divides a QualType into its unqualified type and a set of local qualifiers.
Definition: Type.h:7958
bool isCForbiddenLValueType() const
Determine whether expressions of the given type are forbidden from being lvalues in C.
Definition: Type.h:8147
std::string getAsString() const
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Definition: Stmt.h:3046
std::string printToString(const SourceManager &SM) const
It represents a stack frame of the call stack (based on CallEvent).
const Stmt * getCallSite() const
const CFGBlock * getCallSiteBlock() const
bool inTopFrame() const override
const Stmt * getStmt() const
Definition: ProgramPoint.h:274
Stmt - This represents one statement.
Definition: Stmt.h:84
@ NoStmtClass
Definition: Stmt.h:87
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:334
const char * getStmtClassName() const
Definition: Stmt.cpp:87
int64_t getID(const ASTContext &Context) const
Definition: Stmt.cpp:370
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:346
SwitchStmt - This represents a 'switch' stmt.
Definition: Stmt.h:2415
bool isAllEnumCasesCovered() const
Returns true if the SwitchStmt is a switch of an enum value and all cases have been explicitly covere...
Definition: Stmt.h:2581
Expr * getCond()
Definition: Stmt.h:2478
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1916
bool isVoidType() const
Definition: Type.h:8516
bool isArrayType() const
Definition: Type.h:8264
bool isReferenceType() const
Definition: Type.h:8210
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:8635
bool isVectorType() const
Definition: Type.h:8304
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8741
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:671
QualType getType() const
Definition: Decl.h:682
Represents a variable declaration or definition.
Definition: Decl.h:886
This class is used for tools that requires cross translation unit capability.
const LangOptions & getLangOpts() const
ASTContext & getASTContext() override
BranchNodeBuilder is responsible for constructing the nodes corresponding to the two branches of the ...
Definition: CoreEngine.h:436
ExplodedNode * generateNode(ProgramStateRef State, bool branch, ExplodedNode *Pred)
Definition: CoreEngine.cpp:676
BugReporter is a utility class for generating PathDiagnostics for analysis.
Definition: BugReporter.h:585
llvm::iterator_range< EQClasses_iterator > equivalenceClasses()
Definition: BugReporter.h:617
Represents an abstract call to a function or method along a particular path.
Definition: CallEvent.h:153
static bool isCallStmt(const Stmt *S)
Returns true if this is a statement is a function or method call of some kind.
Definition: CallEvent.cpp:348
void runCheckersForBind(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SVal location, SVal val, const Stmt *S, ExprEngine &Eng, const ProgramPoint &PP)
Run checkers for binding of a value to a location.
void runCheckersForEndFunction(NodeBuilderContext &BC, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng, const ReturnStmt *RS)
Run checkers on end of function.
void runCheckersForLocation(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SVal location, bool isLoad, const Stmt *NodeEx, const Stmt *BoundEx, ExprEngine &Eng)
Run checkers for load/store of a location.
void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, ExprEngine &Eng)
Run checkers for end of analysis.
void runCheckersForPrintStateJson(raw_ostream &Out, ProgramStateRef State, const char *NL="\n", unsigned int Space=0, bool IsDot=false) const
Run checkers for debug-printing a ProgramState.
void runCheckersForDeadSymbols(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SymbolReaper &SymReaper, const Stmt *S, ExprEngine &Eng, ProgramPoint::Kind K)
Run checkers for dead symbols.
ProgramStateRef runCheckersForRegionChanges(ProgramStateRef state, const InvalidatedSymbols *invalidated, ArrayRef< const MemRegion * > ExplicitRegions, ArrayRef< const MemRegion * > Regions, const LocationContext *LCtx, const CallEvent *Call)
Run checkers for region changes.
void runCheckersForLiveSymbols(ProgramStateRef state, SymbolReaper &SymReaper)
Run checkers for live symbols.
void runCheckersForBeginFunction(ExplodedNodeSet &Dst, const BlockEdge &L, ExplodedNode *Pred, ExprEngine &Eng)
Run checkers on beginning of function.
void runCheckersForPostStmt(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng, bool wasInlined=false)
Run checkers for post-visiting Stmts.
void runCheckersForPreStmt(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng)
Run checkers for pre-visiting Stmts.
void runCheckersForBranchCondition(const Stmt *condition, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng)
Run checkers for branch condition.
ProgramStateRef runCheckersForPointerEscape(ProgramStateRef State, const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind, RegionAndSymbolInvalidationTraits *ITraits)
Run checkers when pointers escape.
ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state, SVal Cond, bool Assumption)
Run checkers for handling assumptions on symbolic values.
virtual ProgramStateRef removeDeadBindings(ProgramStateRef state, SymbolReaper &SymReaper)=0
Scan all symbols referenced by the constraints.
void addAbortedBlock(const ExplodedNode *node, const CFGBlock *block)
Inform the CoreEngine that a basic block was aborted because it could not be completely analyzed.
Definition: CoreEngine.h:168
void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx)
Enqueue a single node created as a result of statement processing.
Definition: CoreEngine.cpp:531
void enqueueEndOfFunction(ExplodedNodeSet &Set, const ReturnStmt *RS)
enqueue the nodes corresponding to the end of function onto the end of path / work list.
Definition: CoreEngine.cpp:630
void enqueue(ExplodedNodeSet &Set)
Enqueue the given set of nodes onto the work list.
Definition: CoreEngine.cpp:619
std::unique_ptr< ExplodedGraph > trim(ArrayRef< const NodeTy * > Nodes, InterExplodedGraphMap *ForwardMap=nullptr, InterExplodedGraphMap *InverseMap=nullptr) const
Creates a trimmed version of the graph that only contains paths leading to the given nodes.
void enableNodeReclamation(unsigned Interval)
Enable tracking of recently allocated nodes for potential reclamation when calling reclaimRecentlyAll...
void reclaimRecentlyAllocatedNodes()
Reclaim "uninteresting" nodes created since the last time this method was called.
ExplodedNode * getNode(const ProgramPoint &L, ProgramStateRef State, bool IsSink=false, bool *IsNew=nullptr)
Retrieve the node associated with a (Location,State) pair, where the 'Location' is a ProgramPoint in ...
roots_iterator roots_begin()
void insert(const ExplodedNodeSet &S)
void Add(ExplodedNode *N)
const ProgramStateRef & getState() const
pred_iterator pred_begin()
bool isTrivial() const
The node is trivial if it has only one successor, only one predecessor, it's predecessor has only one...
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
void addPredecessor(ExplodedNode *V, ExplodedGraph &G)
addPredeccessor - Adds a predecessor to the current node, and in tandem add this node as a successor ...
ExplodedNode * getFirstSucc()
const StackFrameContext * getStackFrame() const
const LocationContext * getLocationContext() const
unsigned succ_size() const
void processEndOfFunction(NodeBuilderContext &BC, ExplodedNode *Pred, const ReturnStmt *RS=nullptr)
Called by CoreEngine.
void VisitBinaryOperator(const BinaryOperator *B, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitBinaryOperator - Transfer function logic for binary operators.
Definition: ExprEngineC.cpp:40
ProgramStateManager & getStateManager()
Definition: ExprEngine.h:414
void VisitArraySubscriptExpr(const ArraySubscriptExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitArraySubscriptExpr - Transfer function for array accesses.
void VisitCommonDeclRefExpr(const Expr *DR, const NamedDecl *D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Transfer function logic for DeclRefExprs and BlockDeclRefExprs.
void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred)
void VisitObjCMessage(const ObjCMessageExpr *ME, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void ProcessTemporaryDtor(const CFGTemporaryDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitGuardedExpr - Transfer function logic for ?, __builtin_choose.
void processBeginOfFunction(NodeBuilderContext &BC, ExplodedNode *Pred, ExplodedNodeSet &Dst, const BlockEdge &L)
Called by CoreEngine.
void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitCast - Transfer function logic for all casts (implicit and explicit).
void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out, const Stmt *ReferenceStmt, const LocationContext *LC, const Stmt *DiagnosticStmt=nullptr, ProgramPoint::Kind K=ProgramPoint::PreStmtPurgeDeadSymbolsKind)
Run the analyzer's garbage collection - remove dead symbols and bindings from the state.
void VisitLogicalExpr(const BinaryOperator *B, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitLogicalExpr - Transfer function logic for '&&', '||'.
void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest, const Stmt *S, bool IsBaseDtor, ExplodedNode *Pred, ExplodedNodeSet &Dst, EvalCallOptions &Options)
void evalEagerlyAssumeBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, const Expr *Ex)
evalEagerlyAssumeBifurcation - Given the nodes in 'Src', eagerly assume concrete boolean values for '...
void VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Transfer function logic for ObjCAtSynchronizedStmts.
void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitReturnStmt - Transfer function logic for return statements.
SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op, SVal LHS, SVal RHS, QualType T)
Definition: ExprEngine.h:606
void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
ProgramStateRef processRegionChange(ProgramStateRef state, const MemRegion *MR, const LocationContext *LCtx)
Definition: ExprEngine.h:403
void VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitLambdaExpr - Transfer function logic for LambdaExprs.
void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred)
void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitObjCForCollectionStmt - Transfer function logic for ObjCForCollectionStmt.
void VisitUnaryOperator(const UnaryOperator *B, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitUnaryOperator - Transfer function logic for unary operators.
ProgramStateRef getInitialState(const LocationContext *InitLoc)
getInitialState - Return the initial state used for the root vertex in the ExplodedGraph.
Definition: ExprEngine.cpp:244
void VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *DR, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Transfer function logic for computing the lvalue of an Objective-C ivar.
static bool hasMoreIteration(ProgramStateRef State, const ObjCForCollectionStmt *O, const LocationContext *LC)
void VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitDeclStmt - Transfer function logic for DeclStmts.
void VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitMSAsmStmt - Transfer function logic for MS inline asm.
static std::optional< SVal > getObjectUnderConstruction(ProgramStateRef State, const ConstructionContextItem &Item, const LocationContext *LC)
By looking at a certain item that may be potentially part of an object's ConstructionContext,...
Definition: ExprEngine.cpp:603
std::string DumpGraph(bool trim=false, StringRef Filename="")
Dump graph to the specified filename.
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.
Definition: ExprEngine.cpp:939
InliningModes
The modes of inlining, which override the default analysis-wide settings.
Definition: ExprEngine.h:129
ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State, ArrayRef< std::pair< SVal, SVal > > LocAndVals, const LocationContext *LCtx, PointerEscapeKind Kind, const CallEvent *Call)
Call PointerEscape callback when a value escapes as a result of bind.
const LocationContext * getRootLocationContext() const
Definition: ExprEngine.h:224
static ProgramStateRef removeIterationState(ProgramStateRef State, const ObjCForCollectionStmt *O, const LocationContext *LC)
ProgramStateRef processAssume(ProgramStateRef state, SVal cond, bool assumption)
evalAssume - Callback function invoked by the ConstraintManager when making assumptions about state v...
Definition: ExprEngine.cpp:667
static std::optional< unsigned > getIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E, const LocationContext *LCtx)
Retreives which element is being constructed in a non-POD type array.
Definition: ExprEngine.cpp:513
void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitBlockExpr - Transfer function logic for BlockExprs.
void ProcessBaseDtor(const CFGBaseDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
static std::pair< const ProgramPointTag *, const ProgramPointTag * > getEagerlyAssumeBifurcationTags()
void VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitCall - Transfer function for function calls.
ASTContext & getContext() const
getContext - Return the ASTContext associated with this analysis.
Definition: ExprEngine.h:196
StoreManager & getStoreManager()
Definition: ExprEngine.h:416
void VisitCXXNewAllocatorCall(const CXXNewExpr *CNE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Create a C++ temporary object for an rvalue.
CFGBlock::ConstCFGElementRef getCFGElementRef() const
Definition: ExprEngine.h:229
void VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitGCCAsmStmt - Transfer function logic for inline asm.
void processCFGBlockEntrance(const BlockEdge &L, NodeBuilderWithSinks &nodeBuilder, ExplodedNode *Pred)
Called by CoreEngine when processing the entrance of a CFGBlock.
void VisitInitListExpr(const InitListExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
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.
Definition: ExprEngine.cpp:673
void ProcessStmt(const Stmt *S, ExplodedNode *Pred)
ExprEngine(cross_tu::CrossTranslationUnitContext &CTU, AnalysisManager &mgr, SetOfConstDecls *VisitedCalleesIn, FunctionSummariesTy *FS, InliningModes HowToInlineIn)
Definition: ExprEngine.cpp:221
void ViewGraph(bool trim=false)
Visualize the ExplodedGraph created by executing the simulation.
static std::optional< unsigned > getPendingArrayDestruction(ProgramStateRef State, const LocationContext *LCtx)
Retreives which element is being destructed in a non-POD type array.
Definition: ExprEngine.cpp:532
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.
static const ProgramPointTag * cleanupNodeTag()
A tag to track convenience transitions, which can be removed at cleanup.
void processCFGElement(const CFGElement E, ExplodedNode *Pred, unsigned StmtIdx, NodeBuilderContext *Ctx)
processCFGElement - Called by CoreEngine.
Definition: ExprEngine.cpp:966
void processStaticInitializer(const DeclStmt *DS, NodeBuilderContext &BuilderCtx, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF)
Called by CoreEngine.
void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof.
void processBranch(const Stmt *Condition, NodeBuilderContext &BuilderCtx, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF, std::optional< unsigned > IterationsCompletedInLoop)
ProcessBranch - Called by CoreEngine.
void ProcessLoopExit(const Stmt *S, ExplodedNode *Pred)
void processSwitch(SwitchNodeBuilder &builder)
ProcessSwitch - Called by CoreEngine.
void processEndWorklist()
Called by CoreEngine when the analysis worklist has terminated.
Definition: ExprEngine.cpp:960
CheckerManager & getCheckerManager() const
Definition: ExprEngine.h:204
void VisitAtomicExpr(const AtomicExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitAtomicExpr - Transfer function for builtin atomic expressions.
void ProcessMemberDtor(const CFGMemberDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitMemberExpr - Transfer function for member expressions.
void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
bool didEagerlyAssumeBifurcateAt(ProgramStateRef State, const Expr *Ex) const
ConstraintManager & getConstraintManager()
Definition: ExprEngine.h:418
void processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE, NodeBuilderContext &BldCtx, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF)
Called by CoreEngine.
void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitOffsetOfExpr(const OffsetOfExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitOffsetOfExpr - Transfer function for offsetof.
void evalLoad(ExplodedNodeSet &Dst, const Expr *NodeEx, const Expr *BoundExpr, ExplodedNode *Pred, ProgramStateRef St, SVal location, const ProgramPointTag *tag=nullptr, QualType LoadTy=QualType())
Simulate a read of the result of Ex.
void removeDeadOnEndOfFunction(NodeBuilderContext &BC, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Remove dead bindings/symbols before exiting a function.
void Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Visit - Transfer function logic for all statements.
AnalysisManager & getAnalysisManager()
Definition: ExprEngine.h:198
void ProcessDeleteDtor(const CFGDeleteDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitCompoundLiteralExpr - Transfer function logic for compound literals.
SValBuilder & getSValBuilder()
Definition: ExprEngine.h:208
void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitArrayInitLoopExpr - Transfer function for array init loop.
void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE, ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val, const ProgramPointTag *tag=nullptr)
evalStore - Handle the semantics of a store via an assignment.
void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE, ExplodedNodeSet &PreVisit, ExplodedNodeSet &Dst)
void processIndirectGoto(IndirectGotoNodeBuilder &builder)
processIndirectGoto - Called by CoreEngine.
const NodeBuilderContext & getBuilderContext()
Definition: ExprEngine.h:217
static std::optional< unsigned > getPendingInitLoop(ProgramStateRef State, const CXXConstructExpr *E, const LocationContext *LCtx)
Retreives the size of the array in the pending ArrayInitLoopExpr.
Definition: ExprEngine.cpp:486
void ProcessNewAllocator(const CXXNewExpr *NE, ExplodedNode *Pred)
void markReachedMaxBlockCount(const Decl *D)
const Expr * getTarget() const
Definition: CoreEngine.h:507
const LocationContext * getLocationContext() const
Definition: CoreEngine.h:511
ProgramStateRef getState() const
Definition: CoreEngine.h:509
ExplodedNode * generateNode(const iterator &I, ProgramStateRef State, bool isSink=false)
Definition: CoreEngine.cpp:691
static bool isLocType(QualType T)
Definition: SVals.h:262
const CXXLifetimeExtendedObjectRegion * getCXXLifetimeExtendedObjectRegion(Expr const *Ex, ValueDecl const *VD, LocationContext const *LC)
Create a CXXLifetimeExtendedObjectRegion for temporaries which are lifetime-extended by local referen...
Definition: MemRegion.cpp:1258
const CXXTempObjectRegion * getCXXTempObjectRegion(Expr const *Ex, LocationContext const *LC)
Definition: MemRegion.cpp:1250
const CXXLifetimeExtendedObjectRegion * getCXXStaticLifetimeExtendedObjectRegion(const Expr *Ex, ValueDecl const *VD)
Create a CXXLifetimeExtendedObjectRegion for temporaries which are lifetime-extended by static refere...
Definition: MemRegion.cpp:1267
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:97
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion * getMemorySpace() const
Definition: MemRegion.cpp:1351
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
Definition: MemRegion.cpp:1377
const CFGBlock * getBlock() const
Return the CFGBlock associated with this builder.
Definition: CoreEngine.h:217
unsigned blockCount() const
Returns the number of times the current basic block has been visited on the exploded graph path.
Definition: CoreEngine.h:224
This node builder keeps track of the generated sink nodes.
Definition: CoreEngine.h:347
ExplodedNode * generateNode(ProgramStateRef State, ExplodedNode *Pred, const ProgramPointTag *Tag=nullptr)
Definition: CoreEngine.h:359
ExplodedNode * generateSink(ProgramStateRef State, ExplodedNode *Pred, const ProgramPointTag *Tag=nullptr)
Definition: CoreEngine.h:366
This is the simplest builder which generates nodes in the ExplodedGraph.
Definition: CoreEngine.h:240
ExplodedNode * generateNode(const ProgramPoint &PP, ProgramStateRef State, ExplodedNode *Pred)
Generates a node in the ExplodedGraph.
Definition: CoreEngine.h:293
void takeNodes(const ExplodedNodeSet &S)
Definition: CoreEngine.h:335
ExplodedNode * generateSink(const ProgramPoint &PP, ProgramStateRef State, ExplodedNode *Pred)
Generates a sink in the ExplodedGraph.
Definition: CoreEngine.h:306
void addNodes(const ExplodedNodeSet &S)
Definition: CoreEngine.h:341
const NodeBuilderContext & getContext()
Definition: CoreEngine.h:332
While alive, includes the current analysis stack in a crash trace.
ProgramStateRef removeDeadBindingsFromEnvironmentAndStore(ProgramStateRef St, const StackFrameContext *LCtx, SymbolReaper &SymReaper)
bool haveEqualStores(ProgramStateRef S1, ProgramStateRef S2) const
Definition: ProgramState.h:610
bool haveEqualEnvironments(ProgramStateRef S1, ProgramStateRef S2) const
Definition: ProgramState.h:606
ProgramStateRef getPersistentStateWithGDM(ProgramStateRef FromState, ProgramStateRef GDMState)
MemRegionManager & getRegionManager()
Definition: ProgramState.h:564
ProgramStateRef getInitialState(const LocationContext *InitLoc)
Information about invalidation for a particular region/symbol.
Definition: MemRegion.h:1629
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
Definition: SValBuilder.cpp:62
DefinedSVal getFunctionPointer(const FunctionDecl *func)
NonLoc makeIntValWithWidth(QualType ptrType, uint64_t integer)
Definition: SValBuilder.h:323
NonLoc makeArrayIndex(uint64_t idx)
Definition: SValBuilder.h:282
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
Definition: SValBuilder.h:288
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Expr *expr, const LocationContext *LCtx, unsigned count)
Create a new symbol with a unique 'name'.
QualType getConditionType() const
Definition: SValBuilder.h:153
loc::MemRegionVal getCXXThis(const CXXMethodDecl *D, const StackFrameContext *SFC)
Return a memory region for the 'this' object reference.
std::optional< SVal > getConstantVal(const Expr *E)
Returns the value of E, if it can be determined in a non-path-sensitive manner.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition: SVals.h:56
bool isUndef() const
Definition: SVals.h:107
bool isUnknownOrUndef() const
Definition: SVals.h:109
bool isConstant() const
Definition: SVals.cpp:246
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 llvm::APSInt * getAsInteger() const
If this SVal is loc::ConcreteInt or nonloc::ConcreteInt, return a pointer to APSInt which is held in ...
Definition: SVals.cpp:112
const MemRegion * getAsRegion() const
Definition: SVals.cpp:120
bool isValid() const
Definition: SVals.h:111
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
This builder class is useful for generating nodes that resulted from visiting a statement.
Definition: CoreEngine.h:384
ExplodedNode * generateNode(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, const ProgramPointTag *tag=nullptr, ProgramPoint::Kind K=ProgramPoint::PostStmtKind)
Definition: CoreEngine.h:413
ExplodedNode * generateSink(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, const ProgramPointTag *tag=nullptr, ProgramPoint::Kind K=ProgramPoint::PostStmtKind)
Definition: CoreEngine.h:423
SVal evalDerivedToBase(SVal Derived, const CastExpr *Cast)
Evaluates a chain of derived-to-base casts through the path specified in Cast.
Definition: Store.cpp:252
virtual SVal getLValueField(const FieldDecl *D, SVal Base)
Definition: Store.h:146
SubRegion - A region that subsets another larger region.
Definition: MemRegion.h:446
ProgramStateRef getState() const
Definition: CoreEngine.h:563
const Expr * getCondition() const
Definition: CoreEngine.h:561
ExplodedNode * generateDefaultCaseNode(ProgramStateRef State, bool isSink=false)
Definition: CoreEngine.cpp:725
ExplodedNode * generateCaseStmtNode(const iterator &I, ProgramStateRef State)
Definition: CoreEngine.cpp:710
const LocationContext * getLocationContext() const
Definition: CoreEngine.h:565
const SwitchStmt * getSwitch() const
Definition: CoreEngine.h:551
Symbolic value.
Definition: SymExpr.h:32
A class responsible for cleaning up unused symbols.
void markLive(SymbolRef sym)
Unconditionally marks a symbol as live.
SymbolicRegion - A special, "non-concrete" region.
Definition: MemRegion.h:780
TypedValueRegion - An abstract class representing regions having a typed value.
Definition: MemRegion.h:535
Represents symbolic expression that isn't a location.
Definition: SVals.h:279
const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl
Matches variable declarations.
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
llvm::DenseSet< const Decl * > SetOfConstDecls
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
@ PSK_DirectEscapeOnCall
The pointer has been passed to a function call directly.
@ PSK_EscapeOnBind
A pointer escapes due to binding its value to a location that the analyzer cannot track.
@ PSK_IndirectEscapeOnCall
The pointer has been passed to a function indirectly.
@ PSK_EscapeOther
The reason for pointer escape is unknown.
DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State, const MemRegion *MR, SValBuilder &SVB, QualType Ty)
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
ProgramStateRef processLoopEnd(const Stmt *LoopStmt, ProgramStateRef State)
Updates the given ProgramState.
ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState, const LocationContext *LCtx, unsigned BlockCount, const Stmt *LoopStmt)
Get the states that result from widening the loop.
llvm::DenseSet< SymbolRef > InvalidatedSymbols
Definition: Store.h:51
bool isUnrolledState(ProgramStateRef State)
Returns if the given State indicates that is inside a completely unrolled loop.
ProgramStateRef updateLoopStack(const Stmt *LoopStmt, ASTContext &ASTCtx, ExplodedNode *Pred, unsigned maxVisitOnPath)
Updates the stack of loops contained by the ProgramState.
bool LE(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1167
The JSON file list parser is used to communicate input to InstallAPI.
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
Definition: CallGraph.h:204
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
StorageDuration
The storage duration for an object (per C++ [basic.stc]).
Definition: Specifiers.h:327
@ SD_Thread
Thread storage duration.
Definition: Specifiers.h:330
@ SD_Static
Static storage duration.
Definition: Specifiers.h:331
@ SD_FullExpression
Full-expression storage duration (for temporaries).
Definition: Specifiers.h:328
@ Result
The result type of a method or function.
const FunctionProtoType * T
@ Class
The "class" keyword introduces the elaborated-type-specifier.
Expr * extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE)
Definition: CFG.cpp:1367
@ CXXThis
Parameter for C++ 'this' argument.
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30
Describes how types, statements, expressions, and declarations should be printed.
Definition: PrettyPrinter.h:57
An adjustment to be made to the temporary created when emitting a reference binding,...
Definition: Expr.h:66
Hints for figuring out of a call should be inlined during evalCall().
Definition: ExprEngine.h:97
bool IsTemporaryCtorOrDtor
This call is a constructor or a destructor of a temporary value.
Definition: ExprEngine.h:107
bool IsArrayCtorOrDtor
This call is a constructor or a destructor for a single element within an array, a part of array cons...
Definition: ExprEngine.h:104
Traits for storing the call processing policy inside GDM.
Definition: ExprEngine.h:1006
static std::string getNodeLabel(const ExplodedNode *N, ExplodedGraph *G)
static bool nodeHasBugReport(const ExplodedNode *N)
static bool traverseHiddenNodes(const ExplodedNode *N, llvm::function_ref< void(const ExplodedNode *)> PreCallback, llvm::function_ref< void(const ExplodedNode *)> PostCallback, llvm::function_ref< bool(const ExplodedNode *)> Stop)
PreCallback: callback before break.
static bool isNodeHidden(const ExplodedNode *N, const ExplodedGraph *G)