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