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
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) {
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()) << " '"
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()) << " '"
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
944 printStateTraitWithLocationContextJson<ObjectsUnderConstruction>(
945 Out, State, LCtx, NL, Space, IsDot, "constructing_objects",
947 printStateTraitWithLocationContextJson<IndexOfElementToConstruct>(
948 Out, State, LCtx, NL, Space, IsDot, "index_of_element",
950 printStateTraitWithLocationContextJson<PendingInitLoop>(
951 Out, State, LCtx, NL, Space, IsDot, "pending_init_loops",
953 printStateTraitWithLocationContextJson<PendingArrayDestruction>(
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;
979 ProcessInitializer(E.castAs<CFGInitializer>(), Pred);
980 return;
983 Pred);
984 return;
990 ProcessImplicitDtor(E.castAs<CFGImplicitDtor>(), Pred);
991 return;
993 ProcessLoopExit(E.castAs<CFGLoopExit>().getLoopStmt(), Pred);
994 return;
999 return;
1000 }
1001}
1002
1004 const Stmt *S,
1005 const ExplodedNode *Pred,
1006 const LocationContext *LC) {
1007 // Are we never purging state values?
1008 if (AMgr.options.AnalysisPurgeOpt == PurgeNone)
1009 return false;
1010
1011 // Is this the beginning of a basic block?
1012 if (Pred->getLocation().getAs<BlockEntrance>())
1013 return true;
1014
1015 // Is this on a non-expression?
1016 if (!isa<Expr>(S))
1017 return true;
1018
1019 // Run before processing a call.
1020 if (CallEvent::isCallStmt(S))
1021 return true;
1022
1023 // Is this an expression that is consumed by another expression? If so,
1024 // postpone cleaning out the state.
1026 return !PM.isConsumedExpr(cast<Expr>(S));
1027}
1028
1030 const Stmt *ReferenceStmt,
1031 const LocationContext *LC,
1032 const Stmt *DiagnosticStmt,
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 // For each node in CheckedSet, generate CleanedNodes that have the
1083 // environment, the store, and the constraints cleaned up but have the
1084 // user-supplied states as the predecessors.
1085 StmtNodeBuilder Bldr(CheckedSet, Out, *currBldrCtx);
1086 for (const auto I : CheckedSet) {
1087 ProgramStateRef CheckerState = I->getState();
1088
1089 // The constraint manager has not been cleaned up yet, so clean up now.
1090 CheckerState =
1091 getConstraintManager().removeDeadBindings(CheckerState, SymReaper);
1092
1093 assert(StateMgr.haveEqualEnvironments(CheckerState, Pred->getState()) &&
1094 "Checkers are not allowed to modify the Environment as a part of "
1095 "checkDeadSymbols processing.");
1096 assert(StateMgr.haveEqualStores(CheckerState, Pred->getState()) &&
1097 "Checkers are not allowed to modify the Store as a part of "
1098 "checkDeadSymbols processing.");
1099
1100 // Create a state based on CleanedState with CheckerState GDM and
1101 // generate a transition to that state.
1102 ProgramStateRef CleanedCheckerSt =
1103 StateMgr.getPersistentStateWithGDM(CleanedState, CheckerState);
1104 Bldr.generateNode(DiagnosticStmt, I, CleanedCheckerSt, cleanupNodeTag(), K);
1105 }
1106}
1107
1109 static SimpleProgramPointTag cleanupTag(TagProviderName, "Clean Node");
1110 return &cleanupTag;
1111}
1112
1113void ExprEngine::ProcessStmt(const Stmt *currStmt, ExplodedNode *Pred) {
1114 // Reclaim any unnecessary nodes in the ExplodedGraph.
1116
1117 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
1118 currStmt->getBeginLoc(),
1119 "Error evaluating statement");
1120
1121 // Remove dead bindings and symbols.
1122 ExplodedNodeSet CleanedStates;
1123 if (shouldRemoveDeadBindings(AMgr, currStmt, Pred,
1124 Pred->getLocationContext())) {
1125 removeDead(Pred, CleanedStates, currStmt,
1126 Pred->getLocationContext());
1127 } else
1128 CleanedStates.Add(Pred);
1129
1130 // Visit the statement.
1131 ExplodedNodeSet Dst;
1132 for (const auto I : CleanedStates) {
1133 ExplodedNodeSet DstI;
1134 // Visit the statement.
1135 Visit(currStmt, I, DstI);
1136 Dst.insert(DstI);
1137 }
1138
1139 // Enqueue the new nodes onto the work list.
1140 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1141}
1142
1144 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
1145 S->getBeginLoc(),
1146 "Error evaluating end of the loop");
1147 ExplodedNodeSet Dst;
1148 Dst.Add(Pred);
1149 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1150 ProgramStateRef NewState = Pred->getState();
1151
1152 if(AMgr.options.ShouldUnrollLoops)
1153 NewState = processLoopEnd(S, NewState);
1154
1155 LoopExit PP(S, Pred->getLocationContext());
1156 Bldr.generateNode(PP, NewState, Pred);
1157 // Enqueue the new nodes onto the work list.
1158 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1159}
1160
1162 ExplodedNode *Pred) {
1163 const CXXCtorInitializer *BMI = CFGInit.getInitializer();
1164 const Expr *Init = BMI->getInit()->IgnoreImplicit();
1165 const LocationContext *LC = Pred->getLocationContext();
1166
1167 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
1168 BMI->getSourceLocation(),
1169 "Error evaluating initializer");
1170
1171 // We don't clean up dead bindings here.
1172 const auto *stackFrame = cast<StackFrameContext>(Pred->getLocationContext());
1173 const auto *decl = cast<CXXConstructorDecl>(stackFrame->getDecl());
1174
1175 ProgramStateRef State = Pred->getState();
1176 SVal thisVal = State->getSVal(svalBuilder.getCXXThis(decl, stackFrame));
1177
1178 ExplodedNodeSet Tmp;
1179 SVal FieldLoc;
1180
1181 // Evaluate the initializer, if necessary
1182 if (BMI->isAnyMemberInitializer()) {
1183 // Constructors build the object directly in the field,
1184 // but non-objects must be copied in from the initializer.
1185 if (getObjectUnderConstruction(State, BMI, LC)) {
1186 // The field was directly constructed, so there is no need to bind.
1187 // But we still need to stop tracking the object under construction.
1188 State = finishObjectConstruction(State, BMI, LC);
1189 NodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
1190 PostStore PS(Init, LC, /*Loc*/ nullptr, /*tag*/ nullptr);
1191 Bldr.generateNode(PS, State, Pred);
1192 } else {
1193 const ValueDecl *Field;
1194 if (BMI->isIndirectMemberInitializer()) {
1195 Field = BMI->getIndirectMember();
1196 FieldLoc = State->getLValue(BMI->getIndirectMember(), thisVal);
1197 } else {
1198 Field = BMI->getMember();
1199 FieldLoc = State->getLValue(BMI->getMember(), thisVal);
1200 }
1201
1202 SVal InitVal;
1203 if (Init->getType()->isArrayType()) {
1204 // Handle arrays of trivial type. We can represent this with a
1205 // primitive load/copy from the base array region.
1206 const ArraySubscriptExpr *ASE;
1207 while ((ASE = dyn_cast<ArraySubscriptExpr>(Init)))
1208 Init = ASE->getBase()->IgnoreImplicit();
1209
1210 InitVal = State->getSVal(Init, stackFrame);
1211
1212 // If we fail to get the value for some reason, use a symbolic value.
1213 if (InitVal.isUnknownOrUndef()) {
1214 SValBuilder &SVB = getSValBuilder();
1215 InitVal =
1216 SVB.conjureSymbolVal(getCFGElementRef(), stackFrame,
1217 Field->getType(), currBldrCtx->blockCount());
1218 }
1219 } else {
1220 InitVal = State->getSVal(BMI->getInit(), stackFrame);
1221 }
1222
1223 PostInitializer PP(BMI, FieldLoc.getAsRegion(), stackFrame);
1224 evalBind(Tmp, Init, Pred, FieldLoc, InitVal, /*isInit=*/true, &PP);
1225 }
1226 } else if (BMI->isBaseInitializer() && isa<InitListExpr>(Init)) {
1227 // When the base class is initialized with an initialization list and the
1228 // base class does not have a ctor, there will not be a CXXConstructExpr to
1229 // initialize the base region. Hence, we need to make the bind for it.
1231 thisVal, QualType(BMI->getBaseClass(), 0), BMI->isBaseVirtual());
1232 SVal InitVal = State->getSVal(Init, stackFrame);
1233 evalBind(Tmp, Init, Pred, BaseLoc, InitVal, /*isInit=*/true);
1234 } else {
1235 assert(BMI->isBaseInitializer() || BMI->isDelegatingInitializer());
1236 Tmp.insert(Pred);
1237 // We already did all the work when visiting the CXXConstructExpr.
1238 }
1239
1240 // Construct PostInitializer nodes whether the state changed or not,
1241 // so that the diagnostics don't get confused.
1242 PostInitializer PP(BMI, FieldLoc.getAsRegion(), stackFrame);
1243 ExplodedNodeSet Dst;
1244 NodeBuilder Bldr(Tmp, Dst, *currBldrCtx);
1245 for (const auto I : Tmp) {
1246 ProgramStateRef State = I->getState();
1247 Bldr.generateNode(PP, State, I);
1248 }
1249
1250 // Enqueue the new nodes onto the work list.
1251 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1252}
1253
1254std::pair<ProgramStateRef, uint64_t>
1255ExprEngine::prepareStateForArrayDestruction(const ProgramStateRef State,
1256 const MemRegion *Region,
1257 const QualType &ElementTy,
1258 const LocationContext *LCtx,
1259 SVal *ElementCountVal) {
1260 assert(Region != nullptr && "Not-null region expected");
1261
1262 QualType Ty = ElementTy.getDesugaredType(getContext());
1263 while (const auto *NTy = dyn_cast<ArrayType>(Ty))
1264 Ty = NTy->getElementType().getDesugaredType(getContext());
1265
1266 auto ElementCount = getDynamicElementCount(State, Region, svalBuilder, Ty);
1267
1268 if (ElementCountVal)
1269 *ElementCountVal = ElementCount;
1270
1271 // Note: the destructors are called in reverse order.
1272 unsigned Idx = 0;
1273 if (auto OptionalIdx = getPendingArrayDestruction(State, LCtx)) {
1274 Idx = *OptionalIdx;
1275 } else {
1276 // The element count is either unknown, or an SVal that's not an integer.
1277 if (!ElementCount.isConstant())
1278 return {State, 0};
1279
1280 Idx = ElementCount.getAsInteger()->getLimitedValue();
1281 }
1282
1283 if (Idx == 0)
1284 return {State, 0};
1285
1286 --Idx;
1287
1288 return {setPendingArrayDestruction(State, LCtx, Idx), Idx};
1289}
1290
1292 ExplodedNode *Pred) {
1293 ExplodedNodeSet Dst;
1294 switch (D.getKind()) {
1296 ProcessAutomaticObjDtor(D.castAs<CFGAutomaticObjDtor>(), Pred, Dst);
1297 break;
1299 ProcessBaseDtor(D.castAs<CFGBaseDtor>(), Pred, Dst);
1300 break;
1302 ProcessMemberDtor(D.castAs<CFGMemberDtor>(), Pred, Dst);
1303 break;
1305 ProcessTemporaryDtor(D.castAs<CFGTemporaryDtor>(), Pred, Dst);
1306 break;
1308 ProcessDeleteDtor(D.castAs<CFGDeleteDtor>(), Pred, Dst);
1309 break;
1310 default:
1311 llvm_unreachable("Unexpected dtor kind.");
1312 }
1313
1314 // Enqueue the new nodes onto the work list.
1315 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1316}
1317
1319 ExplodedNode *Pred) {
1320 ExplodedNodeSet Dst;
1322 AnalyzerOptions &Opts = AMgr.options;
1323 // TODO: We're not evaluating allocators for all cases just yet as
1324 // we're not handling the return value correctly, which causes false
1325 // positives when the alpha.cplusplus.NewDeleteLeaks check is on.
1326 if (Opts.MayInlineCXXAllocator)
1327 VisitCXXNewAllocatorCall(NE, Pred, Dst);
1328 else {
1329 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1330 const LocationContext *LCtx = Pred->getLocationContext();
1331 PostImplicitCall PP(NE->getOperatorNew(), NE->getBeginLoc(), LCtx,
1333 Bldr.generateNode(PP, Pred->getState(), Pred);
1334 }
1335 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1336}
1337
1339 ExplodedNode *Pred,
1340 ExplodedNodeSet &Dst) {
1341 const auto *DtorDecl = Dtor.getDestructorDecl(getContext());
1342 const VarDecl *varDecl = Dtor.getVarDecl();
1343 QualType varType = varDecl->getType();
1344
1345 ProgramStateRef state = Pred->getState();
1346 const LocationContext *LCtx = Pred->getLocationContext();
1347
1348 SVal dest = state->getLValue(varDecl, LCtx);
1349 const MemRegion *Region = dest.castAs<loc::MemRegionVal>().getRegion();
1350
1351 if (varType->isReferenceType()) {
1352 const MemRegion *ValueRegion = state->getSVal(Region).getAsRegion();
1353 if (!ValueRegion) {
1354 // FIXME: This should not happen. The language guarantees a presence
1355 // of a valid initializer here, so the reference shall not be undefined.
1356 // It seems that we're calling destructors over variables that
1357 // were not initialized yet.
1358 return;
1359 }
1360 Region = ValueRegion->getBaseRegion();
1361 varType = cast<TypedValueRegion>(Region)->getValueType();
1362 }
1363
1364 unsigned Idx = 0;
1365 if (isa<ArrayType>(varType)) {
1366 SVal ElementCount;
1367 std::tie(state, Idx) = prepareStateForArrayDestruction(
1368 state, Region, varType, LCtx, &ElementCount);
1369
1370 if (ElementCount.isConstant()) {
1371 uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();
1372 assert(ArrayLength &&
1373 "An automatic dtor for a 0 length array shouldn't be triggered!");
1374
1375 // Still handle this case if we don't have assertions enabled.
1376 if (!ArrayLength) {
1377 static SimpleProgramPointTag PT(
1378 "ExprEngine", "Skipping automatic 0 length array destruction, "
1379 "which shouldn't be in the CFG.");
1380 PostImplicitCall PP(DtorDecl, varDecl->getLocation(), LCtx,
1381 getCFGElementRef(), &PT);
1382 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1383 Bldr.generateSink(PP, Pred->getState(), Pred);
1384 return;
1385 }
1386 }
1387 }
1388
1389 EvalCallOptions CallOpts;
1390 Region = makeElementRegion(state, loc::MemRegionVal(Region), varType,
1391 CallOpts.IsArrayCtorOrDtor, Idx)
1392 .getAsRegion();
1393
1394 NodeBuilder Bldr(Pred, Dst, getBuilderContext());
1395
1396 static SimpleProgramPointTag PT("ExprEngine",
1397 "Prepare for object destruction");
1398 PreImplicitCall PP(DtorDecl, varDecl->getLocation(), LCtx, getCFGElementRef(),
1399 &PT);
1400 Pred = Bldr.generateNode(PP, state, Pred);
1401
1402 if (!Pred)
1403 return;
1404 Bldr.takeNodes(Pred);
1405
1406 VisitCXXDestructor(varType, Region, Dtor.getTriggerStmt(),
1407 /*IsBase=*/false, Pred, Dst, CallOpts);
1408}
1409
1411 ExplodedNode *Pred,
1412 ExplodedNodeSet &Dst) {
1413 ProgramStateRef State = Pred->getState();
1414 const LocationContext *LCtx = Pred->getLocationContext();
1415 const CXXDeleteExpr *DE = Dtor.getDeleteExpr();
1416 const Stmt *Arg = DE->getArgument();
1417 QualType DTy = DE->getDestroyedType();
1418 SVal ArgVal = State->getSVal(Arg, LCtx);
1419
1420 // If the argument to delete is known to be a null value,
1421 // don't run destructor.
1422 if (State->isNull(ArgVal).isConstrainedTrue()) {
1424 const CXXRecordDecl *RD = BTy->getAsCXXRecordDecl();
1425 const CXXDestructorDecl *Dtor = RD->getDestructor();
1426
1427 PostImplicitCall PP(Dtor, DE->getBeginLoc(), LCtx, getCFGElementRef());
1428 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1429 Bldr.generateNode(PP, Pred->getState(), Pred);
1430 return;
1431 }
1432
1433 auto getDtorDecl = [](const QualType &DTy) {
1434 const CXXRecordDecl *RD = DTy->getAsCXXRecordDecl();
1435 return RD->getDestructor();
1436 };
1437
1438 unsigned Idx = 0;
1439 EvalCallOptions CallOpts;
1440 const MemRegion *ArgR = ArgVal.getAsRegion();
1441
1442 if (DE->isArrayForm()) {
1443 CallOpts.IsArrayCtorOrDtor = true;
1444 // Yes, it may even be a multi-dimensional array.
1445 while (const auto *AT = getContext().getAsArrayType(DTy))
1446 DTy = AT->getElementType();
1447
1448 if (ArgR) {
1449 SVal ElementCount;
1450 std::tie(State, Idx) = prepareStateForArrayDestruction(
1451 State, ArgR, DTy, LCtx, &ElementCount);
1452
1453 // If we're about to destruct a 0 length array, don't run any of the
1454 // destructors.
1455 if (ElementCount.isConstant() &&
1456 ElementCount.getAsInteger()->getLimitedValue() == 0) {
1457
1458 static SimpleProgramPointTag PT(
1459 "ExprEngine", "Skipping 0 length array delete destruction");
1460 PostImplicitCall PP(getDtorDecl(DTy), DE->getBeginLoc(), LCtx,
1461 getCFGElementRef(), &PT);
1462 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1463 Bldr.generateNode(PP, Pred->getState(), Pred);
1464 return;
1465 }
1466
1467 ArgR = State->getLValue(DTy, svalBuilder.makeArrayIndex(Idx), ArgVal)
1468 .getAsRegion();
1469 }
1470 }
1471
1472 NodeBuilder Bldr(Pred, Dst, getBuilderContext());
1473 static SimpleProgramPointTag PT("ExprEngine",
1474 "Prepare for object destruction");
1475 PreImplicitCall PP(getDtorDecl(DTy), DE->getBeginLoc(), LCtx,
1476 getCFGElementRef(), &PT);
1477 Pred = Bldr.generateNode(PP, State, Pred);
1478
1479 if (!Pred)
1480 return;
1481 Bldr.takeNodes(Pred);
1482
1483 VisitCXXDestructor(DTy, ArgR, DE, /*IsBase=*/false, Pred, Dst, CallOpts);
1484}
1485
1487 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
1488 const LocationContext *LCtx = Pred->getLocationContext();
1489
1490 const auto *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl());
1491 Loc ThisPtr = getSValBuilder().getCXXThis(CurDtor,
1492 LCtx->getStackFrame());
1493 SVal ThisVal = Pred->getState()->getSVal(ThisPtr);
1494
1495 // Create the base object region.
1496 const CXXBaseSpecifier *Base = D.getBaseSpecifier();
1497 QualType BaseTy = Base->getType();
1498 SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy,
1499 Base->isVirtual());
1500
1501 EvalCallOptions CallOpts;
1502 VisitCXXDestructor(BaseTy, BaseVal.getAsRegion(), CurDtor->getBody(),
1503 /*IsBase=*/true, Pred, Dst, CallOpts);
1504}
1505
1507 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
1508 const auto *DtorDecl = D.getDestructorDecl(getContext());
1509 const FieldDecl *Member = D.getFieldDecl();
1510 QualType T = Member->getType();
1511 ProgramStateRef State = Pred->getState();
1512 const LocationContext *LCtx = Pred->getLocationContext();
1513
1514 const auto *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl());
1515 Loc ThisStorageLoc =
1516 getSValBuilder().getCXXThis(CurDtor, LCtx->getStackFrame());
1517 Loc ThisLoc = State->getSVal(ThisStorageLoc).castAs<Loc>();
1518 SVal FieldVal = State->getLValue(Member, ThisLoc);
1519
1520 unsigned Idx = 0;
1521 if (isa<ArrayType>(T)) {
1522 SVal ElementCount;
1523 std::tie(State, Idx) = prepareStateForArrayDestruction(
1524 State, FieldVal.getAsRegion(), T, LCtx, &ElementCount);
1525
1526 if (ElementCount.isConstant()) {
1527 uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();
1528 assert(ArrayLength &&
1529 "A member dtor for a 0 length array shouldn't be triggered!");
1530
1531 // Still handle this case if we don't have assertions enabled.
1532 if (!ArrayLength) {
1533 static SimpleProgramPointTag PT(
1534 "ExprEngine", "Skipping member 0 length array destruction, which "
1535 "shouldn't be in the CFG.");
1536 PostImplicitCall PP(DtorDecl, Member->getLocation(), LCtx,
1537 getCFGElementRef(), &PT);
1538 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1539 Bldr.generateSink(PP, Pred->getState(), Pred);
1540 return;
1541 }
1542 }
1543 }
1544
1545 EvalCallOptions CallOpts;
1546 FieldVal =
1547 makeElementRegion(State, FieldVal, T, CallOpts.IsArrayCtorOrDtor, Idx);
1548
1549 NodeBuilder Bldr(Pred, Dst, getBuilderContext());
1550
1551 static SimpleProgramPointTag PT("ExprEngine",
1552 "Prepare for object destruction");
1553 PreImplicitCall PP(DtorDecl, Member->getLocation(), LCtx, getCFGElementRef(),
1554 &PT);
1555 Pred = Bldr.generateNode(PP, State, Pred);
1556
1557 if (!Pred)
1558 return;
1559 Bldr.takeNodes(Pred);
1560
1561 VisitCXXDestructor(T, FieldVal.getAsRegion(), CurDtor->getBody(),
1562 /*IsBase=*/false, Pred, Dst, CallOpts);
1563}
1564
1566 ExplodedNode *Pred,
1567 ExplodedNodeSet &Dst) {
1568 const CXXBindTemporaryExpr *BTE = D.getBindTemporaryExpr();
1569 ProgramStateRef State = Pred->getState();
1570 const LocationContext *LC = Pred->getLocationContext();
1571 const MemRegion *MR = nullptr;
1572
1573 if (std::optional<SVal> V = getObjectUnderConstruction(
1574 State, D.getBindTemporaryExpr(), Pred->getLocationContext())) {
1575 // FIXME: Currently we insert temporary destructors for default parameters,
1576 // but we don't insert the constructors, so the entry in
1577 // ObjectsUnderConstruction may be missing.
1578 State = finishObjectConstruction(State, D.getBindTemporaryExpr(),
1579 Pred->getLocationContext());
1580 MR = V->getAsRegion();
1581 }
1582
1583 // If copy elision has occurred, and the constructor corresponding to the
1584 // destructor was elided, we need to skip the destructor as well.
1585 if (isDestructorElided(State, BTE, LC)) {
1586 State = cleanupElidedDestructor(State, BTE, LC);
1587 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1588 PostImplicitCall PP(D.getDestructorDecl(getContext()),
1589 D.getBindTemporaryExpr()->getBeginLoc(),
1591 Bldr.generateNode(PP, State, Pred);
1592 return;
1593 }
1594
1595 ExplodedNodeSet CleanDtorState;
1596 StmtNodeBuilder StmtBldr(Pred, CleanDtorState, *currBldrCtx);
1597 StmtBldr.generateNode(D.getBindTemporaryExpr(), Pred, State);
1598
1599 QualType T = D.getBindTemporaryExpr()->getSubExpr()->getType();
1600 // FIXME: Currently CleanDtorState can be empty here due to temporaries being
1601 // bound to default parameters.
1602 assert(CleanDtorState.size() <= 1);
1603 ExplodedNode *CleanPred =
1604 CleanDtorState.empty() ? Pred : *CleanDtorState.begin();
1605
1606 EvalCallOptions CallOpts;
1607 CallOpts.IsTemporaryCtorOrDtor = true;
1608 if (!MR) {
1609 // FIXME: If we have no MR, we still need to unwrap the array to avoid
1610 // destroying the whole array at once.
1611 //
1612 // For this case there is no universal solution as there is no way to
1613 // directly create an array of temporary objects. There are some expressions
1614 // however which can create temporary objects and have an array type.
1615 //
1616 // E.g.: std::initializer_list<S>{S(), S()};
1617 //
1618 // The expression above has a type of 'const struct S[2]' but it's a single
1619 // 'std::initializer_list<>'. The destructors of the 2 temporary 'S()'
1620 // objects will be called anyway, because they are 2 separate objects in 2
1621 // separate clusters, i.e.: not an array.
1622 //
1623 // Now the 'std::initializer_list<>' is not an array either even though it
1624 // has the type of an array. The point is, we only want to invoke the
1625 // destructor for the initializer list once not twice or so.
1626 while (const ArrayType *AT = getContext().getAsArrayType(T)) {
1627 T = AT->getElementType();
1628
1629 // FIXME: Enable this flag once we handle this case properly.
1630 // CallOpts.IsArrayCtorOrDtor = true;
1631 }
1632 } else {
1633 // FIXME: We'd eventually need to makeElementRegion() trick here,
1634 // but for now we don't have the respective construction contexts,
1635 // so MR would always be null in this case. Do nothing for now.
1636 }
1637 VisitCXXDestructor(T, MR, D.getBindTemporaryExpr(),
1638 /*IsBase=*/false, CleanPred, Dst, CallOpts);
1639}
1640
1642 NodeBuilderContext &BldCtx,
1643 ExplodedNode *Pred,
1644 ExplodedNodeSet &Dst,
1645 const CFGBlock *DstT,
1646 const CFGBlock *DstF) {
1647 BranchNodeBuilder TempDtorBuilder(Pred, Dst, BldCtx, DstT, DstF);
1648 ProgramStateRef State = Pred->getState();
1649 const LocationContext *LC = Pred->getLocationContext();
1650 if (getObjectUnderConstruction(State, BTE, LC)) {
1651 TempDtorBuilder.generateNode(State, true, Pred);
1652 } else {
1653 TempDtorBuilder.generateNode(State, false, Pred);
1654 }
1655}
1656
1658 ExplodedNodeSet &PreVisit,
1659 ExplodedNodeSet &Dst) {
1660 // This is a fallback solution in case we didn't have a construction
1661 // context when we were constructing the temporary. Otherwise the map should
1662 // have been populated there.
1663 if (!getAnalysisManager().options.ShouldIncludeTemporaryDtorsInCFG) {
1664 // In case we don't have temporary destructors in the CFG, do not mark
1665 // the initialization - we would otherwise never clean it up.
1666 Dst = PreVisit;
1667 return;
1668 }
1669 StmtNodeBuilder StmtBldr(PreVisit, Dst, *currBldrCtx);
1670 for (ExplodedNode *Node : PreVisit) {
1671 ProgramStateRef State = Node->getState();
1672 const LocationContext *LC = Node->getLocationContext();
1673 if (!getObjectUnderConstruction(State, BTE, LC)) {
1674 // FIXME: Currently the state might also already contain the marker due to
1675 // incorrect handling of temporaries bound to default parameters; for
1676 // those, we currently skip the CXXBindTemporaryExpr but rely on adding
1677 // temporary destructor nodes.
1678 State = addObjectUnderConstruction(State, BTE, LC, UnknownVal());
1679 }
1680 StmtBldr.generateNode(BTE, Node, State);
1681 }
1682}
1683
1685 ArrayRef<SVal> Vs,
1687 const CallEvent *Call) const {
1688 class CollectReachableSymbolsCallback final : public SymbolVisitor {
1689 InvalidatedSymbols &Symbols;
1690
1691 public:
1692 explicit CollectReachableSymbolsCallback(InvalidatedSymbols &Symbols)
1693 : Symbols(Symbols) {}
1694
1695 const InvalidatedSymbols &getSymbols() const { return Symbols; }
1696
1697 bool VisitSymbol(SymbolRef Sym) override {
1698 Symbols.insert(Sym);
1699 return true;
1700 }
1701 };
1702 InvalidatedSymbols Symbols;
1703 CollectReachableSymbolsCallback CallBack(Symbols);
1704 for (SVal V : Vs)
1705 State->scanReachableSymbols(V, CallBack);
1706
1708 State, CallBack.getSymbols(), Call, K, nullptr);
1709}
1710
1712 ExplodedNodeSet &DstTop) {
1713 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
1714 S->getBeginLoc(), "Error evaluating statement");
1715 ExplodedNodeSet Dst;
1716 StmtNodeBuilder Bldr(Pred, DstTop, *currBldrCtx);
1717
1718 assert(!isa<Expr>(S) || S == cast<Expr>(S)->IgnoreParens());
1719
1720 switch (S->getStmtClass()) {
1721 // C++, OpenMP and ARC stuff we don't support yet.
1722 case Stmt::CXXDependentScopeMemberExprClass:
1723 case Stmt::CXXTryStmtClass:
1724 case Stmt::CXXTypeidExprClass:
1725 case Stmt::CXXUuidofExprClass:
1726 case Stmt::CXXFoldExprClass:
1727 case Stmt::MSPropertyRefExprClass:
1728 case Stmt::MSPropertySubscriptExprClass:
1729 case Stmt::CXXUnresolvedConstructExprClass:
1730 case Stmt::DependentScopeDeclRefExprClass:
1731 case Stmt::ArrayTypeTraitExprClass:
1732 case Stmt::ExpressionTraitExprClass:
1733 case Stmt::UnresolvedLookupExprClass:
1734 case Stmt::UnresolvedMemberExprClass:
1735 case Stmt::RecoveryExprClass:
1736 case Stmt::CXXNoexceptExprClass:
1737 case Stmt::PackExpansionExprClass:
1738 case Stmt::PackIndexingExprClass:
1739 case Stmt::SubstNonTypeTemplateParmPackExprClass:
1740 case Stmt::FunctionParmPackExprClass:
1741 case Stmt::CoroutineBodyStmtClass:
1742 case Stmt::CoawaitExprClass:
1743 case Stmt::DependentCoawaitExprClass:
1744 case Stmt::CoreturnStmtClass:
1745 case Stmt::CoyieldExprClass:
1746 case Stmt::SEHTryStmtClass:
1747 case Stmt::SEHExceptStmtClass:
1748 case Stmt::SEHLeaveStmtClass:
1749 case Stmt::SEHFinallyStmtClass:
1750 case Stmt::OMPCanonicalLoopClass:
1751 case Stmt::OMPParallelDirectiveClass:
1752 case Stmt::OMPSimdDirectiveClass:
1753 case Stmt::OMPForDirectiveClass:
1754 case Stmt::OMPForSimdDirectiveClass:
1755 case Stmt::OMPSectionsDirectiveClass:
1756 case Stmt::OMPSectionDirectiveClass:
1757 case Stmt::OMPScopeDirectiveClass:
1758 case Stmt::OMPSingleDirectiveClass:
1759 case Stmt::OMPMasterDirectiveClass:
1760 case Stmt::OMPCriticalDirectiveClass:
1761 case Stmt::OMPParallelForDirectiveClass:
1762 case Stmt::OMPParallelForSimdDirectiveClass:
1763 case Stmt::OMPParallelSectionsDirectiveClass:
1764 case Stmt::OMPParallelMasterDirectiveClass:
1765 case Stmt::OMPParallelMaskedDirectiveClass:
1766 case Stmt::OMPTaskDirectiveClass:
1767 case Stmt::OMPTaskyieldDirectiveClass:
1768 case Stmt::OMPBarrierDirectiveClass:
1769 case Stmt::OMPTaskwaitDirectiveClass:
1770 case Stmt::OMPErrorDirectiveClass:
1771 case Stmt::OMPTaskgroupDirectiveClass:
1772 case Stmt::OMPFlushDirectiveClass:
1773 case Stmt::OMPDepobjDirectiveClass:
1774 case Stmt::OMPScanDirectiveClass:
1775 case Stmt::OMPOrderedDirectiveClass:
1776 case Stmt::OMPAtomicDirectiveClass:
1777 case Stmt::OMPAssumeDirectiveClass:
1778 case Stmt::OMPTargetDirectiveClass:
1779 case Stmt::OMPTargetDataDirectiveClass:
1780 case Stmt::OMPTargetEnterDataDirectiveClass:
1781 case Stmt::OMPTargetExitDataDirectiveClass:
1782 case Stmt::OMPTargetParallelDirectiveClass:
1783 case Stmt::OMPTargetParallelForDirectiveClass:
1784 case Stmt::OMPTargetUpdateDirectiveClass:
1785 case Stmt::OMPTeamsDirectiveClass:
1786 case Stmt::OMPCancellationPointDirectiveClass:
1787 case Stmt::OMPCancelDirectiveClass:
1788 case Stmt::OMPTaskLoopDirectiveClass:
1789 case Stmt::OMPTaskLoopSimdDirectiveClass:
1790 case Stmt::OMPMasterTaskLoopDirectiveClass:
1791 case Stmt::OMPMaskedTaskLoopDirectiveClass:
1792 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
1793 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
1794 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
1795 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
1796 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
1797 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
1798 case Stmt::OMPDistributeDirectiveClass:
1799 case Stmt::OMPDistributeParallelForDirectiveClass:
1800 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
1801 case Stmt::OMPDistributeSimdDirectiveClass:
1802 case Stmt::OMPTargetParallelForSimdDirectiveClass:
1803 case Stmt::OMPTargetSimdDirectiveClass:
1804 case Stmt::OMPTeamsDistributeDirectiveClass:
1805 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
1806 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
1807 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
1808 case Stmt::OMPTargetTeamsDirectiveClass:
1809 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
1810 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
1811 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
1812 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
1813 case Stmt::OMPReverseDirectiveClass:
1814 case Stmt::OMPStripeDirectiveClass:
1815 case Stmt::OMPTileDirectiveClass:
1816 case Stmt::OMPInterchangeDirectiveClass:
1817 case Stmt::OMPInteropDirectiveClass:
1818 case Stmt::OMPDispatchDirectiveClass:
1819 case Stmt::OMPMaskedDirectiveClass:
1820 case Stmt::OMPGenericLoopDirectiveClass:
1821 case Stmt::OMPTeamsGenericLoopDirectiveClass:
1822 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
1823 case Stmt::OMPParallelGenericLoopDirectiveClass:
1824 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
1825 case Stmt::CapturedStmtClass:
1826 case Stmt::SYCLKernelCallStmtClass:
1827 case Stmt::OpenACCComputeConstructClass:
1828 case Stmt::OpenACCLoopConstructClass:
1829 case Stmt::OpenACCCombinedConstructClass:
1830 case Stmt::OpenACCDataConstructClass:
1831 case Stmt::OpenACCEnterDataConstructClass:
1832 case Stmt::OpenACCExitDataConstructClass:
1833 case Stmt::OpenACCHostDataConstructClass:
1834 case Stmt::OpenACCWaitConstructClass:
1835 case Stmt::OpenACCCacheConstructClass:
1836 case Stmt::OpenACCInitConstructClass:
1837 case Stmt::OpenACCShutdownConstructClass:
1838 case Stmt::OpenACCSetConstructClass:
1839 case Stmt::OpenACCUpdateConstructClass:
1840 case Stmt::OpenACCAtomicConstructClass:
1841 case Stmt::OMPUnrollDirectiveClass:
1842 case Stmt::OMPMetaDirectiveClass:
1843 case Stmt::HLSLOutArgExprClass: {
1844 const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
1845 Engine.addAbortedBlock(node, currBldrCtx->getBlock());
1846 break;
1847 }
1848
1849 case Stmt::ParenExprClass:
1850 llvm_unreachable("ParenExprs already handled.");
1851 case Stmt::GenericSelectionExprClass:
1852 llvm_unreachable("GenericSelectionExprs already handled.");
1853 // Cases that should never be evaluated simply because they shouldn't
1854 // appear in the CFG.
1855 case Stmt::BreakStmtClass:
1856 case Stmt::CaseStmtClass:
1857 case Stmt::CompoundStmtClass:
1858 case Stmt::ContinueStmtClass:
1859 case Stmt::CXXForRangeStmtClass:
1860 case Stmt::DefaultStmtClass:
1861 case Stmt::DoStmtClass:
1862 case Stmt::ForStmtClass:
1863 case Stmt::GotoStmtClass:
1864 case Stmt::IfStmtClass:
1865 case Stmt::IndirectGotoStmtClass:
1866 case Stmt::LabelStmtClass:
1867 case Stmt::NoStmtClass:
1868 case Stmt::NullStmtClass:
1869 case Stmt::SwitchStmtClass:
1870 case Stmt::WhileStmtClass:
1871 case Expr::MSDependentExistsStmtClass:
1872 llvm_unreachable("Stmt should not be in analyzer evaluation loop");
1873 case Stmt::ImplicitValueInitExprClass:
1874 // These nodes are shared in the CFG and would case caching out.
1875 // Moreover, no additional evaluation required for them, the
1876 // analyzer can reconstruct these values from the AST.
1877 llvm_unreachable("Should be pruned from CFG");
1878
1879 case Stmt::ObjCSubscriptRefExprClass:
1880 case Stmt::ObjCPropertyRefExprClass:
1881 llvm_unreachable("These are handled by PseudoObjectExpr");
1882
1883 case Stmt::GNUNullExprClass: {
1884 // GNU __null is a pointer-width integer, not an actual pointer.
1885 ProgramStateRef state = Pred->getState();
1886 state = state->BindExpr(
1887 S, Pred->getLocationContext(),
1888 svalBuilder.makeIntValWithWidth(getContext().VoidPtrTy, 0));
1889 Bldr.generateNode(S, Pred, state);
1890 break;
1891 }
1892
1893 case Stmt::ObjCAtSynchronizedStmtClass:
1894 Bldr.takeNodes(Pred);
1895 VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S), Pred, Dst);
1896 Bldr.addNodes(Dst);
1897 break;
1898
1899 case Expr::ConstantExprClass:
1900 case Stmt::ExprWithCleanupsClass:
1901 // Handled due to fully linearised CFG.
1902 break;
1903
1904 case Stmt::CXXBindTemporaryExprClass: {
1905 Bldr.takeNodes(Pred);
1906 ExplodedNodeSet PreVisit;
1907 getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
1908 ExplodedNodeSet Next;
1909 VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), PreVisit, Next);
1910 getCheckerManager().runCheckersForPostStmt(Dst, Next, S, *this);
1911 Bldr.addNodes(Dst);
1912 break;
1913 }
1914
1915 case Stmt::ArrayInitLoopExprClass:
1916 Bldr.takeNodes(Pred);
1917 VisitArrayInitLoopExpr(cast<ArrayInitLoopExpr>(S), Pred, Dst);
1918 Bldr.addNodes(Dst);
1919 break;
1920 // Cases not handled yet; but will handle some day.
1921 case Stmt::DesignatedInitExprClass:
1922 case Stmt::DesignatedInitUpdateExprClass:
1923 case Stmt::ArrayInitIndexExprClass:
1924 case Stmt::ExtVectorElementExprClass:
1925 case Stmt::ImaginaryLiteralClass:
1926 case Stmt::ObjCAtCatchStmtClass:
1927 case Stmt::ObjCAtFinallyStmtClass:
1928 case Stmt::ObjCAtTryStmtClass:
1929 case Stmt::ObjCAutoreleasePoolStmtClass:
1930 case Stmt::ObjCEncodeExprClass:
1931 case Stmt::ObjCIsaExprClass:
1932 case Stmt::ObjCProtocolExprClass:
1933 case Stmt::ObjCSelectorExprClass:
1934 case Stmt::ParenListExprClass:
1935 case Stmt::ShuffleVectorExprClass:
1936 case Stmt::ConvertVectorExprClass:
1937 case Stmt::VAArgExprClass:
1938 case Stmt::CUDAKernelCallExprClass:
1939 case Stmt::OpaqueValueExprClass:
1940 case Stmt::AsTypeExprClass:
1941 case Stmt::ConceptSpecializationExprClass:
1942 case Stmt::CXXRewrittenBinaryOperatorClass:
1943 case Stmt::RequiresExprClass:
1944 case Stmt::EmbedExprClass:
1945 // Fall through.
1946
1947 // Cases we intentionally don't evaluate, since they don't need
1948 // to be explicitly evaluated.
1949 case Stmt::PredefinedExprClass:
1950 case Stmt::AddrLabelExprClass:
1951 case Stmt::IntegerLiteralClass:
1952 case Stmt::FixedPointLiteralClass:
1953 case Stmt::CharacterLiteralClass:
1954 case Stmt::CXXScalarValueInitExprClass:
1955 case Stmt::CXXBoolLiteralExprClass:
1956 case Stmt::ObjCBoolLiteralExprClass:
1957 case Stmt::ObjCAvailabilityCheckExprClass:
1958 case Stmt::FloatingLiteralClass:
1959 case Stmt::NoInitExprClass:
1960 case Stmt::SizeOfPackExprClass:
1961 case Stmt::StringLiteralClass:
1962 case Stmt::SourceLocExprClass:
1963 case Stmt::ObjCStringLiteralClass:
1964 case Stmt::CXXPseudoDestructorExprClass:
1965 case Stmt::SubstNonTypeTemplateParmExprClass:
1966 case Stmt::CXXNullPtrLiteralExprClass:
1967 case Stmt::ArraySectionExprClass:
1968 case Stmt::OMPArrayShapingExprClass:
1969 case Stmt::OMPIteratorExprClass:
1970 case Stmt::SYCLUniqueStableNameExprClass:
1971 case Stmt::OpenACCAsteriskSizeExprClass:
1972 case Stmt::TypeTraitExprClass: {
1973 Bldr.takeNodes(Pred);
1974 ExplodedNodeSet preVisit;
1975 getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
1976 getCheckerManager().runCheckersForPostStmt(Dst, preVisit, S, *this);
1977 Bldr.addNodes(Dst);
1978 break;
1979 }
1980
1981 case Stmt::AttributedStmtClass: {
1982 Bldr.takeNodes(Pred);
1983 VisitAttributedStmt(cast<AttributedStmt>(S), Pred, Dst);
1984 Bldr.addNodes(Dst);
1985 break;
1986 }
1987
1988 case Stmt::CXXDefaultArgExprClass:
1989 case Stmt::CXXDefaultInitExprClass: {
1990 Bldr.takeNodes(Pred);
1991 ExplodedNodeSet PreVisit;
1992 getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
1993
1994 ExplodedNodeSet Tmp;
1995 StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
1996
1997 const Expr *ArgE;
1998 if (const auto *DefE = dyn_cast<CXXDefaultArgExpr>(S))
1999 ArgE = DefE->getExpr();
2000 else if (const auto *DefE = dyn_cast<CXXDefaultInitExpr>(S))
2001 ArgE = DefE->getExpr();
2002 else
2003 llvm_unreachable("unknown constant wrapper kind");
2004
2005 bool IsTemporary = false;
2006 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(ArgE)) {
2007 ArgE = MTE->getSubExpr();
2008 IsTemporary = true;
2009 }
2010
2011 std::optional<SVal> ConstantVal = svalBuilder.getConstantVal(ArgE);
2012 if (!ConstantVal)
2013 ConstantVal = UnknownVal();
2014
2015 const LocationContext *LCtx = Pred->getLocationContext();
2016 for (const auto I : PreVisit) {
2017 ProgramStateRef State = I->getState();
2018 State = State->BindExpr(S, LCtx, *ConstantVal);
2019 if (IsTemporary)
2020 State = createTemporaryRegionIfNeeded(State, LCtx,
2021 cast<Expr>(S),
2022 cast<Expr>(S));
2023 Bldr2.generateNode(S, I, State);
2024 }
2025
2026 getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
2027 Bldr.addNodes(Dst);
2028 break;
2029 }
2030
2031 // Cases we evaluate as opaque expressions, conjuring a symbol.
2032 case Stmt::CXXStdInitializerListExprClass:
2033 case Expr::ObjCArrayLiteralClass:
2034 case Expr::ObjCDictionaryLiteralClass:
2035 case Expr::ObjCBoxedExprClass: {
2036 Bldr.takeNodes(Pred);
2037
2038 ExplodedNodeSet preVisit;
2039 getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
2040
2041 ExplodedNodeSet Tmp;
2042 StmtNodeBuilder Bldr2(preVisit, Tmp, *currBldrCtx);
2043
2044 const auto *Ex = cast<Expr>(S);
2045 QualType resultType = Ex->getType();
2046
2047 for (const auto N : preVisit) {
2048 const LocationContext *LCtx = N->getLocationContext();
2049 SVal result = svalBuilder.conjureSymbolVal(
2050 /*symbolTag=*/nullptr, getCFGElementRef(), LCtx, resultType,
2051 currBldrCtx->blockCount());
2052 ProgramStateRef State = N->getState()->BindExpr(Ex, LCtx, result);
2053
2054 // Escape pointers passed into the list, unless it's an ObjC boxed
2055 // expression which is not a boxable C structure.
2056 if (!(isa<ObjCBoxedExpr>(Ex) &&
2057 !cast<ObjCBoxedExpr>(Ex)->getSubExpr()
2058 ->getType()->isRecordType()))
2059 for (auto Child : Ex->children()) {
2060 assert(Child);
2061 SVal Val = State->getSVal(Child, LCtx);
2062 State = escapeValues(State, Val, PSK_EscapeOther);
2063 }
2064
2065 Bldr2.generateNode(S, N, State);
2066 }
2067
2068 getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
2069 Bldr.addNodes(Dst);
2070 break;
2071 }
2072
2073 case Stmt::ArraySubscriptExprClass:
2074 Bldr.takeNodes(Pred);
2075 VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Pred, Dst);
2076 Bldr.addNodes(Dst);
2077 break;
2078
2079 case Stmt::MatrixSubscriptExprClass:
2080 llvm_unreachable("Support for MatrixSubscriptExpr is not implemented.");
2081 break;
2082
2083 case Stmt::GCCAsmStmtClass: {
2084 Bldr.takeNodes(Pred);
2085 ExplodedNodeSet PreVisit;
2086 getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
2088 for (ExplodedNode *const N : PreVisit)
2089 VisitGCCAsmStmt(cast<GCCAsmStmt>(S), N, PostVisit);
2091 Bldr.addNodes(Dst);
2092 break;
2093 }
2094
2095 case Stmt::MSAsmStmtClass:
2096 Bldr.takeNodes(Pred);
2097 VisitMSAsmStmt(cast<MSAsmStmt>(S), Pred, Dst);
2098 Bldr.addNodes(Dst);
2099 break;
2100
2101 case Stmt::BlockExprClass:
2102 Bldr.takeNodes(Pred);
2103 VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst);
2104 Bldr.addNodes(Dst);
2105 break;
2106
2107 case Stmt::LambdaExprClass:
2108 if (AMgr.options.ShouldInlineLambdas) {
2109 Bldr.takeNodes(Pred);
2110 VisitLambdaExpr(cast<LambdaExpr>(S), Pred, Dst);
2111 Bldr.addNodes(Dst);
2112 } else {
2113 const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
2114 Engine.addAbortedBlock(node, currBldrCtx->getBlock());
2115 }
2116 break;
2117
2118 case Stmt::BinaryOperatorClass: {
2119 const auto *B = cast<BinaryOperator>(S);
2120 if (B->isLogicalOp()) {
2121 Bldr.takeNodes(Pred);
2122 VisitLogicalExpr(B, Pred, Dst);
2123 Bldr.addNodes(Dst);
2124 break;
2125 }
2126 else if (B->getOpcode() == BO_Comma) {
2127 ProgramStateRef state = Pred->getState();
2128 Bldr.generateNode(B, Pred,
2129 state->BindExpr(B, Pred->getLocationContext(),
2130 state->getSVal(B->getRHS(),
2131 Pred->getLocationContext())));
2132 break;
2133 }
2134
2135 Bldr.takeNodes(Pred);
2136
2137 if (AMgr.options.ShouldEagerlyAssume &&
2138 (B->isRelationalOp() || B->isEqualityOp())) {
2139 ExplodedNodeSet Tmp;
2140 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);
2141 evalEagerlyAssumeBifurcation(Dst, Tmp, cast<Expr>(S));
2142 }
2143 else
2144 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
2145
2146 Bldr.addNodes(Dst);
2147 break;
2148 }
2149
2150 case Stmt::CXXOperatorCallExprClass: {
2151 const auto *OCE = cast<CXXOperatorCallExpr>(S);
2152
2153 // For instance method operators, make sure the 'this' argument has a
2154 // valid region.
2155 const Decl *Callee = OCE->getCalleeDecl();
2156 if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(Callee)) {
2157 if (MD->isImplicitObjectMemberFunction()) {
2158 ProgramStateRef State = Pred->getState();
2159 const LocationContext *LCtx = Pred->getLocationContext();
2160 ProgramStateRef NewState =
2161 createTemporaryRegionIfNeeded(State, LCtx, OCE->getArg(0));
2162 if (NewState != State) {
2163 Pred = Bldr.generateNode(OCE, Pred, NewState, /*tag=*/nullptr,
2165 // Did we cache out?
2166 if (!Pred)
2167 break;
2168 }
2169 }
2170 }
2171 [[fallthrough]];
2172 }
2173
2174 case Stmt::CallExprClass:
2175 case Stmt::CXXMemberCallExprClass:
2176 case Stmt::UserDefinedLiteralClass:
2177 Bldr.takeNodes(Pred);
2178 VisitCallExpr(cast<CallExpr>(S), Pred, Dst);
2179 Bldr.addNodes(Dst);
2180 break;
2181
2182 case Stmt::CXXCatchStmtClass:
2183 Bldr.takeNodes(Pred);
2184 VisitCXXCatchStmt(cast<CXXCatchStmt>(S), Pred, Dst);
2185 Bldr.addNodes(Dst);
2186 break;
2187
2188 case Stmt::CXXTemporaryObjectExprClass:
2189 case Stmt::CXXConstructExprClass:
2190 Bldr.takeNodes(Pred);
2191 VisitCXXConstructExpr(cast<CXXConstructExpr>(S), Pred, Dst);
2192 Bldr.addNodes(Dst);
2193 break;
2194
2195 case Stmt::CXXInheritedCtorInitExprClass:
2196 Bldr.takeNodes(Pred);
2197 VisitCXXInheritedCtorInitExpr(cast<CXXInheritedCtorInitExpr>(S), Pred,
2198 Dst);
2199 Bldr.addNodes(Dst);
2200 break;
2201
2202 case Stmt::CXXNewExprClass: {
2203 Bldr.takeNodes(Pred);
2204
2205 ExplodedNodeSet PreVisit;
2206 getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
2207
2209 for (const auto i : PreVisit)
2210 VisitCXXNewExpr(cast<CXXNewExpr>(S), i, PostVisit);
2211
2213 Bldr.addNodes(Dst);
2214 break;
2215 }
2216
2217 case Stmt::CXXDeleteExprClass: {
2218 Bldr.takeNodes(Pred);
2219 ExplodedNodeSet PreVisit;
2220 const auto *CDE = cast<CXXDeleteExpr>(S);
2221 getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
2223 getCheckerManager().runCheckersForPostStmt(PostVisit, PreVisit, S, *this);
2224
2225 for (const auto i : PostVisit)
2226 VisitCXXDeleteExpr(CDE, i, Dst);
2227
2228 Bldr.addNodes(Dst);
2229 break;
2230 }
2231 // FIXME: ChooseExpr is really a constant. We need to fix
2232 // the CFG do not model them as explicit control-flow.
2233
2234 case Stmt::ChooseExprClass: { // __builtin_choose_expr
2235 Bldr.takeNodes(Pred);
2236 const auto *C = cast<ChooseExpr>(S);
2237 VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
2238 Bldr.addNodes(Dst);
2239 break;
2240 }
2241
2242 case Stmt::CompoundAssignOperatorClass:
2243 Bldr.takeNodes(Pred);
2244 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
2245 Bldr.addNodes(Dst);
2246 break;
2247
2248 case Stmt::CompoundLiteralExprClass:
2249 Bldr.takeNodes(Pred);
2250 VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(S), Pred, Dst);
2251 Bldr.addNodes(Dst);
2252 break;
2253
2254 case Stmt::BinaryConditionalOperatorClass:
2255 case Stmt::ConditionalOperatorClass: { // '?' operator
2256 Bldr.takeNodes(Pred);
2257 const auto *C = cast<AbstractConditionalOperator>(S);
2258 VisitGuardedExpr(C, C->getTrueExpr(), C->getFalseExpr(), Pred, Dst);
2259 Bldr.addNodes(Dst);
2260 break;
2261 }
2262
2263 case Stmt::CXXThisExprClass:
2264 Bldr.takeNodes(Pred);
2265 VisitCXXThisExpr(cast<CXXThisExpr>(S), Pred, Dst);
2266 Bldr.addNodes(Dst);
2267 break;
2268
2269 case Stmt::DeclRefExprClass: {
2270 Bldr.takeNodes(Pred);
2271 const auto *DE = cast<DeclRefExpr>(S);
2272 VisitCommonDeclRefExpr(DE, DE->getDecl(), Pred, Dst);
2273 Bldr.addNodes(Dst);
2274 break;
2275 }
2276
2277 case Stmt::DeclStmtClass:
2278 Bldr.takeNodes(Pred);
2279 VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
2280 Bldr.addNodes(Dst);
2281 break;
2282
2283 case Stmt::ImplicitCastExprClass:
2284 case Stmt::CStyleCastExprClass:
2285 case Stmt::CXXStaticCastExprClass:
2286 case Stmt::CXXDynamicCastExprClass:
2287 case Stmt::CXXReinterpretCastExprClass:
2288 case Stmt::CXXConstCastExprClass:
2289 case Stmt::CXXFunctionalCastExprClass:
2290 case Stmt::BuiltinBitCastExprClass:
2291 case Stmt::ObjCBridgedCastExprClass:
2292 case Stmt::CXXAddrspaceCastExprClass: {
2293 Bldr.takeNodes(Pred);
2294 const auto *C = cast<CastExpr>(S);
2295 ExplodedNodeSet dstExpr;
2296 VisitCast(C, C->getSubExpr(), Pred, dstExpr);
2297
2298 // Handle the postvisit checks.
2299 getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, C, *this);
2300 Bldr.addNodes(Dst);
2301 break;
2302 }
2303
2304 case Expr::MaterializeTemporaryExprClass: {
2305 Bldr.takeNodes(Pred);
2306 const auto *MTE = cast<MaterializeTemporaryExpr>(S);
2307 ExplodedNodeSet dstPrevisit;
2308 getCheckerManager().runCheckersForPreStmt(dstPrevisit, Pred, MTE, *this);
2309 ExplodedNodeSet dstExpr;
2310 for (const auto i : dstPrevisit)
2311 CreateCXXTemporaryObject(MTE, i, dstExpr);
2312 getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, MTE, *this);
2313 Bldr.addNodes(Dst);
2314 break;
2315 }
2316
2317 case Stmt::InitListExprClass: {
2318 const InitListExpr *E = cast<InitListExpr>(S);
2319 Bldr.takeNodes(Pred);
2320 ConstructInitList(E, E->inits(), E->isTransparent(), Pred, Dst);
2321 Bldr.addNodes(Dst);
2322 break;
2323 }
2324
2325 case Expr::CXXParenListInitExprClass: {
2326 const CXXParenListInitExpr *E = cast<CXXParenListInitExpr>(S);
2327 Bldr.takeNodes(Pred);
2328 ConstructInitList(E, E->getInitExprs(), /*IsTransparent*/ false, Pred,
2329 Dst);
2330 Bldr.addNodes(Dst);
2331 break;
2332 }
2333
2334 case Stmt::MemberExprClass:
2335 Bldr.takeNodes(Pred);
2336 VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst);
2337 Bldr.addNodes(Dst);
2338 break;
2339
2340 case Stmt::AtomicExprClass:
2341 Bldr.takeNodes(Pred);
2342 VisitAtomicExpr(cast<AtomicExpr>(S), Pred, Dst);
2343 Bldr.addNodes(Dst);
2344 break;
2345
2346 case Stmt::ObjCIvarRefExprClass:
2347 Bldr.takeNodes(Pred);
2348 VisitLvalObjCIvarRefExpr(cast<ObjCIvarRefExpr>(S), Pred, Dst);
2349 Bldr.addNodes(Dst);
2350 break;
2351
2352 case Stmt::ObjCForCollectionStmtClass:
2353 Bldr.takeNodes(Pred);
2354 VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S), Pred, Dst);
2355 Bldr.addNodes(Dst);
2356 break;
2357
2358 case Stmt::ObjCMessageExprClass:
2359 Bldr.takeNodes(Pred);
2360 VisitObjCMessage(cast<ObjCMessageExpr>(S), Pred, Dst);
2361 Bldr.addNodes(Dst);
2362 break;
2363
2364 case Stmt::ObjCAtThrowStmtClass:
2365 case Stmt::CXXThrowExprClass:
2366 // FIXME: This is not complete. We basically treat @throw as
2367 // an abort.
2368 Bldr.generateSink(S, Pred, Pred->getState());
2369 break;
2370
2371 case Stmt::ReturnStmtClass:
2372 Bldr.takeNodes(Pred);
2373 VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst);
2374 Bldr.addNodes(Dst);
2375 break;
2376
2377 case Stmt::OffsetOfExprClass: {
2378 Bldr.takeNodes(Pred);
2379 ExplodedNodeSet PreVisit;
2380 getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
2381
2383 for (const auto Node : PreVisit)
2384 VisitOffsetOfExpr(cast<OffsetOfExpr>(S), Node, PostVisit);
2385
2387 Bldr.addNodes(Dst);
2388 break;
2389 }
2390
2391 case Stmt::UnaryExprOrTypeTraitExprClass:
2392 Bldr.takeNodes(Pred);
2393 VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
2394 Pred, Dst);
2395 Bldr.addNodes(Dst);
2396 break;
2397
2398 case Stmt::StmtExprClass: {
2399 const auto *SE = cast<StmtExpr>(S);
2400
2401 if (SE->getSubStmt()->body_empty()) {
2402 // Empty statement expression.
2403 assert(SE->getType() == getContext().VoidTy
2404 && "Empty statement expression must have void type.");
2405 break;
2406 }
2407
2408 if (const auto *LastExpr =
2409 dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
2410 ProgramStateRef state = Pred->getState();
2411 Bldr.generateNode(SE, Pred,
2412 state->BindExpr(SE, Pred->getLocationContext(),
2413 state->getSVal(LastExpr,
2414 Pred->getLocationContext())));
2415 }
2416 break;
2417 }
2418
2419 case Stmt::UnaryOperatorClass: {
2420 Bldr.takeNodes(Pred);
2421 const auto *U = cast<UnaryOperator>(S);
2422 if (AMgr.options.ShouldEagerlyAssume && (U->getOpcode() == UO_LNot)) {
2423 ExplodedNodeSet Tmp;
2424 VisitUnaryOperator(U, Pred, Tmp);
2426 }
2427 else
2428 VisitUnaryOperator(U, Pred, Dst);
2429 Bldr.addNodes(Dst);
2430 break;
2431 }
2432
2433 case Stmt::PseudoObjectExprClass: {
2434 Bldr.takeNodes(Pred);
2435 ProgramStateRef state = Pred->getState();
2436 const auto *PE = cast<PseudoObjectExpr>(S);
2437 if (const Expr *Result = PE->getResultExpr()) {
2438 SVal V = state->getSVal(Result, Pred->getLocationContext());
2439 Bldr.generateNode(S, Pred,
2440 state->BindExpr(S, Pred->getLocationContext(), V));
2441 }
2442 else
2443 Bldr.generateNode(S, Pred,
2444 state->BindExpr(S, Pred->getLocationContext(),
2445 UnknownVal()));
2446
2447 Bldr.addNodes(Dst);
2448 break;
2449 }
2450
2451 case Expr::ObjCIndirectCopyRestoreExprClass: {
2452 // ObjCIndirectCopyRestoreExpr implies passing a temporary for
2453 // correctness of lifetime management. Due to limited analysis
2454 // of ARC, this is implemented as direct arg passing.
2455 Bldr.takeNodes(Pred);
2456 ProgramStateRef state = Pred->getState();
2457 const auto *OIE = cast<ObjCIndirectCopyRestoreExpr>(S);
2458 const Expr *E = OIE->getSubExpr();
2459 SVal V = state->getSVal(E, Pred->getLocationContext());
2460 Bldr.generateNode(S, Pred,
2461 state->BindExpr(S, Pred->getLocationContext(), V));
2462 Bldr.addNodes(Dst);
2463 break;
2464 }
2465 }
2466}
2467
2468bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
2469 const LocationContext *CalleeLC) {
2470 const StackFrameContext *CalleeSF = CalleeLC->getStackFrame();
2471 const StackFrameContext *CallerSF = CalleeSF->getParent()->getStackFrame();
2472 assert(CalleeSF && CallerSF);
2473 ExplodedNode *BeforeProcessingCall = nullptr;
2474 const Stmt *CE = CalleeSF->getCallSite();
2475
2476 // Find the first node before we started processing the call expression.
2477 while (N) {
2478 ProgramPoint L = N->getLocation();
2479 BeforeProcessingCall = N;
2480 N = N->pred_empty() ? nullptr : *(N->pred_begin());
2481
2482 // Skip the nodes corresponding to the inlined code.
2483 if (L.getStackFrame() != CallerSF)
2484 continue;
2485 // We reached the caller. Find the node right before we started
2486 // processing the call.
2487 if (L.isPurgeKind())
2488 continue;
2489 if (L.getAs<PreImplicitCall>())
2490 continue;
2491 if (L.getAs<CallEnter>())
2492 continue;
2493 if (std::optional<StmtPoint> SP = L.getAs<StmtPoint>())
2494 if (SP->getStmt() == CE)
2495 continue;
2496 break;
2497 }
2498
2499 if (!BeforeProcessingCall)
2500 return false;
2501
2502 // TODO: Clean up the unneeded nodes.
2503
2504 // Build an Epsilon node from which we will restart the analyzes.
2505 // Note that CE is permitted to be NULL!
2506 static SimpleProgramPointTag PT("ExprEngine", "Replay without inlining");
2507 ProgramPoint NewNodeLoc = EpsilonPoint(
2508 BeforeProcessingCall->getLocationContext(), CE, nullptr, &PT);
2509 // Add the special flag to GDM to signal retrying with no inlining.
2510 // Note, changing the state ensures that we are not going to cache out.
2511 ProgramStateRef NewNodeState = BeforeProcessingCall->getState();
2512 NewNodeState =
2513 NewNodeState->set<ReplayWithoutInlining>(const_cast<Stmt *>(CE));
2514
2515 // Make the new node a successor of BeforeProcessingCall.
2516 bool IsNew = false;
2517 ExplodedNode *NewNode = G.getNode(NewNodeLoc, NewNodeState, false, &IsNew);
2518 // We cached out at this point. Caching out is common due to us backtracking
2519 // from the inlined function, which might spawn several paths.
2520 if (!IsNew)
2521 return true;
2522
2523 NewNode->addPredecessor(BeforeProcessingCall, G);
2524
2525 // Add the new node to the work list.
2526 Engine.enqueueStmtNode(NewNode, CalleeSF->getCallSiteBlock(),
2527 CalleeSF->getIndex());
2528 NumTimesRetriedWithoutInlining++;
2529 return true;
2530}
2531
2532/// Return the innermost location context which is inlined at `Node`, unless
2533/// it's the top-level (entry point) location context.
2535 ExplodedGraph &G) {
2536 const LocationContext *CalleeLC = Node->getLocation().getLocationContext();
2537 const LocationContext *RootLC =
2539
2540 if (CalleeLC->getStackFrame() == RootLC->getStackFrame())
2541 return nullptr;
2542
2543 return CalleeLC;
2544}
2545
2546/// Block entrance. (Update counters).
2548 NodeBuilderWithSinks &nodeBuilder,
2549 ExplodedNode *Pred) {
2550 // If we reach a loop which has a known bound (and meets
2551 // other constraints) then consider completely unrolling it.
2552 if(AMgr.options.ShouldUnrollLoops) {
2553 unsigned maxBlockVisitOnPath = AMgr.options.maxBlockVisitOnPath;
2554 const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminatorStmt();
2555 if (Term) {
2556 ProgramStateRef NewState = updateLoopStack(Term, AMgr.getASTContext(),
2557 Pred, maxBlockVisitOnPath);
2558 if (NewState != Pred->getState()) {
2559 ExplodedNode *UpdatedNode = nodeBuilder.generateNode(NewState, Pred);
2560 if (!UpdatedNode)
2561 return;
2562 Pred = UpdatedNode;
2563 }
2564 }
2565 // Is we are inside an unrolled loop then no need the check the counters.
2566 if(isUnrolledState(Pred->getState()))
2567 return;
2568 }
2569
2570 // If this block is terminated by a loop and it has already been visited the
2571 // maximum number of times, widen the loop.
2572 unsigned int BlockCount = nodeBuilder.getContext().blockCount();
2573 if (BlockCount == AMgr.options.maxBlockVisitOnPath - 1 &&
2574 AMgr.options.ShouldWidenLoops) {
2575 const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminatorStmt();
2576 if (!isa_and_nonnull<ForStmt, WhileStmt, DoStmt, CXXForRangeStmt>(Term))
2577 return;
2578
2579 // Widen.
2580 const LocationContext *LCtx = Pred->getLocationContext();
2581
2582 // FIXME:
2583 // We cannot use the CFG element from the via `ExprEngine::getCFGElementRef`
2584 // since we are currently at the block entrance and the current reference
2585 // would be stale. Ideally, we should pass on the terminator of the CFG
2586 // block, but the terminator cannot be referred as a CFG element.
2587 // Here we just pass the the first CFG element in the block.
2588 ProgramStateRef WidenedState =
2589 getWidenedLoopState(Pred->getState(), LCtx, BlockCount,
2590 *nodeBuilder.getContext().getBlock()->ref_begin());
2591 nodeBuilder.generateNode(WidenedState, Pred);
2592 return;
2593 }
2594
2595 // FIXME: Refactor this into a checker.
2596 if (BlockCount >= AMgr.options.maxBlockVisitOnPath) {
2597 static SimpleProgramPointTag tag(TagProviderName, "Block count exceeded");
2598 const ExplodedNode *Sink =
2599 nodeBuilder.generateSink(Pred->getState(), Pred, &tag);
2600
2601 if (const LocationContext *LC = getInlinedLocationContext(Pred, G)) {
2602 // FIXME: This will unconditionally prevent inlining this function (even
2603 // from other entry points), which is not a reasonable heuristic: even if
2604 // we reached max block count on this particular execution path, there
2605 // may be other execution paths (especially with other parametrizations)
2606 // where the analyzer can reach the end of the function (so there is no
2607 // natural reason to avoid inlining it). However, disabling this would
2608 // significantly increase the analysis time (because more entry points
2609 // would exhaust their allocated budget), so it must be compensated by a
2610 // different (more reasonable) reduction of analysis scope.
2611 Engine.FunctionSummaries->markShouldNotInline(
2612 LC->getStackFrame()->getDecl());
2613
2614 // Re-run the call evaluation without inlining it, by storing the
2615 // no-inlining policy in the state and enqueuing the new work item on
2616 // the list. Replay should almost never fail. Use the stats to catch it
2617 // if it does.
2618 if ((!AMgr.options.NoRetryExhausted && replayWithoutInlining(Pred, LC)))
2619 return;
2620 NumMaxBlockCountReachedInInlined++;
2621 } else
2622 NumMaxBlockCountReached++;
2623
2624 // Make sink nodes as exhausted(for stats) only if retry failed.
2625 Engine.blocksExhausted.push_back(std::make_pair(L, Sink));
2626 }
2627}
2628
2630 const BlockEntrance &Entrance,
2631 ExplodedNode *Pred,
2632 ExplodedNodeSet &Dst) {
2633 llvm::PrettyStackTraceFormat CrashInfo(
2634 "Processing block entrance B%d -> B%d",
2635 Entrance.getPreviousBlock()->getBlockID(),
2636 Entrance.getBlock()->getBlockID());
2637 currBldrCtx = &BldCtx;
2638 getCheckerManager().runCheckersForBlockEntrance(Dst, Pred, Entrance, *this);
2639 currBldrCtx = nullptr;
2640}
2641
2642//===----------------------------------------------------------------------===//
2643// Branch processing.
2644//===----------------------------------------------------------------------===//
2645
2646/// RecoverCastedSymbol - A helper function for ProcessBranch that is used
2647/// to try to recover some path-sensitivity for casts of symbolic
2648/// integers that promote their values (which are currently not tracked well).
2649/// This function returns the SVal bound to Condition->IgnoreCasts if all the
2650// cast(s) did was sign-extend the original value.
2652 const Stmt *Condition,
2653 const LocationContext *LCtx,
2654 ASTContext &Ctx) {
2655
2656 const auto *Ex = dyn_cast<Expr>(Condition);
2657 if (!Ex)
2658 return UnknownVal();
2659
2660 uint64_t bits = 0;
2661 bool bitsInit = false;
2662
2663 while (const auto *CE = dyn_cast<CastExpr>(Ex)) {
2664 QualType T = CE->getType();
2665
2667 return UnknownVal();
2668
2669 uint64_t newBits = Ctx.getTypeSize(T);
2670 if (!bitsInit || newBits < bits) {
2671 bitsInit = true;
2672 bits = newBits;
2673 }
2674
2675 Ex = CE->getSubExpr();
2676 }
2677
2678 // We reached a non-cast. Is it a symbolic value?
2679 QualType T = Ex->getType();
2680
2681 if (!bitsInit || !T->isIntegralOrEnumerationType() ||
2682 Ctx.getTypeSize(T) > bits)
2683 return UnknownVal();
2684
2685 return state->getSVal(Ex, LCtx);
2686}
2687
2688#ifndef NDEBUG
2689static const Stmt *getRightmostLeaf(const Stmt *Condition) {
2690 while (Condition) {
2691 const auto *BO = dyn_cast<BinaryOperator>(Condition);
2692 if (!BO || !BO->isLogicalOp()) {
2693 return Condition;
2694 }
2695 Condition = BO->getRHS()->IgnoreParens();
2696 }
2697 return nullptr;
2698}
2699#endif
2700
2701// Returns the condition the branch at the end of 'B' depends on and whose value
2702// has been evaluated within 'B'.
2703// In most cases, the terminator condition of 'B' will be evaluated fully in
2704// the last statement of 'B'; in those cases, the resolved condition is the
2705// given 'Condition'.
2706// If the condition of the branch is a logical binary operator tree, the CFG is
2707// optimized: in that case, we know that the expression formed by all but the
2708// rightmost leaf of the logical binary operator tree must be true, and thus
2709// the branch condition is at this point equivalent to the truth value of that
2710// rightmost leaf; the CFG block thus only evaluates this rightmost leaf
2711// expression in its final statement. As the full condition in that case was
2712// not evaluated, and is thus not in the SVal cache, we need to use that leaf
2713// expression to evaluate the truth value of the condition in the current state
2714// space.
2716 const CFGBlock *B) {
2717 if (const auto *Ex = dyn_cast<Expr>(Condition))
2718 Condition = Ex->IgnoreParens();
2719
2720 const auto *BO = dyn_cast<BinaryOperator>(Condition);
2721 if (!BO || !BO->isLogicalOp())
2722 return Condition;
2723
2724 assert(B->getTerminator().isStmtBranch() &&
2725 "Other kinds of branches are handled separately!");
2726
2727 // For logical operations, we still have the case where some branches
2728 // use the traditional "merge" approach and others sink the branch
2729 // directly into the basic blocks representing the logical operation.
2730 // We need to distinguish between those two cases here.
2731
2732 // The invariants are still shifting, but it is possible that the
2733 // last element in a CFGBlock is not a CFGStmt. Look for the last
2734 // CFGStmt as the value of the condition.
2735 for (CFGElement Elem : llvm::reverse(*B)) {
2736 std::optional<CFGStmt> CS = Elem.getAs<CFGStmt>();
2737 if (!CS)
2738 continue;
2739 const Stmt *LastStmt = CS->getStmt();
2740 assert(LastStmt == Condition || LastStmt == getRightmostLeaf(Condition));
2741 return LastStmt;
2742 }
2743 llvm_unreachable("could not resolve condition");
2744}
2745
2747 std::pair<const ObjCForCollectionStmt *, const LocationContext *>;
2748
2749REGISTER_MAP_WITH_PROGRAMSTATE(ObjCForHasMoreIterations, ObjCForLctxPair, bool)
2750
2751ProgramStateRef ExprEngine::setWhetherHasMoreIteration(
2752 ProgramStateRef State, const ObjCForCollectionStmt *O,
2753 const LocationContext *LC, bool HasMoreIteraton) {
2754 assert(!State->contains<ObjCForHasMoreIterations>({O, LC}));
2755 return State->set<ObjCForHasMoreIterations>({O, LC}, HasMoreIteraton);
2756}
2757
2760 const ObjCForCollectionStmt *O,
2761 const LocationContext *LC) {
2762 assert(State->contains<ObjCForHasMoreIterations>({O, LC}));
2763 return State->remove<ObjCForHasMoreIterations>({O, LC});
2764}
2765
2767 const ObjCForCollectionStmt *O,
2768 const LocationContext *LC) {
2769 assert(State->contains<ObjCForHasMoreIterations>({O, LC}));
2770 return *State->get<ObjCForHasMoreIterations>({O, LC});
2771}
2772
2773/// Split the state on whether there are any more iterations left for this loop.
2774/// Returns a (HasMoreIteration, HasNoMoreIteration) pair, or std::nullopt when
2775/// the acquisition of the loop condition value failed.
2776static std::optional<std::pair<ProgramStateRef, ProgramStateRef>>
2778 ProgramStateRef State = N->getState();
2779 if (const auto *ObjCFor = dyn_cast<ObjCForCollectionStmt>(Condition)) {
2780 bool HasMoreIteraton =
2782 // Checkers have already ran on branch conditions, so the current
2783 // information as to whether the loop has more iteration becomes outdated
2784 // after this point.
2785 State = ExprEngine::removeIterationState(State, ObjCFor,
2786 N->getLocationContext());
2787 if (HasMoreIteraton)
2788 return std::pair<ProgramStateRef, ProgramStateRef>{State, nullptr};
2789 else
2790 return std::pair<ProgramStateRef, ProgramStateRef>{nullptr, State};
2791 }
2792 SVal X = State->getSVal(Condition, N->getLocationContext());
2793
2794 if (X.isUnknownOrUndef()) {
2795 // Give it a chance to recover from unknown.
2796 if (const auto *Ex = dyn_cast<Expr>(Condition)) {
2797 if (Ex->getType()->isIntegralOrEnumerationType()) {
2798 // Try to recover some path-sensitivity. Right now casts of symbolic
2799 // integers that promote their values are currently not tracked well.
2800 // If 'Condition' is such an expression, try and recover the
2801 // underlying value and use that instead.
2802 SVal recovered =
2804 N->getState()->getStateManager().getContext());
2805
2806 if (!recovered.isUnknown()) {
2807 X = recovered;
2808 }
2809 }
2810 }
2811 }
2812
2813 // If the condition is still unknown, give up.
2814 if (X.isUnknownOrUndef())
2815 return std::nullopt;
2816
2817 DefinedSVal V = X.castAs<DefinedSVal>();
2818
2819 ProgramStateRef StTrue, StFalse;
2820 return State->assume(V);
2821}
2822
2824 const Stmt *Condition, NodeBuilderContext &BldCtx, ExplodedNode *Pred,
2825 ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF,
2826 std::optional<unsigned> IterationsCompletedInLoop) {
2827 assert((!Condition || !isa<CXXBindTemporaryExpr>(Condition)) &&
2828 "CXXBindTemporaryExprs are handled by processBindTemporary.");
2829 currBldrCtx = &BldCtx;
2830
2831 // Check for NULL conditions; e.g. "for(;;)"
2832 if (!Condition) {
2833 BranchNodeBuilder NullCondBldr(Pred, Dst, BldCtx, DstT, DstF);
2834 NullCondBldr.generateNode(Pred->getState(), true, Pred);
2835 return;
2836 }
2837
2838 if (const auto *Ex = dyn_cast<Expr>(Condition))
2839 Condition = Ex->IgnoreParens();
2840
2842 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
2843 Condition->getBeginLoc(),
2844 "Error evaluating branch");
2845
2846 ExplodedNodeSet CheckersOutSet;
2848 Pred, *this);
2849 // We generated only sinks.
2850 if (CheckersOutSet.empty())
2851 return;
2852
2853 BranchNodeBuilder Builder(CheckersOutSet, Dst, BldCtx, DstT, DstF);
2854 for (ExplodedNode *PredN : CheckersOutSet) {
2855 if (PredN->isSink())
2856 continue;
2857
2858 ProgramStateRef PrevState = PredN->getState();
2859
2860 ProgramStateRef StTrue = PrevState, StFalse = PrevState;
2861 if (const auto KnownCondValueAssumption = assumeCondition(Condition, PredN))
2862 std::tie(StTrue, StFalse) = *KnownCondValueAssumption;
2863
2864 if (StTrue && StFalse)
2865 assert(!isa<ObjCForCollectionStmt>(Condition));
2866
2867 // We want to ensure consistent behavior between `eagerly-assume=false`,
2868 // when the state split is always performed by the `assumeCondition()`
2869 // call within this function and `eagerly-assume=true` (the default), when
2870 // some conditions (comparison operators, unary negation) can trigger a
2871 // state split before this callback. There are some contrived corner cases
2872 // that behave differently with and without `eagerly-assume`, but I don't
2873 // know about an example that could plausibly appear in "real" code.
2874 bool BothFeasible =
2875 (StTrue && StFalse) ||
2876 didEagerlyAssumeBifurcateAt(PrevState, dyn_cast<Expr>(Condition));
2877
2878 if (StTrue) {
2879 // In a loop, if both branches are feasible (i.e. the analyzer doesn't
2880 // understand the loop condition) and two iterations have already been
2881 // completed, then don't assume a third iteration because it is a
2882 // redundant execution path (unlikely to be different from earlier loop
2883 // exits) and can cause false positives if e.g. the loop iterates over a
2884 // two-element structure with an opaque condition.
2885 //
2886 // The iteration count "2" is hardcoded because it's the natural limit:
2887 // * the fact that the programmer wrote a loop (and not just an `if`)
2888 // implies that they thought that the loop body might be executed twice;
2889 // * however, there are situations where the programmer knows that there
2890 // are at most two iterations but writes a loop that appears to be
2891 // generic, because there is no special syntax for "loop with at most
2892 // two iterations". (This pattern is common in FFMPEG and appears in
2893 // many other projects as well.)
2894 bool CompletedTwoIterations = IterationsCompletedInLoop.value_or(0) >= 2;
2895 bool SkipTrueBranch = BothFeasible && CompletedTwoIterations;
2896
2897 // FIXME: This "don't assume third iteration" heuristic partially
2898 // conflicts with the widen-loop analysis option (which is off by
2899 // default). If we intend to support and stabilize the loop widening,
2900 // we must ensure that it 'plays nicely' with this logic.
2901 if (!SkipTrueBranch || AMgr.options.ShouldWidenLoops) {
2902 Builder.generateNode(StTrue, true, PredN);
2903 } else if (!AMgr.options.InlineFunctionsWithAmbiguousLoops) {
2904 // FIXME: There is an ancient and arbitrary heuristic in
2905 // `ExprEngine::processCFGBlockEntrance` which prevents all further
2906 // inlining of a function if it finds an execution path within that
2907 // function which reaches the `MaxBlockVisitOnPath` limit (a/k/a
2908 // `analyzer-max-loop`, by default four iterations in a loop). Adding
2909 // this "don't assume third iteration" logic significantly increased
2910 // the analysis runtime on some inputs because less functions were
2911 // arbitrarily excluded from being inlined, so more entry points used
2912 // up their full allocated budget. As a hacky compensation for this,
2913 // here we apply the "should not inline" mark in cases when the loop
2914 // could potentially reach the `MaxBlockVisitOnPath` limit without the
2915 // "don't assume third iteration" logic. This slightly overcompensates
2916 // (activates if the third iteration can be entered, and will not
2917 // recognize cases where the fourth iteration would't be completed), but
2918 // should be good enough for practical purposes.
2919 if (const LocationContext *LC = getInlinedLocationContext(Pred, G)) {
2920 Engine.FunctionSummaries->markShouldNotInline(
2921 LC->getStackFrame()->getDecl());
2922 }
2923 }
2924 }
2925
2926 if (StFalse) {
2927 // In a loop, if both branches are feasible (i.e. the analyzer doesn't
2928 // understand the loop condition), we are before the first iteration and
2929 // the analyzer option `assume-at-least-one-iteration` is set to `true`,
2930 // then avoid creating the execution path where the loop is skipped.
2931 //
2932 // In some situations this "loop is skipped" execution path is an
2933 // important corner case that may evade the notice of the developer and
2934 // hide significant bugs -- however, there are also many situations where
2935 // it's guaranteed that at least one iteration will happen (e.g. some
2936 // data structure is always nonempty), but the analyzer cannot realize
2937 // this and will produce false positives when it assumes that the loop is
2938 // skipped.
2939 bool BeforeFirstIteration = IterationsCompletedInLoop == std::optional{0};
2940 bool SkipFalseBranch = BothFeasible && BeforeFirstIteration &&
2941 AMgr.options.ShouldAssumeAtLeastOneIteration;
2942 if (!SkipFalseBranch)
2943 Builder.generateNode(StFalse, false, PredN);
2944 }
2945 }
2946 currBldrCtx = nullptr;
2947}
2948
2949/// The GDM component containing the set of global variables which have been
2950/// previously initialized with explicit initializers.
2952 llvm::ImmutableSet<const VarDecl *>)
2953
2955 const DeclStmt *DS, NodeBuilderContext &BuilderCtx, ExplodedNode *Pred,
2956 ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF) {
2957 currBldrCtx = &BuilderCtx;
2958
2959 const auto *VD = cast<VarDecl>(DS->getSingleDecl());
2960 ProgramStateRef state = Pred->getState();
2961 bool initHasRun = state->contains<InitializedGlobalsSet>(VD);
2962 BranchNodeBuilder Builder(Pred, Dst, BuilderCtx, DstT, DstF);
2963
2964 if (!initHasRun) {
2965 state = state->add<InitializedGlobalsSet>(VD);
2966 }
2967
2968 Builder.generateNode(state, initHasRun, Pred);
2969
2970 currBldrCtx = nullptr;
2971}
2972
2973/// processIndirectGoto - Called by CoreEngine. Used to generate successor
2974/// nodes by processing the 'effects' of a computed goto jump.
2976 ProgramStateRef state = builder.getState();
2977 SVal V = state->getSVal(builder.getTarget(), builder.getLocationContext());
2978
2979 // Three possibilities:
2980 //
2981 // (1) We know the computed label.
2982 // (2) The label is NULL (or some other constant), or Undefined.
2983 // (3) We have no clue about the label. Dispatch to all targets.
2984 //
2985
2986 using iterator = IndirectGotoNodeBuilder::iterator;
2987
2988 if (std::optional<loc::GotoLabel> LV = V.getAs<loc::GotoLabel>()) {
2989 const LabelDecl *L = LV->getLabel();
2990
2991 for (iterator Succ : builder) {
2992 if (Succ.getLabel() == L) {
2993 builder.generateNode(Succ, state);
2994 return;
2995 }
2996 }
2997
2998 llvm_unreachable("No block with label.");
2999 }
3000
3001 if (isa<UndefinedVal, loc::ConcreteInt>(V)) {
3002 // Dispatch to the first target and mark it as a sink.
3003 //ExplodedNode* N = builder.generateNode(builder.begin(), state, true);
3004 // FIXME: add checker visit.
3005 // UndefBranches.insert(N);
3006 return;
3007 }
3008
3009 // This is really a catch-all. We don't support symbolics yet.
3010 // FIXME: Implement dispatch for symbolic pointers.
3011
3012 for (iterator Succ : builder)
3013 builder.generateNode(Succ, state);
3014}
3015
3017 ExplodedNode *Pred,
3018 ExplodedNodeSet &Dst,
3019 const BlockEdge &L) {
3020 SaveAndRestore<const NodeBuilderContext *> NodeContextRAII(currBldrCtx, &BC);
3021 getCheckerManager().runCheckersForBeginFunction(Dst, L, Pred, *this);
3022}
3023
3024/// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path
3025/// nodes when the control reaches the end of a function.
3027 ExplodedNode *Pred,
3028 const ReturnStmt *RS) {
3029 ProgramStateRef State = Pred->getState();
3030
3031 if (!Pred->getStackFrame()->inTopFrame())
3032 State = finishArgumentConstruction(
3033 State, *getStateManager().getCallEventManager().getCaller(
3034 Pred->getStackFrame(), Pred->getState()));
3035
3036 // FIXME: We currently cannot assert that temporaries are clear, because
3037 // lifetime extended temporaries are not always modelled correctly. In some
3038 // cases when we materialize the temporary, we do
3039 // createTemporaryRegionIfNeeded(), and the region changes, and also the
3040 // respective destructor becomes automatic from temporary. So for now clean up
3041 // the state manually before asserting. Ideally, this braced block of code
3042 // should go away.
3043 {
3044 const LocationContext *FromLC = Pred->getLocationContext();
3045 const LocationContext *ToLC = FromLC->getStackFrame()->getParent();
3046 const LocationContext *LC = FromLC;
3047 while (LC != ToLC) {
3048 assert(LC && "ToLC must be a parent of FromLC!");
3049 for (auto I : State->get<ObjectsUnderConstruction>())
3050 if (I.first.getLocationContext() == LC) {
3051 // The comment above only pardons us for not cleaning up a
3052 // temporary destructor. If any other statements are found here,
3053 // it must be a separate problem.
3054 assert(I.first.getItem().getKind() ==
3056 I.first.getItem().getKind() ==
3058 State = State->remove<ObjectsUnderConstruction>(I.first);
3059 }
3060 LC = LC->getParent();
3061 }
3062 }
3063
3064 // Perform the transition with cleanups.
3065 if (State != Pred->getState()) {
3066 ExplodedNodeSet PostCleanup;
3067 NodeBuilder Bldr(Pred, PostCleanup, BC);
3068 Pred = Bldr.generateNode(Pred->getLocation(), State, Pred);
3069 if (!Pred) {
3070 // The node with clean temporaries already exists. We might have reached
3071 // it on a path on which we initialize different temporaries.
3072 return;
3073 }
3074 }
3075
3076 assert(areAllObjectsFullyConstructed(Pred->getState(),
3077 Pred->getLocationContext(),
3078 Pred->getStackFrame()->getParent()));
3079 ExplodedNodeSet Dst;
3080 if (Pred->getLocationContext()->inTopFrame()) {
3081 // Remove dead symbols.
3082 ExplodedNodeSet AfterRemovedDead;
3083 removeDeadOnEndOfFunction(BC, Pred, AfterRemovedDead);
3084
3085 // Notify checkers.
3086 for (const auto I : AfterRemovedDead)
3087 getCheckerManager().runCheckersForEndFunction(BC, Dst, I, *this, RS);
3088 } else {
3089 getCheckerManager().runCheckersForEndFunction(BC, Dst, Pred, *this, RS);
3090 }
3091
3092 Engine.enqueueEndOfFunction(Dst, RS);
3093}
3094
3095/// ProcessSwitch - Called by CoreEngine. Used to generate successor
3096/// nodes by processing the 'effects' of a switch statement.
3098 using iterator = SwitchNodeBuilder::iterator;
3099
3100 ProgramStateRef state = builder.getState();
3101 const Expr *CondE = builder.getCondition();
3102 SVal CondV_untested = state->getSVal(CondE, builder.getLocationContext());
3103
3104 if (CondV_untested.isUndef()) {
3105 //ExplodedNode* N = builder.generateDefaultCaseNode(state, true);
3106 // FIXME: add checker
3107 //UndefBranches.insert(N);
3108
3109 return;
3110 }
3111 DefinedOrUnknownSVal CondV = CondV_untested.castAs<DefinedOrUnknownSVal>();
3112
3113 ProgramStateRef DefaultSt = state;
3114
3115 iterator I = builder.begin(), EI = builder.end();
3116 bool defaultIsFeasible = I == EI;
3117
3118 for ( ; I != EI; ++I) {
3119 // Successor may be pruned out during CFG construction.
3120 if (!I.getBlock())
3121 continue;
3122
3123 const CaseStmt *Case = I.getCase();
3124
3125 // Evaluate the LHS of the case value.
3126 llvm::APSInt V1 = Case->getLHS()->EvaluateKnownConstInt(getContext());
3127 assert(V1.getBitWidth() == getContext().getIntWidth(CondE->getType()));
3128
3129 // Get the RHS of the case, if it exists.
3130 llvm::APSInt V2;
3131 if (const Expr *E = Case->getRHS())
3133 else
3134 V2 = V1;
3135
3136 ProgramStateRef StateCase;
3137 if (std::optional<NonLoc> NL = CondV.getAs<NonLoc>())
3138 std::tie(StateCase, DefaultSt) =
3139 DefaultSt->assumeInclusiveRange(*NL, V1, V2);
3140 else // UnknownVal
3141 StateCase = DefaultSt;
3142
3143 if (StateCase)
3144 builder.generateCaseStmtNode(I, StateCase);
3145
3146 // Now "assume" that the case doesn't match. Add this state
3147 // to the default state (if it is feasible).
3148 if (DefaultSt)
3149 defaultIsFeasible = true;
3150 else {
3151 defaultIsFeasible = false;
3152 break;
3153 }
3154 }
3155
3156 if (!defaultIsFeasible)
3157 return;
3158
3159 // If we have switch(enum value), the default branch is not
3160 // feasible if all of the enum constants not covered by 'case:' statements
3161 // are not feasible values for the switch condition.
3162 //
3163 // Note that this isn't as accurate as it could be. Even if there isn't
3164 // a case for a particular enum value as long as that enum value isn't
3165 // feasible then it shouldn't be considered for making 'default:' reachable.
3166 const SwitchStmt *SS = builder.getSwitch();
3167 const Expr *CondExpr = SS->getCond()->IgnoreParenImpCasts();
3168 if (CondExpr->getType()->isEnumeralType()) {
3169 if (SS->isAllEnumCasesCovered())
3170 return;
3171 }
3172
3173 builder.generateDefaultCaseNode(DefaultSt);
3174}
3175
3176//===----------------------------------------------------------------------===//
3177// Transfer functions: Loads and stores.
3178//===----------------------------------------------------------------------===//
3179
3181 ExplodedNode *Pred,
3182 ExplodedNodeSet &Dst) {
3183 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
3184
3185 ProgramStateRef state = Pred->getState();
3186 const LocationContext *LCtx = Pred->getLocationContext();
3187
3188 auto resolveAsLambdaCapturedVar =
3189 [&](const ValueDecl *VD) -> std::optional<std::pair<SVal, QualType>> {
3190 const auto *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
3191 const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
3192 if (AMgr.options.ShouldInlineLambdas && DeclRefEx &&
3193 DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
3194 MD->getParent()->isLambda()) {
3195 // Lookup the field of the lambda.
3196 const CXXRecordDecl *CXXRec = MD->getParent();
3197 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
3198 FieldDecl *LambdaThisCaptureField;
3199 CXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField);
3200
3201 // Sema follows a sequence of complex rules to determine whether the
3202 // variable should be captured.
3203 if (const FieldDecl *FD = LambdaCaptureFields[VD]) {
3204 Loc CXXThis = svalBuilder.getCXXThis(MD, LCtx->getStackFrame());
3205 SVal CXXThisVal = state->getSVal(CXXThis);
3206 return std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType());
3207 }
3208 }
3209
3210 return std::nullopt;
3211 };
3212
3213 if (const auto *VD = dyn_cast<VarDecl>(D)) {
3214 // C permits "extern void v", and if you cast the address to a valid type,
3215 // you can even do things with it. We simply pretend
3216 assert(Ex->isGLValue() || VD->getType()->isVoidType());
3217 const LocationContext *LocCtxt = Pred->getLocationContext();
3218 std::optional<std::pair<SVal, QualType>> VInfo =
3219 resolveAsLambdaCapturedVar(VD);
3220
3221 if (!VInfo)
3222 VInfo = std::make_pair(state->getLValue(VD, LocCtxt), VD->getType());
3223
3224 SVal V = VInfo->first;
3225 bool IsReference = VInfo->second->isReferenceType();
3226
3227 // For references, the 'lvalue' is the pointer address stored in the
3228 // reference region.
3229 if (IsReference) {
3230 if (const MemRegion *R = V.getAsRegion())
3231 V = state->getSVal(R);
3232 else
3233 V = UnknownVal();
3234 }
3235
3236 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
3238 return;
3239 }
3240 if (const auto *ED = dyn_cast<EnumConstantDecl>(D)) {
3241 assert(!Ex->isGLValue());
3242 SVal V = svalBuilder.makeIntVal(ED->getInitVal());
3243 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V));
3244 return;
3245 }
3246 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
3247 SVal V = svalBuilder.getFunctionPointer(FD);
3248 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
3250 return;
3251 }
3252 if (isa<FieldDecl, IndirectFieldDecl>(D)) {
3253 // Delegate all work related to pointer to members to the surrounding
3254 // operator&.
3255 return;
3256 }
3257 if (const auto *BD = dyn_cast<BindingDecl>(D)) {
3258 // Handle structured bindings captured by lambda.
3259 if (std::optional<std::pair<SVal, QualType>> VInfo =
3260 resolveAsLambdaCapturedVar(BD)) {
3261 auto [V, T] = VInfo.value();
3262
3263 if (T->isReferenceType()) {
3264 if (const MemRegion *R = V.getAsRegion())
3265 V = state->getSVal(R);
3266 else
3267 V = UnknownVal();
3268 }
3269
3270 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
3272 return;
3273 }
3274
3275 const auto *DD = cast<DecompositionDecl>(BD->getDecomposedDecl());
3276
3277 SVal Base = state->getLValue(DD, LCtx);
3278 if (DD->getType()->isReferenceType()) {
3279 if (const MemRegion *R = Base.getAsRegion())
3280 Base = state->getSVal(R);
3281 else
3282 Base = UnknownVal();
3283 }
3284
3285 SVal V = UnknownVal();
3286
3287 // Handle binding to data members
3288 if (const auto *ME = dyn_cast<MemberExpr>(BD->getBinding())) {
3289 const auto *Field = cast<FieldDecl>(ME->getMemberDecl());
3290 V = state->getLValue(Field, Base);
3291 }
3292 // Handle binding to arrays
3293 else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(BD->getBinding())) {
3294 SVal Idx = state->getSVal(ASE->getIdx(), LCtx);
3295
3296 // Note: the index of an element in a structured binding is automatically
3297 // created and it is a unique identifier of the specific element. Thus it
3298 // cannot be a value that varies at runtime.
3299 assert(Idx.isConstant() && "BindingDecl array index is not a constant!");
3300
3301 V = state->getLValue(BD->getType(), Idx, Base);
3302 }
3303 // Handle binding to tuple-like structures
3304 else if (const auto *HV = BD->getHoldingVar()) {
3305 V = state->getLValue(HV, LCtx);
3306
3307 if (HV->getType()->isReferenceType()) {
3308 if (const MemRegion *R = V.getAsRegion())
3309 V = state->getSVal(R);
3310 else
3311 V = UnknownVal();
3312 }
3313 } else
3314 llvm_unreachable("An unknown case of structured binding encountered!");
3315
3316 // In case of tuple-like types the references are already handled, so we
3317 // don't want to handle them again.
3318 if (BD->getType()->isReferenceType() && !BD->getHoldingVar()) {
3319 if (const MemRegion *R = V.getAsRegion())
3320 V = state->getSVal(R);
3321 else
3322 V = UnknownVal();
3323 }
3324
3325 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
3327
3328 return;
3329 }
3330
3331 if (const auto *TPO = dyn_cast<TemplateParamObjectDecl>(D)) {
3332 // FIXME: We should meaningfully implement this.
3333 (void)TPO;
3334 return;
3335 }
3336
3337 llvm_unreachable("Support for this Decl not implemented.");
3338}
3339
3340/// VisitArrayInitLoopExpr - Transfer function for array init loop.
3342 ExplodedNode *Pred,
3343 ExplodedNodeSet &Dst) {
3344 ExplodedNodeSet CheckerPreStmt;
3345 getCheckerManager().runCheckersForPreStmt(CheckerPreStmt, Pred, Ex, *this);
3346
3347 ExplodedNodeSet EvalSet;
3348 StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);
3349
3350 const Expr *Arr = Ex->getCommonExpr()->getSourceExpr();
3351
3352 for (auto *Node : CheckerPreStmt) {
3353
3354 // The constructor visitior has already taken care of everything.
3355 if (isa<CXXConstructExpr>(Ex->getSubExpr()))
3356 break;
3357
3358 const LocationContext *LCtx = Node->getLocationContext();
3359 ProgramStateRef state = Node->getState();
3360
3361 SVal Base = UnknownVal();
3362
3363 // As in case of this expression the sub-expressions are not visited by any
3364 // other transfer functions, they are handled by matching their AST.
3365
3366 // Case of implicit copy or move ctor of object with array member
3367 //
3368 // Note: ExprEngine::VisitMemberExpr is not able to bind the array to the
3369 // environment.
3370 //
3371 // struct S {
3372 // int arr[2];
3373 // };
3374 //
3375 //
3376 // S a;
3377 // S b = a;
3378 //
3379 // The AST in case of a *copy constructor* looks like this:
3380 // ArrayInitLoopExpr
3381 // |-OpaqueValueExpr
3382 // | `-MemberExpr <-- match this
3383 // | `-DeclRefExpr
3384 // ` ...
3385 //
3386 //
3387 // S c;
3388 // S d = std::move(d);
3389 //
3390 // In case of a *move constructor* the resulting AST looks like:
3391 // ArrayInitLoopExpr
3392 // |-OpaqueValueExpr
3393 // | `-MemberExpr <-- match this first
3394 // | `-CXXStaticCastExpr <-- match this after
3395 // | `-DeclRefExpr
3396 // ` ...
3397 if (const auto *ME = dyn_cast<MemberExpr>(Arr)) {
3398 Expr *MEBase = ME->getBase();
3399
3400 // Move ctor
3401 if (auto CXXSCE = dyn_cast<CXXStaticCastExpr>(MEBase)) {
3402 MEBase = CXXSCE->getSubExpr();
3403 }
3404
3405 auto ObjDeclExpr = cast<DeclRefExpr>(MEBase);
3406 SVal Obj = state->getLValue(cast<VarDecl>(ObjDeclExpr->getDecl()), LCtx);
3407
3408 Base = state->getLValue(cast<FieldDecl>(ME->getMemberDecl()), Obj);
3409 }
3410
3411 // Case of lambda capture and decomposition declaration
3412 //
3413 // int arr[2];
3414 //
3415 // [arr]{ int a = arr[0]; }();
3416 // auto[a, b] = arr;
3417 //
3418 // In both of these cases the AST looks like the following:
3419 // ArrayInitLoopExpr
3420 // |-OpaqueValueExpr
3421 // | `-DeclRefExpr <-- match this
3422 // ` ...
3423 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arr))
3424 Base = state->getLValue(cast<VarDecl>(DRE->getDecl()), LCtx);
3425
3426 // Create a lazy compound value to the original array
3427 if (const MemRegion *R = Base.getAsRegion())
3428 Base = state->getSVal(R);
3429 else
3430 Base = UnknownVal();
3431
3432 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, Base));
3433 }
3434
3435 getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, Ex, *this);
3436}
3437
3438/// VisitArraySubscriptExpr - Transfer function for array accesses
3440 ExplodedNode *Pred,
3441 ExplodedNodeSet &Dst){
3442 const Expr *Base = A->getBase()->IgnoreParens();
3443 const Expr *Idx = A->getIdx()->IgnoreParens();
3444
3445 ExplodedNodeSet CheckerPreStmt;
3446 getCheckerManager().runCheckersForPreStmt(CheckerPreStmt, Pred, A, *this);
3447
3448 ExplodedNodeSet EvalSet;
3449 StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);
3450
3451 bool IsVectorType = A->getBase()->getType()->isVectorType();
3452
3453 // The "like" case is for situations where C standard prohibits the type to
3454 // be an lvalue, e.g. taking the address of a subscript of an expression of
3455 // type "void *".
3456 bool IsGLValueLike = A->isGLValue() ||
3457 (A->getType().isCForbiddenLValueType() && !AMgr.getLangOpts().CPlusPlus);
3458
3459 for (auto *Node : CheckerPreStmt) {
3460 const LocationContext *LCtx = Node->getLocationContext();
3461 ProgramStateRef state = Node->getState();
3462
3463 if (IsGLValueLike) {
3464 QualType T = A->getType();
3465
3466 // One of the forbidden LValue types! We still need to have sensible
3467 // symbolic locations to represent this stuff. Note that arithmetic on
3468 // void pointers is a GCC extension.
3469 if (T->isVoidType())
3470 T = getContext().CharTy;
3471
3472 SVal V = state->getLValue(T,
3473 state->getSVal(Idx, LCtx),
3474 state->getSVal(Base, LCtx));
3475 Bldr.generateNode(A, Node, state->BindExpr(A, LCtx, V), nullptr,
3477 } else if (IsVectorType) {
3478 // FIXME: non-glvalue vector reads are not modelled.
3479 Bldr.generateNode(A, Node, state, nullptr);
3480 } else {
3481 llvm_unreachable("Array subscript should be an lValue when not \
3482a vector and not a forbidden lvalue type");
3483 }
3484 }
3485
3486 getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, A, *this);
3487}
3488
3489/// VisitMemberExpr - Transfer function for member expressions.
3491 ExplodedNodeSet &Dst) {
3492 // FIXME: Prechecks eventually go in ::Visit().
3493 ExplodedNodeSet CheckedSet;
3494 getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, M, *this);
3495
3496 ExplodedNodeSet EvalSet;
3498
3499 // Handle static member variables and enum constants accessed via
3500 // member syntax.
3501 if (isa<VarDecl, EnumConstantDecl>(Member)) {
3502 for (const auto I : CheckedSet)
3503 VisitCommonDeclRefExpr(M, Member, I, EvalSet);
3504 } else {
3505 StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx);
3506 ExplodedNodeSet Tmp;
3507
3508 for (const auto I : CheckedSet) {
3509 ProgramStateRef state = I->getState();
3510 const LocationContext *LCtx = I->getLocationContext();
3511 Expr *BaseExpr = M->getBase();
3512
3513 // Handle C++ method calls.
3514 if (const auto *MD = dyn_cast<CXXMethodDecl>(Member)) {
3515 if (MD->isImplicitObjectMemberFunction())
3516 state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr);
3517
3518 SVal MDVal = svalBuilder.getFunctionPointer(MD);
3519 state = state->BindExpr(M, LCtx, MDVal);
3520
3521 Bldr.generateNode(M, I, state);
3522 continue;
3523 }
3524
3525 // Handle regular struct fields / member variables.
3526 const SubRegion *MR = nullptr;
3527 state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr,
3528 /*Result=*/nullptr,
3529 /*OutRegionWithAdjustments=*/&MR);
3530 SVal baseExprVal =
3531 MR ? loc::MemRegionVal(MR) : state->getSVal(BaseExpr, LCtx);
3532
3533 // FIXME: Copied from RegionStoreManager::bind()
3534 if (const auto *SR =
3535 dyn_cast_or_null<SymbolicRegion>(baseExprVal.getAsRegion())) {
3536 QualType T = SR->getPointeeStaticType();
3537 baseExprVal =
3538 loc::MemRegionVal(getStoreManager().GetElementZeroRegion(SR, T));
3539 }
3540
3541 const auto *field = cast<FieldDecl>(Member);
3542 SVal L = state->getLValue(field, baseExprVal);
3543
3544 if (M->isGLValue() || M->getType()->isArrayType()) {
3545 // We special-case rvalues of array type because the analyzer cannot
3546 // reason about them, since we expect all regions to be wrapped in Locs.
3547 // We instead treat these as lvalues and assume that they will decay to
3548 // pointers as soon as they are used.
3549 if (!M->isGLValue()) {
3550 assert(M->getType()->isArrayType());
3551 const auto *PE =
3552 dyn_cast<ImplicitCastExpr>(I->getParentMap().getParentIgnoreParens(M));
3553 if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {
3554 llvm_unreachable("should always be wrapped in ArrayToPointerDecay");
3555 }
3556 }
3557
3558 if (field->getType()->isReferenceType()) {
3559 if (const MemRegion *R = L.getAsRegion())
3560 L = state->getSVal(R);
3561 else
3562 L = UnknownVal();
3563 }
3564
3565 Bldr.generateNode(M, I, state->BindExpr(M, LCtx, L), nullptr,
3567 } else {
3568 Bldr.takeNodes(I);
3569 evalLoad(Tmp, M, M, I, state, L);
3570 Bldr.addNodes(Tmp);
3571 }
3572 }
3573 }
3574
3575 getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, M, *this);
3576}
3577
3579 ExplodedNodeSet &Dst) {
3580 ExplodedNodeSet AfterPreSet;
3581 getCheckerManager().runCheckersForPreStmt(AfterPreSet, Pred, AE, *this);
3582
3583 // For now, treat all the arguments to C11 atomics as escaping.
3584 // FIXME: Ideally we should model the behavior of the atomics precisely here.
3585
3586 ExplodedNodeSet AfterInvalidateSet;
3587 StmtNodeBuilder Bldr(AfterPreSet, AfterInvalidateSet, *currBldrCtx);
3588
3589 for (const auto I : AfterPreSet) {
3590 ProgramStateRef State = I->getState();
3591 const LocationContext *LCtx = I->getLocationContext();
3592
3593 SmallVector<SVal, 8> ValuesToInvalidate;
3594 for (unsigned SI = 0, Count = AE->getNumSubExprs(); SI != Count; SI++) {
3595 const Expr *SubExpr = AE->getSubExprs()[SI];
3596 SVal SubExprVal = State->getSVal(SubExpr, LCtx);
3597 ValuesToInvalidate.push_back(SubExprVal);
3598 }
3599
3600 State = State->invalidateRegions(ValuesToInvalidate, getCFGElementRef(),
3601 currBldrCtx->blockCount(), LCtx,
3602 /*CausedByPointerEscape*/ true,
3603 /*Symbols=*/nullptr);
3604
3605 SVal ResultVal = UnknownVal();
3606 State = State->BindExpr(AE, LCtx, ResultVal);
3607 Bldr.generateNode(AE, I, State, nullptr,
3609 }
3610
3611 getCheckerManager().runCheckersForPostStmt(Dst, AfterInvalidateSet, AE, *this);
3612}
3613
3614// A value escapes in four possible cases:
3615// (1) We are binding to something that is not a memory region.
3616// (2) We are binding to a MemRegion that does not have stack storage.
3617// (3) We are binding to a top-level parameter region with a non-trivial
3618// destructor. We won't see the destructor during analysis, but it's there.
3619// (4) We are binding to a MemRegion with stack storage that the store
3620// does not understand.
3622 ProgramStateRef State, ArrayRef<std::pair<SVal, SVal>> LocAndVals,
3623 const LocationContext *LCtx, PointerEscapeKind Kind,
3624 const CallEvent *Call) {
3625 SmallVector<SVal, 8> Escaped;
3626 for (const std::pair<SVal, SVal> &LocAndVal : LocAndVals) {
3627 // Cases (1) and (2).
3628 const MemRegion *MR = LocAndVal.first.getAsRegion();
3629 const MemSpaceRegion *Space = MR ? MR->getMemorySpace(State) : nullptr;
3630 if (!MR || !isa<StackSpaceRegion, StaticGlobalSpaceRegion>(Space)) {
3631 Escaped.push_back(LocAndVal.second);
3632 continue;
3633 }
3634
3635 // Case (3).
3636 if (const auto *VR = dyn_cast<VarRegion>(MR->getBaseRegion()))
3637 if (isa<StackArgumentsSpaceRegion>(Space) &&
3638 VR->getStackFrame()->inTopFrame())
3639 if (const auto *RD = VR->getValueType()->getAsCXXRecordDecl())
3640 if (!RD->hasTrivialDestructor()) {
3641 Escaped.push_back(LocAndVal.second);
3642 continue;
3643 }
3644
3645 // Case (4): in order to test that, generate a new state with the binding
3646 // added. If it is the same state, then it escapes (since the store cannot
3647 // represent the binding).
3648 // Do this only if we know that the store is not supposed to generate the
3649 // same state.
3650 SVal StoredVal = State->getSVal(MR);
3651 if (StoredVal != LocAndVal.second)
3652 if (State ==
3653 (State->bindLoc(loc::MemRegionVal(MR), LocAndVal.second, LCtx)))
3654 Escaped.push_back(LocAndVal.second);
3655 }
3656
3657 if (Escaped.empty())
3658 return State;
3659
3660 return escapeValues(State, Escaped, Kind, Call);
3661}
3662
3665 SVal Val, const LocationContext *LCtx) {
3666 std::pair<SVal, SVal> LocAndVal(Loc, Val);
3667 return processPointerEscapedOnBind(State, LocAndVal, LCtx, PSK_EscapeOnBind,
3668 nullptr);
3669}
3670
3673 const InvalidatedSymbols *Invalidated,
3674 ArrayRef<const MemRegion *> ExplicitRegions,
3675 const CallEvent *Call,
3677 if (!Invalidated || Invalidated->empty())
3678 return State;
3679
3680 if (!Call)
3682 *Invalidated,
3683 nullptr,
3685 &ITraits);
3686
3687 // If the symbols were invalidated by a call, we want to find out which ones
3688 // were invalidated directly due to being arguments to the call.
3689 InvalidatedSymbols SymbolsDirectlyInvalidated;
3690 for (const auto I : ExplicitRegions) {
3691 if (const SymbolicRegion *R = I->StripCasts()->getAs<SymbolicRegion>())
3692 SymbolsDirectlyInvalidated.insert(R->getSymbol());
3693 }
3694
3695 InvalidatedSymbols SymbolsIndirectlyInvalidated;
3696 for (const auto &sym : *Invalidated) {
3697 if (SymbolsDirectlyInvalidated.count(sym))
3698 continue;
3699 SymbolsIndirectlyInvalidated.insert(sym);
3700 }
3701
3702 if (!SymbolsDirectlyInvalidated.empty())
3704 SymbolsDirectlyInvalidated, Call, PSK_DirectEscapeOnCall, &ITraits);
3705
3706 // Notify about the symbols that get indirectly invalidated by the call.
3707 if (!SymbolsIndirectlyInvalidated.empty())
3709 SymbolsIndirectlyInvalidated, Call, PSK_IndirectEscapeOnCall, &ITraits);
3710
3711 return State;
3712}
3713
3714/// evalBind - Handle the semantics of binding a value to a specific location.
3715/// This method is used by evalStore and (soon) VisitDeclStmt, and others.
3716void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
3717 ExplodedNode *Pred, SVal location, SVal Val,
3718 bool AtDeclInit, const ProgramPoint *PP) {
3719 const LocationContext *LC = Pred->getLocationContext();
3720 PostStmt PS(StoreE, LC);
3721 if (!PP)
3722 PP = &PS;
3723
3724 // Do a previsit of the bind.
3725 ExplodedNodeSet CheckedSet;
3726 getCheckerManager().runCheckersForBind(CheckedSet, Pred, location, Val,
3727 StoreE, AtDeclInit, *this, *PP);
3728
3729 StmtNodeBuilder Bldr(CheckedSet, Dst, *currBldrCtx);
3730
3731 // If the location is not a 'Loc', it will already be handled by
3732 // the checkers. There is nothing left to do.
3733 if (!isa<Loc>(location)) {
3734 const ProgramPoint L = PostStore(StoreE, LC, /*Loc*/nullptr,
3735 /*tag*/nullptr);
3736 ProgramStateRef state = Pred->getState();
3737 state = processPointerEscapedOnBind(state, location, Val, LC);
3738 Bldr.generateNode(L, state, Pred);
3739 return;
3740 }
3741
3742 for (const auto PredI : CheckedSet) {
3743 ProgramStateRef state = PredI->getState();
3744
3745 state = processPointerEscapedOnBind(state, location, Val, LC);
3746
3747 // When binding the value, pass on the hint that this is a initialization.
3748 // For initializations, we do not need to inform clients of region
3749 // changes.
3750 state = state->bindLoc(location.castAs<Loc>(), Val, LC,
3751 /* notifyChanges = */ !AtDeclInit);
3752
3753 const MemRegion *LocReg = nullptr;
3754 if (std::optional<loc::MemRegionVal> LocRegVal =
3755 location.getAs<loc::MemRegionVal>()) {
3756 LocReg = LocRegVal->getRegion();
3757 }
3758
3759 const ProgramPoint L = PostStore(StoreE, LC, LocReg, nullptr);
3760 Bldr.generateNode(L, state, PredI);
3761 }
3762}
3763
3764/// evalStore - Handle the semantics of a store via an assignment.
3765/// @param Dst The node set to store generated state nodes
3766/// @param AssignE The assignment expression if the store happens in an
3767/// assignment.
3768/// @param LocationE The location expression that is stored to.
3769/// @param state The current simulation state
3770/// @param location The location to store the value
3771/// @param Val The value to be stored
3773 const Expr *LocationE,
3774 ExplodedNode *Pred,
3775 ProgramStateRef state, SVal location, SVal Val,
3776 const ProgramPointTag *tag) {
3777 // Proceed with the store. We use AssignE as the anchor for the PostStore
3778 // ProgramPoint if it is non-NULL, and LocationE otherwise.
3779 const Expr *StoreE = AssignE ? AssignE : LocationE;
3780
3781 // Evaluate the location (checks for bad dereferences).
3782 ExplodedNodeSet Tmp;
3783 evalLocation(Tmp, AssignE, LocationE, Pred, state, location, false);
3784
3785 if (Tmp.empty())
3786 return;
3787
3788 if (location.isUndef())
3789 return;
3790
3791 for (const auto I : Tmp)
3792 evalBind(Dst, StoreE, I, location, Val, false);
3793}
3794
3796 const Expr *NodeEx,
3797 const Expr *BoundEx,
3798 ExplodedNode *Pred,
3799 ProgramStateRef state,
3800 SVal location,
3801 const ProgramPointTag *tag,
3802 QualType LoadTy) {
3803 assert(!isa<NonLoc>(location) && "location cannot be a NonLoc.");
3804 assert(NodeEx);
3805 assert(BoundEx);
3806 // Evaluate the location (checks for bad dereferences).
3807 ExplodedNodeSet Tmp;
3808 evalLocation(Tmp, NodeEx, BoundEx, Pred, state, location, true);
3809 if (Tmp.empty())
3810 return;
3811
3812 StmtNodeBuilder Bldr(Tmp, Dst, *currBldrCtx);
3813 if (location.isUndef())
3814 return;
3815
3816 // Proceed with the load.
3817 for (const auto I : Tmp) {
3818 state = I->getState();
3819 const LocationContext *LCtx = I->getLocationContext();
3820
3821 SVal V = UnknownVal();
3822 if (location.isValid()) {
3823 if (LoadTy.isNull())
3824 LoadTy = BoundEx->getType();
3825 V = state->getSVal(location.castAs<Loc>(), LoadTy);
3826 }
3827
3828 Bldr.generateNode(NodeEx, I, state->BindExpr(BoundEx, LCtx, V), tag,
3830 }
3831}
3832
3833void ExprEngine::evalLocation(ExplodedNodeSet &Dst,
3834 const Stmt *NodeEx,
3835 const Stmt *BoundEx,
3836 ExplodedNode *Pred,
3837 ProgramStateRef state,
3838 SVal location,
3839 bool isLoad) {
3840 StmtNodeBuilder BldrTop(Pred, Dst, *currBldrCtx);
3841 // Early checks for performance reason.
3842 if (location.isUnknown()) {
3843 return;
3844 }
3845
3846 ExplodedNodeSet Src;
3847 BldrTop.takeNodes(Pred);
3848 StmtNodeBuilder Bldr(Pred, Src, *currBldrCtx);
3849 if (Pred->getState() != state) {
3850 // Associate this new state with an ExplodedNode.
3851 // FIXME: If I pass null tag, the graph is incorrect, e.g for
3852 // int *p;
3853 // p = 0;
3854 // *p = 0xDEADBEEF;
3855 // "p = 0" is not noted as "Null pointer value stored to 'p'" but
3856 // instead "int *p" is noted as
3857 // "Variable 'p' initialized to a null pointer value"
3858
3859 static SimpleProgramPointTag tag(TagProviderName, "Location");
3860 Bldr.generateNode(NodeEx, Pred, state, &tag);
3861 }
3862 ExplodedNodeSet Tmp;
3863 getCheckerManager().runCheckersForLocation(Tmp, Src, location, isLoad,
3864 NodeEx, BoundEx, *this);
3865 BldrTop.addNodes(Tmp);
3866}
3867
3868std::pair<const ProgramPointTag *, const ProgramPointTag *>
3870 static SimpleProgramPointTag TrueTag(TagProviderName, "Eagerly Assume True"),
3871 FalseTag(TagProviderName, "Eagerly Assume False");
3872
3873 return std::make_pair(&TrueTag, &FalseTag);
3874}
3875
3876/// If the last EagerlyAssume attempt was successful (i.e. the true and false
3877/// cases were both feasible), this state trait stores the expression where it
3878/// happened; otherwise this holds nullptr.
3879REGISTER_TRAIT_WITH_PROGRAMSTATE(LastEagerlyAssumeExprIfSuccessful,
3880 const Expr *)
3881
3883 ExplodedNodeSet &Src,
3884 const Expr *Ex) {
3885 StmtNodeBuilder Bldr(Src, Dst, *currBldrCtx);
3886
3887 for (ExplodedNode *Pred : Src) {
3888 // Test if the previous node was as the same expression. This can happen
3889 // when the expression fails to evaluate to anything meaningful and
3890 // (as an optimization) we don't generate a node.
3891 ProgramPoint P = Pred->getLocation();
3892 if (!P.getAs<PostStmt>() || P.castAs<PostStmt>().getStmt() != Ex) {
3893 continue;
3894 }
3895
3896 ProgramStateRef State = Pred->getState();
3897 State = State->set<LastEagerlyAssumeExprIfSuccessful>(nullptr);
3898 SVal V = State->getSVal(Ex, Pred->getLocationContext());
3899 std::optional<nonloc::SymbolVal> SEV = V.getAs<nonloc::SymbolVal>();
3900 if (SEV && SEV->isExpression()) {
3901 const auto &[TrueTag, FalseTag] = getEagerlyAssumeBifurcationTags();
3902
3903 auto [StateTrue, StateFalse] = State->assume(*SEV);
3904
3905 if (StateTrue && StateFalse) {
3906 StateTrue = StateTrue->set<LastEagerlyAssumeExprIfSuccessful>(Ex);
3907 StateFalse = StateFalse->set<LastEagerlyAssumeExprIfSuccessful>(Ex);
3908 }
3909
3910 // First assume that the condition is true.
3911 if (StateTrue) {
3912 SVal Val = svalBuilder.makeIntVal(1U, Ex->getType());
3913 StateTrue = StateTrue->BindExpr(Ex, Pred->getLocationContext(), Val);
3914 Bldr.generateNode(Ex, Pred, StateTrue, TrueTag);
3915 }
3916
3917 // Next, assume that the condition is false.
3918 if (StateFalse) {
3919 SVal Val = svalBuilder.makeIntVal(0U, Ex->getType());
3920 StateFalse = StateFalse->BindExpr(Ex, Pred->getLocationContext(), Val);
3921 Bldr.generateNode(Ex, Pred, StateFalse, FalseTag);
3922 }
3923 }
3924 }
3925}
3926
3928 const Expr *Ex) const {
3929 return Ex && State->get<LastEagerlyAssumeExprIfSuccessful>() == Ex;
3930}
3931
3933 ExplodedNodeSet &Dst) {
3934 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
3935 // We have processed both the inputs and the outputs. All of the outputs
3936 // should evaluate to Locs. Nuke all of their values.
3937
3938 // FIXME: Some day in the future it would be nice to allow a "plug-in"
3939 // which interprets the inline asm and stores proper results in the
3940 // outputs.
3941
3942 ProgramStateRef state = Pred->getState();
3943
3944 for (const Expr *O : A->outputs()) {
3945 SVal X = state->getSVal(O, Pred->getLocationContext());
3946 assert(!isa<NonLoc>(X)); // Should be an Lval, or unknown, undef.
3947
3948 if (std::optional<Loc> LV = X.getAs<Loc>())
3949 state = state->invalidateRegions(*LV, getCFGElementRef(),
3950 currBldrCtx->blockCount(),
3951 Pred->getLocationContext(),
3952 /*CausedByPointerEscape=*/true);
3953 }
3954
3955 // Do not reason about locations passed inside inline assembly.
3956 for (const Expr *I : A->inputs()) {
3957 SVal X = state->getSVal(I, Pred->getLocationContext());
3958
3959 if (std::optional<Loc> LV = X.getAs<Loc>())
3960 state = state->invalidateRegions(*LV, getCFGElementRef(),
3961 currBldrCtx->blockCount(),
3962 Pred->getLocationContext(),
3963 /*CausedByPointerEscape=*/true);
3964 }
3965
3966 Bldr.generateNode(A, Pred, state);
3967}
3968
3970 ExplodedNodeSet &Dst) {
3971 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
3972 Bldr.generateNode(A, Pred, Pred->getState());
3973}
3974
3975//===----------------------------------------------------------------------===//
3976// Visualization.
3977//===----------------------------------------------------------------------===//
3978
3979namespace llvm {
3980
3981template<>
3982struct DOTGraphTraits<ExplodedGraph*> : public DefaultDOTGraphTraits {
3983 DOTGraphTraits (bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
3984
3985 static bool nodeHasBugReport(const ExplodedNode *N) {
3986 BugReporter &BR = static_cast<ExprEngine &>(
3987 N->getState()->getStateManager().getOwningEngine()).getBugReporter();
3988
3989 for (const auto &Class : BR.equivalenceClasses()) {
3990 for (const auto &Report : Class.getReports()) {
3991 const auto *PR = dyn_cast<PathSensitiveBugReport>(Report.get());
3992 if (!PR)
3993 continue;
3994 const ExplodedNode *EN = PR->getErrorNode();
3995 if (EN->getState() == N->getState() &&
3996 EN->getLocation() == N->getLocation())
3997 return true;
3998 }
3999 }
4000 return false;
4001 }
4002
4003 /// \p PreCallback: callback before break.
4004 /// \p PostCallback: callback after break.
4005 /// \p Stop: stop iteration if returns @c true
4006 /// \return Whether @c Stop ever returned @c true.
4008 const ExplodedNode *N,
4009 llvm::function_ref<void(const ExplodedNode *)> PreCallback,
4010 llvm::function_ref<void(const ExplodedNode *)> PostCallback,
4011 llvm::function_ref<bool(const ExplodedNode *)> Stop) {
4012 while (true) {
4013 PreCallback(N);
4014 if (Stop(N))
4015 return true;
4016
4017 if (N->succ_size() != 1 || !isNodeHidden(N->getFirstSucc(), nullptr))
4018 break;
4019 PostCallback(N);
4020
4021 N = N->getFirstSucc();
4022 }
4023 return false;
4024 }
4025
4026 static bool isNodeHidden(const ExplodedNode *N, const ExplodedGraph *G) {
4027 return N->isTrivial();
4028 }
4029
4030 static std::string getNodeLabel(const ExplodedNode *N, ExplodedGraph *G){
4031 std::string Buf;
4032 llvm::raw_string_ostream Out(Buf);
4033
4034 const bool IsDot = true;
4035 const unsigned int Space = 1;
4036 ProgramStateRef State = N->getState();
4037
4038 Out << "{ \"state_id\": " << State->getID()
4039 << ",\\l";
4040
4041 Indent(Out, Space, IsDot) << "\"program_points\": [\\l";
4042
4043 // Dump program point for all the previously skipped nodes.
4044 traverseHiddenNodes(
4045 N,
4046 [&](const ExplodedNode *OtherNode) {
4047 Indent(Out, Space + 1, IsDot) << "{ ";
4048 OtherNode->getLocation().printJson(Out, /*NL=*/"\\l");
4049 Out << ", \"tag\": ";
4050 if (const ProgramPointTag *Tag = OtherNode->getLocation().getTag())
4051 Out << '\"' << Tag->getDebugTag() << '\"';
4052 else
4053 Out << "null";
4054 Out << ", \"node_id\": " << OtherNode->getID() <<
4055 ", \"is_sink\": " << OtherNode->isSink() <<
4056 ", \"has_report\": " << nodeHasBugReport(OtherNode) << " }";
4057 },
4058 // Adds a comma and a new-line between each program point.
4059 [&](const ExplodedNode *) { Out << ",\\l"; },
4060 [&](const ExplodedNode *) { return false; });
4061
4062 Out << "\\l"; // Adds a new-line to the last program point.
4063 Indent(Out, Space, IsDot) << "],\\l";
4064
4065 State->printDOT(Out, N->getLocationContext(), Space);
4066
4067 Out << "\\l}\\l";
4068 return Buf;
4069 }
4070};
4071
4072} // namespace llvm
4073
4074void ExprEngine::ViewGraph(bool trim) {
4075 std::string Filename = DumpGraph(trim);
4076 llvm::DisplayGraph(Filename, false, llvm::GraphProgram::DOT);
4077}
4078
4080 std::string Filename = DumpGraph(Nodes);
4081 llvm::DisplayGraph(Filename, false, llvm::GraphProgram::DOT);
4082}
4083
4084std::string ExprEngine::DumpGraph(bool trim, StringRef Filename) {
4085 if (trim) {
4086 std::vector<const ExplodedNode *> Src;
4087
4088 // Iterate through the reports and get their nodes.
4089 for (const auto &Class : BR.equivalenceClasses()) {
4090 const auto *R =
4091 dyn_cast<PathSensitiveBugReport>(Class.getReports()[0].get());
4092 if (!R)
4093 continue;
4094 const auto *N = const_cast<ExplodedNode *>(R->getErrorNode());
4095 Src.push_back(N);
4096 }
4097 return DumpGraph(Src, Filename);
4098 }
4099
4100 return llvm::WriteGraph(&G, "ExprEngine", /*ShortNames=*/false,
4101 /*Title=*/"Exploded Graph",
4102 /*Filename=*/std::string(Filename));
4103}
4104
4106 StringRef Filename) {
4107 std::unique_ptr<ExplodedGraph> TrimmedG(G.trim(Nodes));
4108
4109 if (!TrimmedG) {
4110 llvm::errs() << "warning: Trimmed ExplodedGraph is empty.\n";
4111 return "";
4112 }
4113
4114 return llvm::WriteGraph(TrimmedG.get(), "TrimmedExprEngine",
4115 /*ShortNames=*/false,
4116 /*Title=*/"Trimmed Exploded Graph",
4117 /*Filename=*/std::string(Filename));
4118}
4119
4121 static int index = 0;
4122 return &index;
4123}
4124
4125void ExprEngine::anchor() { }
4126
4128 bool IsTransparent, ExplodedNode *Pred,
4129 ExplodedNodeSet &Dst) {
4130 assert((isa<InitListExpr, CXXParenListInitExpr>(E)));
4131
4132 const LocationContext *LC = Pred->getLocationContext();
4133
4134 StmtNodeBuilder B(Pred, Dst, *currBldrCtx);
4135 ProgramStateRef S = Pred->getState();
4137
4138 bool IsCompound = T->isArrayType() || T->isRecordType() ||
4140
4141 if (Args.size() > 1 || (E->isPRValue() && IsCompound && !IsTransparent)) {
4142 llvm::ImmutableList<SVal> ArgList = getBasicVals().getEmptySValList();
4143 for (Expr *E : llvm::reverse(Args))
4144 ArgList = getBasicVals().prependSVal(S->getSVal(E, LC), ArgList);
4145
4146 B.generateNode(E, Pred,
4147 S->BindExpr(E, LC, svalBuilder.makeCompoundVal(T, ArgList)));
4148 } else {
4149 B.generateNode(E, Pred,
4150 S->BindExpr(E, LC,
4151 Args.size() == 0
4152 ? getSValBuilder().makeZeroVal(T)
4153 : S->getSVal(Args.front(), LC)));
4154 }
4155}
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3597
BoundNodesTreeBuilder Nodes
DynTypedNode Node
StringRef P
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
static const MemRegion * getRegion(const CallEvent &Call, const MutexDescriptor &Descriptor, bool IsLock)
const Decl * D
Expr * E
static Decl::Kind getKind(const Decl *D)
Definition: DeclBase.cpp:1192
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)
std::pair< const ObjCForCollectionStmt *, const LocationContext * > ObjCForLctxPair
static SVal RecoverCastedSymbol(ProgramStateRef state, const Stmt *Condition, const LocationContext *LCtx, ASTContext &Ctx)
RecoverCastedSymbol - A helper function for ProcessBranch that is used to try to recover some path-se...
static void printObjectsUnderConstructionJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
Definition: ExprEngine.cpp:686
static void printIndicesOfElementsToConstructJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
Definition: ExprEngine.cpp:732
static void printStateTraitWithLocationContextJson(raw_ostream &Out, ProgramStateRef State, const LocationContext *LCtx, const char *NL, unsigned int Space, bool IsDot, const char *jsonPropertyName, Printer printer, Args &&...args)
A helper function to generalize program state trait printing.
Definition: ExprEngine.cpp:911
static void printPendingArrayDestructionsJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
Definition: ExprEngine.cpp:855
static bool shouldRemoveDeadBindings(AnalysisManager &AMgr, const Stmt *S, const ExplodedNode *Pred, const LocationContext *LC)
static const Stmt * ResolveCondition(const Stmt *Condition, const CFGBlock *B)
REGISTER_TRAIT_WITH_PROGRAMSTATE(ObjectsUnderConstruction, ObjectsUnderConstructionMap) typedef llvm REGISTER_TRAIT_WITH_PROGRAMSTATE(IndexOfElementToConstruct, IndexOfElementToConstructMap) typedef llvm typedef llvm::ImmutableMap< const LocationContext *, unsigned > PendingArrayDestructionMap
Definition: ExprEngine.cpp:200
static void printPendingInitLoopJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
Definition: ExprEngine.cpp:794
llvm::ImmutableMap< ConstructedObjectKey, SVal > ObjectsUnderConstructionMap
Definition: ExprEngine.cpp:187
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.
StringRef Filename
Definition: Format.cpp:3177
bool PostVisit
Definition: HTMLLogger.cpp:154
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
#define X(type, name)
Definition: Value.h:145
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.
__device__ int
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
SourceManager & getSourceManager()
Definition: ASTContext.h:801
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CanQualType CharTy
Definition: ASTContext.h:1224
const clang::PrintingPolicy & getPrintingPolicy() const
Definition: ASTContext.h:793
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2625
ASTContext & getASTContext() const
Stores options for the analyzer from the command line.
unsigned NoRetryExhausted
Do not re-analyze paths leading to exhausted nodes with a different strategy.
unsigned maxBlockVisitOnPath
The maximum number of times the analyzer visits a block.
AnalysisPurgeMode AnalysisPurgeOpt
Represents a loop initializing the elements of an array.
Definition: Expr.h:5904
OpaqueValueExpr * getCommonExpr() const
Get the common subexpression shared by all initializations (the source array).
Definition: Expr.h:5919
Expr * getSubExpr() const
Get the initializer to use for each array element.
Definition: Expr.h:5924
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2723
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: TypeBase.h:3738
outputs_range outputs()
Definition: Stmt.h:3369
inputs_range inputs()
Definition: Stmt.h:3340
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
Definition: Expr.h:6816
Expr ** getSubExprs()
Definition: Expr.h:6891
static unsigned getNumSubExprs(AtomicOp Op)
Determine the number of arguments the specified atomic builtin should have.
Definition: Expr.cpp:5112
const CFGBlock * getPreviousBlock() const
Definition: ProgramPoint.h:233
const CFGBlock * getBlock() const
Definition: ProgramPoint.h:237
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
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:1111
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
@ LifetimeEnds
Definition: CFG.h:63
@ CXXRecordTypedCall
Definition: CFG.h:68
@ AutomaticObjectDtor
Definition: CFG.h:72
@ TemporaryDtor
Definition: CFG.h:76
@ NewAllocator
Definition: CFG.h:62
Represents C++ object destructor implicitly generated by compiler on various occasions.
Definition: CFG.h:367
const CXXDestructorDecl * getDestructorDecl(ASTContext &astContext) const
Definition: CFG.cpp:5398
Represents C++ base or member initializer from constructor's initialization list.
Definition: CFG.h:228
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
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
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:1494
Represents a call to a C++ constructor.
Definition: ExprCXX.h:1549
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:2620
bool isArrayForm() const
Definition: ExprCXX.h:2646
SourceLocation getBeginLoc() const
Definition: ExprCXX.h:2670
Expr * getArgument()
Definition: ExprCXX.h:2661
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:2349
Represents a list-initialization with parenthesis.
Definition: ExprCXX.h:5135
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.
Definition: ProgramPoint.h:638
CaseStmt - Represent a case statement.
Definition: Stmt.h:1920
Expr * getLHS()
Definition: Stmt.h:2003
Expr * getRHS()
Definition: Stmt.h:2015
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:1272
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1611
const Decl * getSingleDecl() const
Definition: Stmt.h:1626
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:431
Kind getKind() const
Definition: DeclBase.h:442
This is a meta program point, which should be skipped by all the diagnostic reasoning etc.
Definition: ProgramPoint.h:740
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:80
bool isGLValue() const
Definition: Expr.h:287
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3073
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3061
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3069
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:3157
This represents a GCC inline-assembly statement extension.
Definition: Stmt.h:3395
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:5235
Represents the declaration of a label.
Definition: Decl.h:523
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
const Decl * getDecl() const
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
const LocationContext * getParent() const
It might return null.
const StackFrameContext * getStackFrame() const
virtual bool inTopFrame() const
void printJson(raw_ostream &Out, const char *NL="\n", unsigned int Space=0, bool IsDot=false, std::function< void(const LocationContext *)> printMoreInfoPerContext=[](const LocationContext *) {}) const
Prints out the call stack in json format.
Represents a point when we exit a loop.
Definition: ProgramPoint.h:721
This represents a Microsoft inline-assembly statement extension.
Definition: Stmt.h:3614
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3300
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition: Expr.h:3383
Expr * getBase() const
Definition: Expr.h:3377
This represents a decl that may have a name.
Definition: Decl.h:273
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:339
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:1230
bool isConsumedExpr(Expr *E) const
Definition: ParentMap.cpp:181
Represents a parameter to a function.
Definition: Decl.h:1789
Represents a program point just after an implicit call event.
Definition: ProgramPoint.h:607
Represents a program point after a store evaluation.
Definition: ProgramPoint.h:436
Represents a program point just before an implicit call event.
Definition: ProgramPoint.h:589
If a crash happens while one of these objects are live, the message is printed out along with the spe...
ProgramPoints can be "tagged" as representing points specific to a given analysis entity.
Definition: ProgramPoint.h:38
const ProgramPointTag * getTag() const
Definition: ProgramPoint.h:179
bool isPurgeKind()
Is this a program point corresponding to purge/removal of dead symbols and bindings.
Definition: ProgramPoint.h:173
void printJson(llvm::raw_ostream &Out, const char *NL="\n") const
const StackFrameContext * getStackFrame() const
Definition: ProgramPoint.h:185
std::optional< T > getAs() const
Convert to the specified ProgramPoint type, returning std::nullopt if this ProgramPoint is not of the...
Definition: ProgramPoint.h:153
const LocationContext * getLocationContext() const
Definition: ProgramPoint.h:181
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:8395
SplitQualType split() const
Divides a QualType into its unqualified type and a set of local qualifiers.
Definition: TypeBase.h:8364
bool isCForbiddenLValueType() const
Determine whether expressions of the given type are forbidden from being lvalues in C.
Definition: TypeBase.h:8535
std::string getAsString() const
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Definition: Stmt.h:3160
std::string printToString(const SourceManager &SM) const
It represents a stack frame of the call stack (based on CallEvent).
const Stmt * getCallSite() const
const CFGBlock * getCallSiteBlock() const
bool inTopFrame() const override
const Stmt * getStmt() const
Definition: ProgramPoint.h:284
Stmt - This represents one statement.
Definition: Stmt.h:85
@ NoStmtClass
Definition: Stmt.h:88
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:334
const char * getStmtClassName() const
Definition: Stmt.cpp:87
int64_t getID(const ASTContext &Context) const
Definition: Stmt.cpp:370
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:346
SwitchStmt - This represents a 'switch' stmt.
Definition: Stmt.h:2509
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:2669
Expr * getCond()
Definition: Stmt.h:2572
bool isVoidType() const
Definition: TypeBase.h:8936
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:8679
bool isReferenceType() const
Definition: TypeBase.h:8604
bool isEnumeralType() const
Definition: TypeBase.h:8711
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: TypeBase.h:9054
bool isAnyComplexType() const
Definition: TypeBase.h:8715
bool isVectorType() const
Definition: TypeBase.h:8719
bool isRecordType() const
Definition: TypeBase.h:8707
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:711
QualType getType() const
Definition: Decl.h:722
Represents a variable declaration or definition.
Definition: Decl.h:925
This class is used for tools that requires cross translation unit capability.
const LangOptions & getLangOpts() const
ASTContext & getASTContext() override
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)
Definition: CoreEngine.cpp:718
BugReporter is a utility class for generating PathDiagnostics for analysis.
Definition: BugReporter.h:586
llvm::iterator_range< EQClasses_iterator > equivalenceClasses()
Definition: BugReporter.h:619
Represents an abstract call to a function or method along a particular path.
Definition: CallEvent.h:153
static bool isCallStmt(const Stmt *S)
Returns true if this is a statement is a function or method call of some kind.
Definition: CallEvent.cpp:346
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 addAbortedBlock(const ExplodedNode *node, const CFGBlock *block)
Inform the CoreEngine that a basic block was aborted because it could not be completely analyzed.
Definition: CoreEngine.h:168
void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx)
Enqueue a single node created as a result of statement processing.
Definition: CoreEngine.cpp:573
void enqueueEndOfFunction(ExplodedNodeSet &Set, const ReturnStmt *RS)
enqueue the nodes corresponding to the end of function onto the end of path / work list.
Definition: CoreEngine.cpp:672
void enqueue(ExplodedNodeSet &Set)
Enqueue the given set of nodes onto the work list.
Definition: CoreEngine.cpp:661
std::unique_ptr< ExplodedGraph > trim(ArrayRef< const NodeTy * > Nodes, InterExplodedGraphMap *ForwardMap=nullptr, InterExplodedGraphMap *InverseMap=nullptr) const
Creates a trimmed version of the graph that only contains paths leading to the given nodes.
void enableNodeReclamation(unsigned Interval)
Enable tracking of recently allocated nodes for potential reclamation when calling reclaimRecentlyAll...
void reclaimRecentlyAllocatedNodes()
Reclaim "uninteresting" nodes created since the last time this method was called.
ExplodedNode * getNode(const ProgramPoint &L, ProgramStateRef State, bool IsSink=false, bool *IsNew=nullptr)
Retrieve the node associated with a (Location, State) pair, where the 'Location' is a ProgramPoint in...
ExplodedNode * getRoot() const
Get the root node of the graph.
void insert(const ExplodedNodeSet &S)
void Add(ExplodedNode *N)
const ProgramStateRef & getState() const
pred_iterator pred_begin()
bool isTrivial() const
The node is trivial if it has only one successor, only one predecessor, it's predecessor has only one...
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
void addPredecessor(ExplodedNode *V, ExplodedGraph &G)
addPredeccessor - Adds a predecessor to the current node, and in tandem add this node as a successor ...
ExplodedNode * getFirstSucc()
const StackFrameContext * getStackFrame() const
const LocationContext * getLocationContext() const
unsigned succ_size() const
void processEndOfFunction(NodeBuilderContext &BC, ExplodedNode *Pred, const ReturnStmt *RS=nullptr)
Called by CoreEngine.
void VisitBinaryOperator(const BinaryOperator *B, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitBinaryOperator - Transfer function logic for binary operators.
Definition: ExprEngineC.cpp:41
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.
Definition: ExprEngine.cpp:245
void VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *DR, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Transfer function logic for computing the lvalue of an Objective-C ivar.
static bool hasMoreIteration(ProgramStateRef State, const ObjCForCollectionStmt *O, const LocationContext *LC)
void VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitDeclStmt - Transfer function logic for DeclStmts.
void VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitMSAsmStmt - Transfer function logic for MS inline asm.
static std::optional< SVal > getObjectUnderConstruction(ProgramStateRef State, const ConstructionContextItem &Item, const LocationContext *LC)
By looking at a certain item that may be potentially part of an object's ConstructionContext,...
Definition: ExprEngine.cpp:604
std::string DumpGraph(bool trim=false, StringRef Filename="")
Dump graph to the specified filename.
void printJson(raw_ostream &Out, ProgramStateRef State, const LocationContext *LCtx, const char *NL, unsigned int Space, bool IsDot) const
printJson - Called by ProgramStateManager to print checker-specific data.
Definition: ExprEngine.cpp:940
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...
Definition: ExprEngine.cpp:668
static std::optional< unsigned > getIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E, const LocationContext *LCtx)
Retreives which element is being constructed in a non-POD type array.
Definition: ExprEngine.cpp:514
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.
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.
Definition: ExprEngine.cpp:674
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)
Definition: ExprEngine.cpp:222
void ViewGraph(bool trim=false)
Visualize the ExplodedGraph created by executing the simulation.
static std::optional< unsigned > getPendingArrayDestruction(ProgramStateRef State, const LocationContext *LCtx)
Retreives which element is being destructed in a non-POD type array.
Definition: ExprEngine.cpp:533
ProgramStateRef notifyCheckersOfPointerEscape(ProgramStateRef State, const InvalidatedSymbols *Invalidated, ArrayRef< const MemRegion * > ExplicitRegions, const CallEvent *Call, RegionAndSymbolInvalidationTraits &ITraits)
Call PointerEscape callback when a value escapes as a result of region invalidation.
static const ProgramPointTag * cleanupNodeTag()
A tag to track convenience transitions, which can be removed at cleanup.
void processCFGElement(const CFGElement E, ExplodedNode *Pred, unsigned StmtIdx, NodeBuilderContext *Ctx)
processCFGElement - Called by CoreEngine.
Definition: ExprEngine.cpp:967
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.
Definition: ExprEngine.cpp:961
CheckerManager & getCheckerManager() const
Definition: ExprEngine.h:205
void VisitAtomicExpr(const AtomicExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitAtomicExpr - Transfer function for builtin atomic expressions.
void ProcessMemberDtor(const CFGMemberDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitMemberExpr - Transfer function for member expressions.
void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
bool didEagerlyAssumeBifurcateAt(ProgramStateRef State, const Expr *Ex) const
ConstraintManager & getConstraintManager()
Definition: ExprEngine.h: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
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 std::optional< unsigned > getPendingInitLoop(ProgramStateRef State, const CXXConstructExpr *E, const LocationContext *LCtx)
Retreives the size of the array in the pending ArrayInitLoopExpr.
Definition: ExprEngine.cpp:487
void ProcessNewAllocator(const CXXNewExpr *NE, ExplodedNode *Pred)
void markShouldNotInline(const Decl *D)
const Expr * getTarget() const
Definition: CoreEngine.h:507
const LocationContext * getLocationContext() const
Definition: CoreEngine.h:511
ProgramStateRef getState() const
Definition: CoreEngine.h:509
ExplodedNode * generateNode(const iterator &I, ProgramStateRef State, bool isSink=false)
Definition: CoreEngine.cpp:733
static bool isLocType(QualType T)
Definition: SVals.h:262
const CXXLifetimeExtendedObjectRegion * getCXXLifetimeExtendedObjectRegion(Expr const *Ex, ValueDecl const *VD, LocationContext const *LC)
Create a CXXLifetimeExtendedObjectRegion for temporaries which are lifetime-extended by local referen...
Definition: MemRegion.cpp:1292
const CXXTempObjectRegion * getCXXTempObjectRegion(Expr const *Ex, LocationContext const *LC)
Definition: MemRegion.cpp:1284
const CXXLifetimeExtendedObjectRegion * getCXXStaticLifetimeExtendedObjectRegion(const Expr *Ex, ValueDecl const *VD)
Create a CXXLifetimeExtendedObjectRegion for temporaries which are lifetime-extended by static refere...
Definition: MemRegion.cpp:1301
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.
Definition: MemRegion.cpp:1397
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
Definition: MemRegion.cpp:1422
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.
ProgramStateRef removeDeadBindingsFromEnvironmentAndStore(ProgramStateRef St, const StackFrameContext *LCtx, SymbolReaper &SymReaper)
bool haveEqualStores(ProgramStateRef S1, ProgramStateRef S2) const
Definition: ProgramState.h:615
bool haveEqualEnvironments(ProgramStateRef S1, ProgramStateRef S2) const
Definition: ProgramState.h:611
ProgramStateRef getPersistentStateWithGDM(ProgramStateRef FromState, ProgramStateRef GDMState)
MemRegionManager & getRegionManager()
Definition: ProgramState.h:565
ProgramStateRef getInitialState(const LocationContext *InitLoc)
Information about invalidation for a particular region/symbol.
Definition: MemRegion.h:1657
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
Definition: SValBuilder.cpp:62
NonLoc makeCompoundVal(QualType type, llvm::ImmutableList< SVal > vals)
Definition: SValBuilder.h:249
DefinedSVal getFunctionPointer(const FunctionDecl *func)
NonLoc makeIntValWithWidth(QualType ptrType, uint64_t integer)
Definition: SValBuilder.h:312
NonLoc makeArrayIndex(uint64_t idx)
Definition: SValBuilder.h:271
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
Definition: SValBuilder.h:277
QualType getConditionType() const
Definition: SValBuilder.h:154
loc::MemRegionVal getCXXThis(const CXXMethodDecl *D, const StackFrameContext *SFC)
Return a memory region for the 'this' object reference.
std::optional< SVal > getConstantVal(const Expr *E)
Returns the value of E, if it can be determined in a non-path-sensitive manner.
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 llvm::APSInt * getAsInteger() const
If this SVal is loc::ConcreteInt or nonloc::ConcreteInt, return a pointer to APSInt which is held in ...
Definition: SVals.cpp:111
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)
Definition: CoreEngine.cpp:767
ExplodedNode * generateCaseStmtNode(const iterator &I, ProgramStateRef State)
Definition: CoreEngine.cpp:752
const LocationContext * getLocationContext() const
Definition: CoreEngine.h:565
const SwitchStmt * getSwitch() const
Definition: CoreEngine.h:551
Symbolic value.
Definition: SymExpr.h:32
A class responsible for cleaning up unused symbols.
void markLive(SymbolRef sym)
Unconditionally marks a symbol as live.
SymbolicRegion - A special, "non-concrete" region.
Definition: MemRegion.h:808
TypedValueRegion - An abstract class representing regions having a typed value.
Definition: MemRegion.h:563
Represents symbolic expression that isn't a location.
Definition: SVals.h:279
#define bool
Definition: gpuintrin.h:32
Definition: ARM.cpp:1134
const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl
Matches variable declarations.
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
llvm::DenseSet< const Decl * > SetOfConstDecls
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
@ PSK_DirectEscapeOnCall
The pointer has been passed to a function call directly.
@ PSK_EscapeOnBind
A pointer escapes due to binding its value to a location that the analyzer cannot track.
@ PSK_IndirectEscapeOnCall
The pointer has been passed to a function indirectly.
@ PSK_EscapeOther
The reason for pointer escape is unknown.
DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State, const MemRegion *MR, SValBuilder &SVB, QualType Ty)
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
ProgramStateRef processLoopEnd(const Stmt *LoopStmt, ProgramStateRef State)
Updates the given ProgramState.
llvm::DenseSet< SymbolRef > InvalidatedSymbols
Definition: Store.h:51
bool isUnrolledState(ProgramStateRef State)
Returns if the given State indicates that is inside a completely unrolled loop.
ProgramStateRef 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:1274
The JSON file list parser is used to communicate input to InstallAPI.
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
Definition: CallGraph.h:204
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
StorageDuration
The storage duration for an object (per C++ [basic.stc]).
Definition: Specifiers.h: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.
const FunctionProtoType * T
@ Class
The "class" keyword introduces the elaborated-type-specifier.
Expr * extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE)
Definition: CFG.cpp:1448
@ CXXThis
Parameter for C++ 'this' argument.
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30
Describes how types, statements, expressions, and declarations should be printed.
Definition: PrettyPrinter.h:57
An adjustment to be made to the temporary created when emitting a reference binding,...
Definition: Expr.h:68
Hints for figuring out of a call should be inlined during evalCall().
Definition: ExprEngine.h:97
bool IsTemporaryCtorOrDtor
This call is a constructor or a destructor of a temporary value.
Definition: ExprEngine.h:107
bool IsArrayCtorOrDtor
This call is a constructor or a destructor for a single element within an array, a part of array cons...
Definition: ExprEngine.h:104
Traits for storing the call processing policy inside GDM.
Definition: ExprEngine.h:1026
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)