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