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