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