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