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