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