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