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