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