1 //===- ExprEngine.cpp - Path-Sensitive Expression-Level Dataflow ----------===//
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
7 //===----------------------------------------------------------------------===//
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.
13 //===----------------------------------------------------------------------===//
15 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
16 #include "PrettyStackTraceLocationContext.h"
17 #include "clang/AST/ASTContext.h"
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"
26 #include "clang/AST/PrettyPrinter.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"
31 #include "clang/Analysis/AnalysisDeclContext.h"
32 #include "clang/Analysis/CFG.h"
33 #include "clang/Analysis/ConstructionContext.h"
34 #include "clang/Analysis/ProgramPoint.h"
35 #include "clang/Basic/IdentifierTable.h"
36 #include "clang/Basic/JsonSupport.h"
37 #include "clang/Basic/LLVM.h"
38 #include "clang/Basic/LangOptions.h"
39 #include "clang/Basic/PrettyStackTrace.h"
40 #include "clang/Basic/SourceLocation.h"
41 #include "clang/Basic/SourceManager.h"
42 #include "clang/Basic/Specifiers.h"
43 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
44 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
45 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
46 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
47 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
48 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
49 #include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
50 #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
51 #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
52 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
53 #include "clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h"
54 #include "clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h"
55 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
56 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
57 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
58 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
59 #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
60 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
61 #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
62 #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
63 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.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/ADT/Statistic.h"
71 #include "llvm/Support/Casting.h"
72 #include "llvm/Support/Compiler.h"
73 #include "llvm/Support/DOTGraphTraits.h"
74 #include "llvm/Support/ErrorHandling.h"
75 #include "llvm/Support/GraphWriter.h"
76 #include "llvm/Support/SaveAndRestore.h"
77 #include "llvm/Support/raw_ostream.h"
87 using namespace clang
;
90 #define DEBUG_TYPE "ExprEngine"
92 STATISTIC(NumRemoveDeadBindings
,
93 "The # of times RemoveDeadBindings is called");
94 STATISTIC(NumMaxBlockCountReached
,
95 "The # of aborted paths due to reaching the maximum block count in "
96 "a top level function");
97 STATISTIC(NumMaxBlockCountReachedInInlined
,
98 "The # of aborted paths due to reaching the maximum block count in "
99 "an inlined function");
100 STATISTIC(NumTimesRetriedWithoutInlining
,
101 "The # of times we re-evaluated a call without inlining");
103 //===----------------------------------------------------------------------===//
104 // Internal program state traits.
105 //===----------------------------------------------------------------------===//
109 // When modeling a C++ constructor, for a variety of reasons we need to track
110 // the location of the object for the duration of its ConstructionContext.
111 // ObjectsUnderConstruction maps statements within the construction context
112 // to the object's location, so that on every such statement the location
113 // could have been retrieved.
115 /// ConstructedObjectKey is used for being able to find the path-sensitive
116 /// memory region of a freshly constructed object while modeling the AST node
117 /// that syntactically represents the object that is being constructed.
118 /// Semantics of such nodes may sometimes require access to the region that's
119 /// not otherwise present in the program state, or to the very fact that
120 /// the construction context was present and contained references to these
122 class ConstructedObjectKey
{
123 using ConstructedObjectKeyImpl
=
124 std::pair
<ConstructionContextItem
, const LocationContext
*>;
125 const ConstructedObjectKeyImpl Impl
;
128 explicit ConstructedObjectKey(const ConstructionContextItem
&Item
,
129 const LocationContext
*LC
)
132 const ConstructionContextItem
&getItem() const { return Impl
.first
; }
133 const LocationContext
*getLocationContext() const { return Impl
.second
; }
135 ASTContext
&getASTContext() const {
136 return getLocationContext()->getDecl()->getASTContext();
139 void printJson(llvm::raw_ostream
&Out
, PrinterHelper
*Helper
,
140 PrintingPolicy
&PP
) const {
141 const Stmt
*S
= getItem().getStmtOrNull();
142 const CXXCtorInitializer
*I
= nullptr;
144 I
= getItem().getCXXCtorInitializer();
147 Out
<< "\"stmt_id\": " << S
->getID(getASTContext());
149 Out
<< "\"init_id\": " << I
->getID(getASTContext());
152 Out
<< ", \"kind\": \"" << getItem().getKindAsString()
153 << "\", \"argument_index\": ";
155 if (getItem().getKind() == ConstructionContextItem::ArgumentKind
)
156 Out
<< getItem().getIndex();
161 Out
<< ", \"pretty\": ";
164 S
->printJson(Out
, Helper
, PP
, /*AddQuotes=*/true);
166 Out
<< '\"' << I
->getAnyMember()->getDeclName() << '\"';
170 void Profile(llvm::FoldingSetNodeID
&ID
) const {
172 ID
.AddPointer(Impl
.second
);
175 bool operator==(const ConstructedObjectKey
&RHS
) const {
176 return Impl
== RHS
.Impl
;
179 bool operator<(const ConstructedObjectKey
&RHS
) const {
180 return Impl
< RHS
.Impl
;
185 typedef llvm::ImmutableMap
<ConstructedObjectKey
, SVal
>
186 ObjectsUnderConstructionMap
;
187 REGISTER_TRAIT_WITH_PROGRAMSTATE(ObjectsUnderConstruction
,
188 ObjectsUnderConstructionMap
)
190 // This trait is responsible for storing the index of the element that is to be
191 // constructed in the next iteration. As a result a CXXConstructExpr is only
192 // stored if it is array type. Also the index is the index of the continuous
193 // memory region, which is important for multi-dimensional arrays. E.g:: int
194 // arr[2][2]; assume arr[1][1] will be the next element under construction, so
196 typedef llvm::ImmutableMap
<
197 std::pair
<const CXXConstructExpr
*, const LocationContext
*>, unsigned>
198 IndexOfElementToConstructMap
;
199 REGISTER_TRAIT_WITH_PROGRAMSTATE(IndexOfElementToConstruct
,
200 IndexOfElementToConstructMap
)
202 // This trait is responsible for holding our pending ArrayInitLoopExprs.
203 // It pairs the LocationContext and the initializer CXXConstructExpr with
204 // the size of the array that's being copy initialized.
205 typedef llvm::ImmutableMap
<
206 std::pair
<const CXXConstructExpr
*, const LocationContext
*>, unsigned>
208 REGISTER_TRAIT_WITH_PROGRAMSTATE(PendingInitLoop
, PendingInitLoopMap
)
210 typedef llvm::ImmutableMap
<const LocationContext
*, unsigned>
211 PendingArrayDestructionMap
;
212 REGISTER_TRAIT_WITH_PROGRAMSTATE(PendingArrayDestruction
,
213 PendingArrayDestructionMap
)
215 //===----------------------------------------------------------------------===//
216 // Engine construction and deletion.
217 //===----------------------------------------------------------------------===//
219 static const char* TagProviderName
= "ExprEngine";
221 ExprEngine::ExprEngine(cross_tu::CrossTranslationUnitContext
&CTU
,
222 AnalysisManager
&mgr
, SetOfConstDecls
*VisitedCalleesIn
,
223 FunctionSummariesTy
*FS
, InliningModes HowToInlineIn
)
224 : CTU(CTU
), IsCTUEnabled(mgr
.getAnalyzerOptions().IsNaiveCTUEnabled
),
225 AMgr(mgr
), AnalysisDeclContexts(mgr
.getAnalysisDeclContextManager()),
226 Engine(*this, FS
, mgr
.getAnalyzerOptions()), G(Engine
.getGraph()),
227 StateMgr(getContext(), mgr
.getStoreManagerCreator(),
228 mgr
.getConstraintManagerCreator(), G
.getAllocator(), this),
229 SymMgr(StateMgr
.getSymbolManager()), MRMgr(StateMgr
.getRegionManager()),
230 svalBuilder(StateMgr
.getSValBuilder()), ObjCNoRet(mgr
.getASTContext()),
231 BR(mgr
, *this), VisitedCallees(VisitedCalleesIn
),
232 HowToInline(HowToInlineIn
) {
233 unsigned TrimInterval
= mgr
.options
.GraphTrimInterval
;
234 if (TrimInterval
!= 0) {
235 // Enable eager node reclamation when constructing the ExplodedGraph.
236 G
.enableNodeReclamation(TrimInterval
);
240 //===----------------------------------------------------------------------===//
242 //===----------------------------------------------------------------------===//
244 ProgramStateRef
ExprEngine::getInitialState(const LocationContext
*InitLoc
) {
245 ProgramStateRef state
= StateMgr
.getInitialState(InitLoc
);
246 const Decl
*D
= InitLoc
->getDecl();
249 // FIXME: It would be nice if we had a more general mechanism to add
250 // such preconditions. Some day.
252 if (const auto *FD
= dyn_cast
<FunctionDecl
>(D
)) {
253 // Precondition: the first argument of 'main' is an integer guaranteed
255 const IdentifierInfo
*II
= FD
->getIdentifier();
256 if (!II
|| !(II
->getName() == "main" && FD
->getNumParams() > 0))
259 const ParmVarDecl
*PD
= FD
->getParamDecl(0);
260 QualType T
= PD
->getType();
261 const auto *BT
= dyn_cast
<BuiltinType
>(T
);
262 if (!BT
|| !BT
->isInteger())
265 const MemRegion
*R
= state
->getRegion(PD
, InitLoc
);
269 SVal V
= state
->getSVal(loc::MemRegionVal(R
));
270 SVal Constraint_untested
= evalBinOp(state
, BO_GT
, V
,
271 svalBuilder
.makeZeroVal(T
),
272 svalBuilder
.getConditionType());
274 std::optional
<DefinedOrUnknownSVal
> Constraint
=
275 Constraint_untested
.getAs
<DefinedOrUnknownSVal
>();
280 if (ProgramStateRef newState
= state
->assume(*Constraint
, true))
287 if (const auto *MD
= dyn_cast
<ObjCMethodDecl
>(D
)) {
288 // Precondition: 'self' is always non-null upon entry to an Objective-C
290 const ImplicitParamDecl
*SelfD
= MD
->getSelfDecl();
291 const MemRegion
*R
= state
->getRegion(SelfD
, InitLoc
);
292 SVal V
= state
->getSVal(loc::MemRegionVal(R
));
294 if (std::optional
<Loc
> LV
= V
.getAs
<Loc
>()) {
295 // Assume that the pointer value in 'self' is non-null.
296 state
= state
->assume(*LV
, true);
297 assert(state
&& "'self' cannot be null");
301 if (const auto *MD
= dyn_cast
<CXXMethodDecl
>(D
)) {
302 if (!MD
->isStatic()) {
303 // Precondition: 'this' is always non-null upon entry to the
304 // top-level function. This is our starting assumption for
305 // analyzing an "open" program.
306 const StackFrameContext
*SFC
= InitLoc
->getStackFrame();
307 if (SFC
->getParent() == nullptr) {
308 loc::MemRegionVal L
= svalBuilder
.getCXXThis(MD
, SFC
);
309 SVal V
= state
->getSVal(L
);
310 if (std::optional
<Loc
> LV
= V
.getAs
<Loc
>()) {
311 state
= state
->assume(*LV
, true);
312 assert(state
&& "'this' cannot be null");
321 ProgramStateRef
ExprEngine::createTemporaryRegionIfNeeded(
322 ProgramStateRef State
, const LocationContext
*LC
,
323 const Expr
*InitWithAdjustments
, const Expr
*Result
,
324 const SubRegion
**OutRegionWithAdjustments
) {
325 // FIXME: This function is a hack that works around the quirky AST
326 // we're often having with respect to C++ temporaries. If only we modelled
327 // the actual execution order of statements properly in the CFG,
328 // all the hassle with adjustments would not be necessary,
329 // and perhaps the whole function would be removed.
330 SVal InitValWithAdjustments
= State
->getSVal(InitWithAdjustments
, LC
);
332 // If we don't have an explicit result expression, we're in "if needed"
333 // mode. Only create a region if the current value is a NonLoc.
334 if (!isa
<NonLoc
>(InitValWithAdjustments
)) {
335 if (OutRegionWithAdjustments
)
336 *OutRegionWithAdjustments
= nullptr;
339 Result
= InitWithAdjustments
;
341 // We need to create a region no matter what. Make sure we don't try to
342 // stuff a Loc into a non-pointer temporary region.
343 assert(!isa
<Loc
>(InitValWithAdjustments
) ||
344 Loc::isLocType(Result
->getType()) ||
345 Result
->getType()->isMemberPointerType());
348 ProgramStateManager
&StateMgr
= State
->getStateManager();
349 MemRegionManager
&MRMgr
= StateMgr
.getRegionManager();
350 StoreManager
&StoreMgr
= StateMgr
.getStoreManager();
352 // MaterializeTemporaryExpr may appear out of place, after a few field and
353 // base-class accesses have been made to the object, even though semantically
354 // it is the whole object that gets materialized and lifetime-extended.
358 // `-MaterializeTemporaryExpr
360 // `-CXXTemporaryObjectExpr
362 // instead of the more natural
365 // `-MaterializeTemporaryExpr
366 // `-CXXTemporaryObjectExpr
368 // Use the usual methods for obtaining the expression of the base object,
369 // and record the adjustments that we need to make to obtain the sub-object
370 // that the whole expression 'Ex' refers to. This trick is usual,
371 // in the sense that CodeGen takes a similar route.
373 SmallVector
<const Expr
*, 2> CommaLHSs
;
374 SmallVector
<SubobjectAdjustment
, 2> Adjustments
;
376 const Expr
*Init
= InitWithAdjustments
->skipRValueSubobjectAdjustments(
377 CommaLHSs
, Adjustments
);
379 // Take the region for Init, i.e. for the whole object. If we do not remember
380 // the region in which the object originally was constructed, come up with
381 // a new temporary region out of thin air and copy the contents of the object
382 // (which are currently present in the Environment, because Init is an rvalue)
383 // into that region. This is not correct, but it is better than nothing.
384 const TypedValueRegion
*TR
= nullptr;
385 if (const auto *MT
= dyn_cast
<MaterializeTemporaryExpr
>(Result
)) {
386 if (std::optional
<SVal
> V
= getObjectUnderConstruction(State
, MT
, LC
)) {
387 State
= finishObjectConstruction(State
, MT
, LC
);
388 State
= State
->BindExpr(Result
, LC
, *V
);
390 } else if (const ValueDecl
*VD
= MT
->getExtendingDecl()) {
391 StorageDuration SD
= MT
->getStorageDuration();
392 assert(SD
!= SD_FullExpression
);
393 // If this object is bound to a reference with static storage duration, we
394 // put it in a different region to prevent "address leakage" warnings.
395 if (SD
== SD_Static
|| SD
== SD_Thread
) {
396 TR
= MRMgr
.getCXXStaticLifetimeExtendedObjectRegion(Init
, VD
);
398 TR
= MRMgr
.getCXXLifetimeExtendedObjectRegion(Init
, VD
, LC
);
401 assert(MT
->getStorageDuration() == SD_FullExpression
);
402 TR
= MRMgr
.getCXXTempObjectRegion(Init
, LC
);
405 TR
= MRMgr
.getCXXTempObjectRegion(Init
, LC
);
408 SVal Reg
= loc::MemRegionVal(TR
);
411 // Make the necessary adjustments to obtain the sub-object.
412 for (const SubobjectAdjustment
&Adj
: llvm::reverse(Adjustments
)) {
414 case SubobjectAdjustment::DerivedToBaseAdjustment
:
415 Reg
= StoreMgr
.evalDerivedToBase(Reg
, Adj
.DerivedToBase
.BasePath
);
417 case SubobjectAdjustment::FieldAdjustment
:
418 Reg
= StoreMgr
.getLValueField(Adj
.Field
, Reg
);
420 case SubobjectAdjustment::MemberPointerAdjustment
:
421 // FIXME: Unimplemented.
422 State
= State
->invalidateRegions(Reg
, InitWithAdjustments
,
423 currBldrCtx
->blockCount(), LC
, true,
424 nullptr, nullptr, nullptr);
429 // What remains is to copy the value of the object to the new region.
430 // FIXME: In other words, what we should always do is copy value of the
431 // Init expression (which corresponds to the bigger object) to the whole
432 // temporary region TR. However, this value is often no longer present
433 // in the Environment. If it has disappeared, we instead invalidate TR.
434 // Still, what we can do is assign the value of expression Ex (which
435 // corresponds to the sub-object) to the TR's sub-region Reg. At least,
436 // values inside Reg would be correct.
437 SVal InitVal
= State
->getSVal(Init
, LC
);
438 if (InitVal
.isUnknown()) {
439 InitVal
= getSValBuilder().conjureSymbolVal(Result
, LC
, Init
->getType(),
440 currBldrCtx
->blockCount());
441 State
= State
->bindLoc(BaseReg
.castAs
<Loc
>(), InitVal
, LC
, false);
443 // Then we'd need to take the value that certainly exists and bind it
445 if (InitValWithAdjustments
.isUnknown()) {
446 // Try to recover some path sensitivity in case we couldn't
447 // compute the value.
448 InitValWithAdjustments
= getSValBuilder().conjureSymbolVal(
449 Result
, LC
, InitWithAdjustments
->getType(),
450 currBldrCtx
->blockCount());
453 State
->bindLoc(Reg
.castAs
<Loc
>(), InitValWithAdjustments
, LC
, false);
455 State
= State
->bindLoc(BaseReg
.castAs
<Loc
>(), InitVal
, LC
, false);
458 // The result expression would now point to the correct sub-region of the
459 // newly created temporary region. Do this last in order to getSVal of Init
460 // correctly in case (Result == Init).
461 if (Result
->isGLValue()) {
462 State
= State
->BindExpr(Result
, LC
, Reg
);
464 State
= State
->BindExpr(Result
, LC
, InitValWithAdjustments
);
467 // Notify checkers once for two bindLoc()s.
468 State
= processRegionChange(State
, TR
, LC
);
470 if (OutRegionWithAdjustments
)
471 *OutRegionWithAdjustments
= cast
<SubRegion
>(Reg
.getAsRegion());
475 ProgramStateRef
ExprEngine::setIndexOfElementToConstruct(
476 ProgramStateRef State
, const CXXConstructExpr
*E
,
477 const LocationContext
*LCtx
, unsigned Idx
) {
478 auto Key
= std::make_pair(E
, LCtx
->getStackFrame());
480 assert(!State
->contains
<IndexOfElementToConstruct
>(Key
) || Idx
> 0);
482 return State
->set
<IndexOfElementToConstruct
>(Key
, Idx
);
485 std::optional
<unsigned>
486 ExprEngine::getPendingInitLoop(ProgramStateRef State
, const CXXConstructExpr
*E
,
487 const LocationContext
*LCtx
) {
488 const unsigned *V
= State
->get
<PendingInitLoop
>({E
, LCtx
->getStackFrame()});
489 return V
? std::make_optional(*V
) : std::nullopt
;
492 ProgramStateRef
ExprEngine::removePendingInitLoop(ProgramStateRef State
,
493 const CXXConstructExpr
*E
,
494 const LocationContext
*LCtx
) {
495 auto Key
= std::make_pair(E
, LCtx
->getStackFrame());
497 assert(E
&& State
->contains
<PendingInitLoop
>(Key
));
498 return State
->remove
<PendingInitLoop
>(Key
);
501 ProgramStateRef
ExprEngine::setPendingInitLoop(ProgramStateRef State
,
502 const CXXConstructExpr
*E
,
503 const LocationContext
*LCtx
,
505 auto Key
= std::make_pair(E
, LCtx
->getStackFrame());
507 assert(!State
->contains
<PendingInitLoop
>(Key
) && Size
> 0);
509 return State
->set
<PendingInitLoop
>(Key
, Size
);
512 std::optional
<unsigned>
513 ExprEngine::getIndexOfElementToConstruct(ProgramStateRef State
,
514 const CXXConstructExpr
*E
,
515 const LocationContext
*LCtx
) {
517 State
->get
<IndexOfElementToConstruct
>({E
, LCtx
->getStackFrame()});
518 return V
? std::make_optional(*V
) : std::nullopt
;
522 ExprEngine::removeIndexOfElementToConstruct(ProgramStateRef State
,
523 const CXXConstructExpr
*E
,
524 const LocationContext
*LCtx
) {
525 auto Key
= std::make_pair(E
, LCtx
->getStackFrame());
527 assert(E
&& State
->contains
<IndexOfElementToConstruct
>(Key
));
528 return State
->remove
<IndexOfElementToConstruct
>(Key
);
531 std::optional
<unsigned>
532 ExprEngine::getPendingArrayDestruction(ProgramStateRef State
,
533 const LocationContext
*LCtx
) {
534 assert(LCtx
&& "LocationContext shouldn't be null!");
537 State
->get
<PendingArrayDestruction
>(LCtx
->getStackFrame());
538 return V
? std::make_optional(*V
) : std::nullopt
;
541 ProgramStateRef
ExprEngine::setPendingArrayDestruction(
542 ProgramStateRef State
, const LocationContext
*LCtx
, unsigned Idx
) {
543 assert(LCtx
&& "LocationContext shouldn't be null!");
545 auto Key
= LCtx
->getStackFrame();
547 return State
->set
<PendingArrayDestruction
>(Key
, Idx
);
551 ExprEngine::removePendingArrayDestruction(ProgramStateRef State
,
552 const LocationContext
*LCtx
) {
553 assert(LCtx
&& "LocationContext shouldn't be null!");
555 auto Key
= LCtx
->getStackFrame();
557 assert(LCtx
&& State
->contains
<PendingArrayDestruction
>(Key
));
558 return State
->remove
<PendingArrayDestruction
>(Key
);
562 ExprEngine::addObjectUnderConstruction(ProgramStateRef State
,
563 const ConstructionContextItem
&Item
,
564 const LocationContext
*LC
, SVal V
) {
565 ConstructedObjectKey
Key(Item
, LC
->getStackFrame());
567 const Expr
*Init
= nullptr;
569 if (auto DS
= dyn_cast_or_null
<DeclStmt
>(Item
.getStmtOrNull())) {
570 if (auto VD
= dyn_cast_or_null
<VarDecl
>(DS
->getSingleDecl()))
571 Init
= VD
->getInit();
574 if (auto LE
= dyn_cast_or_null
<LambdaExpr
>(Item
.getStmtOrNull()))
575 Init
= *(LE
->capture_init_begin() + Item
.getIndex());
577 if (!Init
&& !Item
.getStmtOrNull())
578 Init
= Item
.getCXXCtorInitializer()->getInit();
580 // In an ArrayInitLoopExpr the real initializer is returned by
581 // getSubExpr(). Note that AILEs can be nested in case of
582 // multidimesnional arrays.
583 if (const auto *AILE
= dyn_cast_or_null
<ArrayInitLoopExpr
>(Init
))
584 Init
= extractElementInitializerFromNestedAILE(AILE
);
586 // FIXME: Currently the state might already contain the marker due to
587 // incorrect handling of temporaries bound to default parameters.
588 // The state will already contain the marker if we construct elements
589 // in an array, as we visit the same statement multiple times before
590 // the array declaration. The marker is removed when we exit the
592 assert((!State
->get
<ObjectsUnderConstruction
>(Key
) ||
593 Key
.getItem().getKind() ==
594 ConstructionContextItem::TemporaryDestructorKind
||
595 State
->contains
<IndexOfElementToConstruct
>(
596 {dyn_cast_or_null
<CXXConstructExpr
>(Init
), LC
})) &&
597 "The object is already marked as `UnderConstruction`, when it's not "
599 return State
->set
<ObjectsUnderConstruction
>(Key
, V
);
603 ExprEngine::getObjectUnderConstruction(ProgramStateRef State
,
604 const ConstructionContextItem
&Item
,
605 const LocationContext
*LC
) {
606 ConstructedObjectKey
Key(Item
, LC
->getStackFrame());
607 const SVal
*V
= State
->get
<ObjectsUnderConstruction
>(Key
);
608 return V
? std::make_optional(*V
) : std::nullopt
;
612 ExprEngine::finishObjectConstruction(ProgramStateRef State
,
613 const ConstructionContextItem
&Item
,
614 const LocationContext
*LC
) {
615 ConstructedObjectKey
Key(Item
, LC
->getStackFrame());
616 assert(State
->contains
<ObjectsUnderConstruction
>(Key
));
617 return State
->remove
<ObjectsUnderConstruction
>(Key
);
620 ProgramStateRef
ExprEngine::elideDestructor(ProgramStateRef State
,
621 const CXXBindTemporaryExpr
*BTE
,
622 const LocationContext
*LC
) {
623 ConstructedObjectKey
Key({BTE
, /*IsElided=*/true}, LC
);
624 // FIXME: Currently the state might already contain the marker due to
625 // incorrect handling of temporaries bound to default parameters.
626 return State
->set
<ObjectsUnderConstruction
>(Key
, UnknownVal());
630 ExprEngine::cleanupElidedDestructor(ProgramStateRef State
,
631 const CXXBindTemporaryExpr
*BTE
,
632 const LocationContext
*LC
) {
633 ConstructedObjectKey
Key({BTE
, /*IsElided=*/true}, LC
);
634 assert(State
->contains
<ObjectsUnderConstruction
>(Key
));
635 return State
->remove
<ObjectsUnderConstruction
>(Key
);
638 bool ExprEngine::isDestructorElided(ProgramStateRef State
,
639 const CXXBindTemporaryExpr
*BTE
,
640 const LocationContext
*LC
) {
641 ConstructedObjectKey
Key({BTE
, /*IsElided=*/true}, LC
);
642 return State
->contains
<ObjectsUnderConstruction
>(Key
);
645 bool ExprEngine::areAllObjectsFullyConstructed(ProgramStateRef State
,
646 const LocationContext
*FromLC
,
647 const LocationContext
*ToLC
) {
648 const LocationContext
*LC
= FromLC
;
650 assert(LC
&& "ToLC must be a parent of FromLC!");
651 for (auto I
: State
->get
<ObjectsUnderConstruction
>())
652 if (I
.first
.getLocationContext() == LC
)
655 LC
= LC
->getParent();
661 //===----------------------------------------------------------------------===//
662 // Top-level transfer function logic (Dispatcher).
663 //===----------------------------------------------------------------------===//
665 /// evalAssume - Called by ConstraintManager. Used to call checker-specific
666 /// logic for handling assumptions on symbolic values.
667 ProgramStateRef
ExprEngine::processAssume(ProgramStateRef state
,
668 SVal cond
, bool assumption
) {
669 return getCheckerManager().runCheckersForEvalAssume(state
, cond
, assumption
);
673 ExprEngine::processRegionChanges(ProgramStateRef state
,
674 const InvalidatedSymbols
*invalidated
,
675 ArrayRef
<const MemRegion
*> Explicits
,
676 ArrayRef
<const MemRegion
*> Regions
,
677 const LocationContext
*LCtx
,
678 const CallEvent
*Call
) {
679 return getCheckerManager().runCheckersForRegionChanges(state
, invalidated
,
685 printObjectsUnderConstructionJson(raw_ostream
&Out
, ProgramStateRef State
,
686 const char *NL
, const LocationContext
*LCtx
,
687 unsigned int Space
= 0, bool IsDot
= false) {
689 LCtx
->getAnalysisDeclContext()->getASTContext().getPrintingPolicy();
692 bool HasItem
= false;
694 // Store the last key.
695 const ConstructedObjectKey
*LastKey
= nullptr;
696 for (const auto &I
: State
->get
<ObjectsUnderConstruction
>()) {
697 const ConstructedObjectKey
&Key
= I
.first
;
698 if (Key
.getLocationContext() != LCtx
)
709 for (const auto &I
: State
->get
<ObjectsUnderConstruction
>()) {
710 const ConstructedObjectKey
&Key
= I
.first
;
711 SVal Value
= I
.second
;
712 if (Key
.getLocationContext() != LCtx
)
715 Indent(Out
, Space
, IsDot
) << "{ ";
716 Key
.printJson(Out
, nullptr, PP
);
717 Out
<< ", \"value\": \"" << Value
<< "\" }";
725 Indent(Out
, --Space
, IsDot
) << ']'; // End of "location_context".
731 static void printIndicesOfElementsToConstructJson(
732 raw_ostream
&Out
, ProgramStateRef State
, const char *NL
,
733 const LocationContext
*LCtx
, unsigned int Space
= 0, bool IsDot
= false) {
734 using KeyT
= std::pair
<const Expr
*, const LocationContext
*>;
736 const auto &Context
= LCtx
->getAnalysisDeclContext()->getASTContext();
737 PrintingPolicy PP
= Context
.getPrintingPolicy();
740 bool HasItem
= false;
742 // Store the last key.
744 for (const auto &I
: State
->get
<IndexOfElementToConstruct
>()) {
745 const KeyT
&Key
= I
.first
;
746 if (Key
.second
!= LCtx
)
757 for (const auto &I
: State
->get
<IndexOfElementToConstruct
>()) {
758 const KeyT
&Key
= I
.first
;
759 unsigned Value
= I
.second
;
760 if (Key
.second
!= LCtx
)
763 Indent(Out
, Space
, IsDot
) << "{ ";
766 const Expr
*E
= Key
.first
;
767 Out
<< "\"stmt_id\": " << E
->getID(Context
);
770 Out
<< ", \"kind\": null";
773 Out
<< ", \"pretty\": ";
774 Out
<< "\"" << E
->getStmtClassName() << ' '
775 << E
->getSourceRange().printToString(Context
.getSourceManager()) << " '"
776 << QualType::getAsString(E
->getType().split(), PP
);
779 Out
<< ", \"value\": \"Current index: " << Value
- 1 << "\" }";
787 Indent(Out
, --Space
, IsDot
) << ']'; // End of "location_context".
793 static void printPendingInitLoopJson(raw_ostream
&Out
, ProgramStateRef State
,
795 const LocationContext
*LCtx
,
796 unsigned int Space
= 0,
797 bool IsDot
= false) {
798 using KeyT
= std::pair
<const CXXConstructExpr
*, const LocationContext
*>;
800 const auto &Context
= LCtx
->getAnalysisDeclContext()->getASTContext();
801 PrintingPolicy PP
= Context
.getPrintingPolicy();
804 bool HasItem
= false;
806 // Store the last key.
808 for (const auto &I
: State
->get
<PendingInitLoop
>()) {
809 const KeyT
&Key
= I
.first
;
810 if (Key
.second
!= LCtx
)
821 for (const auto &I
: State
->get
<PendingInitLoop
>()) {
822 const KeyT
&Key
= I
.first
;
823 unsigned Value
= I
.second
;
824 if (Key
.second
!= LCtx
)
827 Indent(Out
, Space
, IsDot
) << "{ ";
829 const CXXConstructExpr
*E
= Key
.first
;
830 Out
<< "\"stmt_id\": " << E
->getID(Context
);
832 Out
<< ", \"kind\": null";
833 Out
<< ", \"pretty\": ";
834 Out
<< '\"' << E
->getStmtClassName() << ' '
835 << E
->getSourceRange().printToString(Context
.getSourceManager()) << " '"
836 << QualType::getAsString(E
->getType().split(), PP
);
839 Out
<< ", \"value\": \"Flattened size: " << Value
<< "\"}";
847 Indent(Out
, --Space
, IsDot
) << ']'; // End of "location_context".
854 printPendingArrayDestructionsJson(raw_ostream
&Out
, ProgramStateRef State
,
855 const char *NL
, const LocationContext
*LCtx
,
856 unsigned int Space
= 0, bool IsDot
= false) {
857 using KeyT
= const LocationContext
*;
860 bool HasItem
= false;
862 // Store the last key.
863 KeyT LastKey
= nullptr;
864 for (const auto &I
: State
->get
<PendingArrayDestruction
>()) {
865 const KeyT
&Key
= I
.first
;
877 for (const auto &I
: State
->get
<PendingArrayDestruction
>()) {
878 const KeyT
&Key
= I
.first
;
882 Indent(Out
, Space
, IsDot
) << "{ ";
884 Out
<< "\"stmt_id\": null";
885 Out
<< ", \"kind\": null";
886 Out
<< ", \"pretty\": \"Current index: \"";
887 Out
<< ", \"value\": \"" << I
.second
<< "\" }";
895 Indent(Out
, --Space
, IsDot
) << ']'; // End of "location_context".
901 /// A helper function to generalize program state trait printing.
902 /// The function invokes Printer as 'Printer(Out, State, NL, LC, Space, IsDot,
903 /// std::forward<Args>(args)...)'. \n One possible type for Printer is
904 /// 'void()(raw_ostream &, ProgramStateRef, const char *, const LocationContext
905 /// *, unsigned int, bool, ...)' \n \param Trait The state trait to be printed.
906 /// \param Printer A void function that prints Trait.
907 /// \param Args An additional parameter pack that is passed to Print upon
909 template <typename Trait
, typename Printer
, typename
... Args
>
910 static void printStateTraitWithLocationContextJson(
911 raw_ostream
&Out
, ProgramStateRef State
, const LocationContext
*LCtx
,
912 const char *NL
, unsigned int Space
, bool IsDot
,
913 const char *jsonPropertyName
, Printer printer
, Args
&&...args
) {
916 void (*)(raw_ostream
&, ProgramStateRef
, const char *,
917 const LocationContext
*, unsigned int, bool, Args
&&...);
919 // Try to do as much compile time checking as possible.
920 // FIXME: check for invocable instead of function?
921 static_assert(std::is_function_v
<std::remove_pointer_t
<Printer
>>,
922 "Printer is not a function!");
923 static_assert(std::is_convertible_v
<Printer
, RequiredType
>,
924 "Printer doesn't have the required type!");
926 if (LCtx
&& !State
->get
<Trait
>().isEmpty()) {
927 Indent(Out
, Space
, IsDot
) << '\"' << jsonPropertyName
<< "\": ";
930 LCtx
->printJson(Out
, NL
, Space
, IsDot
, [&](const LocationContext
*LC
) {
931 printer(Out
, State
, NL
, LC
, Space
, IsDot
, std::forward
<Args
>(args
)...);
935 Indent(Out
, Space
, IsDot
) << "]," << NL
; // End of "jsonPropertyName".
939 void ExprEngine::printJson(raw_ostream
&Out
, ProgramStateRef State
,
940 const LocationContext
*LCtx
, const char *NL
,
941 unsigned int Space
, bool IsDot
) const {
943 printStateTraitWithLocationContextJson
<ObjectsUnderConstruction
>(
944 Out
, State
, LCtx
, NL
, Space
, IsDot
, "constructing_objects",
945 printObjectsUnderConstructionJson
);
946 printStateTraitWithLocationContextJson
<IndexOfElementToConstruct
>(
947 Out
, State
, LCtx
, NL
, Space
, IsDot
, "index_of_element",
948 printIndicesOfElementsToConstructJson
);
949 printStateTraitWithLocationContextJson
<PendingInitLoop
>(
950 Out
, State
, LCtx
, NL
, Space
, IsDot
, "pending_init_loops",
951 printPendingInitLoopJson
);
952 printStateTraitWithLocationContextJson
<PendingArrayDestruction
>(
953 Out
, State
, LCtx
, NL
, Space
, IsDot
, "pending_destructors",
954 printPendingArrayDestructionsJson
);
956 getCheckerManager().runCheckersForPrintStateJson(Out
, State
, NL
, Space
,
960 void ExprEngine::processEndWorklist() {
961 // This prints the name of the top-level function if we crash.
962 PrettyStackTraceLocationContext
CrashInfo(getRootLocationContext());
963 getCheckerManager().runCheckersForEndAnalysis(G
, BR
, *this);
966 void ExprEngine::processCFGElement(const CFGElement E
, ExplodedNode
*Pred
,
967 unsigned StmtIdx
, NodeBuilderContext
*Ctx
) {
968 PrettyStackTraceLocationContext
CrashInfo(Pred
->getLocationContext());
969 currStmtIdx
= StmtIdx
;
972 switch (E
.getKind()) {
973 case CFGElement::Statement
:
974 case CFGElement::Constructor
:
975 case CFGElement::CXXRecordTypedCall
:
976 ProcessStmt(E
.castAs
<CFGStmt
>().getStmt(), Pred
);
978 case CFGElement::Initializer
:
979 ProcessInitializer(E
.castAs
<CFGInitializer
>(), Pred
);
981 case CFGElement::NewAllocator
:
982 ProcessNewAllocator(E
.castAs
<CFGNewAllocator
>().getAllocatorExpr(),
985 case CFGElement::AutomaticObjectDtor
:
986 case CFGElement::DeleteDtor
:
987 case CFGElement::BaseDtor
:
988 case CFGElement::MemberDtor
:
989 case CFGElement::TemporaryDtor
:
990 ProcessImplicitDtor(E
.castAs
<CFGImplicitDtor
>(), Pred
);
992 case CFGElement::LoopExit
:
993 ProcessLoopExit(E
.castAs
<CFGLoopExit
>().getLoopStmt(), Pred
);
995 case CFGElement::LifetimeEnds
:
996 case CFGElement::ScopeBegin
:
997 case CFGElement::ScopeEnd
:
1002 static bool shouldRemoveDeadBindings(AnalysisManager
&AMgr
,
1004 const ExplodedNode
*Pred
,
1005 const LocationContext
*LC
) {
1006 // Are we never purging state values?
1007 if (AMgr
.options
.AnalysisPurgeOpt
== PurgeNone
)
1010 // Is this the beginning of a basic block?
1011 if (Pred
->getLocation().getAs
<BlockEntrance
>())
1014 // Is this on a non-expression?
1018 // Run before processing a call.
1019 if (CallEvent::isCallStmt(S
))
1022 // Is this an expression that is consumed by another expression? If so,
1023 // postpone cleaning out the state.
1024 ParentMap
&PM
= LC
->getAnalysisDeclContext()->getParentMap();
1025 return !PM
.isConsumedExpr(cast
<Expr
>(S
));
1028 void ExprEngine::removeDead(ExplodedNode
*Pred
, ExplodedNodeSet
&Out
,
1029 const Stmt
*ReferenceStmt
,
1030 const LocationContext
*LC
,
1031 const Stmt
*DiagnosticStmt
,
1032 ProgramPoint::Kind K
) {
1033 assert((K
== ProgramPoint::PreStmtPurgeDeadSymbolsKind
||
1034 ReferenceStmt
== nullptr || isa
<ReturnStmt
>(ReferenceStmt
))
1035 && "PostStmt is not generally supported by the SymbolReaper yet");
1036 assert(LC
&& "Must pass the current (or expiring) LocationContext");
1038 if (!DiagnosticStmt
) {
1039 DiagnosticStmt
= ReferenceStmt
;
1040 assert(DiagnosticStmt
&& "Required for clearing a LocationContext");
1043 NumRemoveDeadBindings
++;
1044 ProgramStateRef CleanedState
= Pred
->getState();
1046 // LC is the location context being destroyed, but SymbolReaper wants a
1047 // location context that is still live. (If this is the top-level stack
1048 // frame, this will be null.)
1049 if (!ReferenceStmt
) {
1050 assert(K
== ProgramPoint::PostStmtPurgeDeadSymbolsKind
&&
1051 "Use PostStmtPurgeDeadSymbolsKind for clearing a LocationContext");
1052 LC
= LC
->getParent();
1055 const StackFrameContext
*SFC
= LC
? LC
->getStackFrame() : nullptr;
1056 SymbolReaper
SymReaper(SFC
, ReferenceStmt
, SymMgr
, getStoreManager());
1058 for (auto I
: CleanedState
->get
<ObjectsUnderConstruction
>()) {
1059 if (SymbolRef Sym
= I
.second
.getAsSymbol())
1060 SymReaper
.markLive(Sym
);
1061 if (const MemRegion
*MR
= I
.second
.getAsRegion())
1062 SymReaper
.markLive(MR
);
1065 getCheckerManager().runCheckersForLiveSymbols(CleanedState
, SymReaper
);
1067 // Create a state in which dead bindings are removed from the environment
1068 // and the store. TODO: The function should just return new env and store,
1070 CleanedState
= StateMgr
.removeDeadBindingsFromEnvironmentAndStore(
1071 CleanedState
, SFC
, SymReaper
);
1073 // Process any special transfer function for dead symbols.
1074 // A tag to track convenience transitions, which can be removed at cleanup.
1075 static SimpleProgramPointTag
cleanupTag(TagProviderName
, "Clean Node");
1076 // Call checkers with the non-cleaned state so that they could query the
1077 // values of the soon to be dead symbols.
1078 ExplodedNodeSet CheckedSet
;
1079 getCheckerManager().runCheckersForDeadSymbols(CheckedSet
, Pred
, SymReaper
,
1080 DiagnosticStmt
, *this, K
);
1082 // For each node in CheckedSet, generate CleanedNodes that have the
1083 // environment, the store, and the constraints cleaned up but have the
1084 // user-supplied states as the predecessors.
1085 StmtNodeBuilder
Bldr(CheckedSet
, Out
, *currBldrCtx
);
1086 for (const auto I
: CheckedSet
) {
1087 ProgramStateRef CheckerState
= I
->getState();
1089 // The constraint manager has not been cleaned up yet, so clean up now.
1091 getConstraintManager().removeDeadBindings(CheckerState
, SymReaper
);
1093 assert(StateMgr
.haveEqualEnvironments(CheckerState
, Pred
->getState()) &&
1094 "Checkers are not allowed to modify the Environment as a part of "
1095 "checkDeadSymbols processing.");
1096 assert(StateMgr
.haveEqualStores(CheckerState
, Pred
->getState()) &&
1097 "Checkers are not allowed to modify the Store as a part of "
1098 "checkDeadSymbols processing.");
1100 // Create a state based on CleanedState with CheckerState GDM and
1101 // generate a transition to that state.
1102 ProgramStateRef CleanedCheckerSt
=
1103 StateMgr
.getPersistentStateWithGDM(CleanedState
, CheckerState
);
1104 Bldr
.generateNode(DiagnosticStmt
, I
, CleanedCheckerSt
, &cleanupTag
, K
);
1108 void ExprEngine::ProcessStmt(const Stmt
*currStmt
, ExplodedNode
*Pred
) {
1109 // Reclaim any unnecessary nodes in the ExplodedGraph.
1110 G
.reclaimRecentlyAllocatedNodes();
1112 PrettyStackTraceLoc
CrashInfo(getContext().getSourceManager(),
1113 currStmt
->getBeginLoc(),
1114 "Error evaluating statement");
1116 // Remove dead bindings and symbols.
1117 ExplodedNodeSet CleanedStates
;
1118 if (shouldRemoveDeadBindings(AMgr
, currStmt
, Pred
,
1119 Pred
->getLocationContext())) {
1120 removeDead(Pred
, CleanedStates
, currStmt
,
1121 Pred
->getLocationContext());
1123 CleanedStates
.Add(Pred
);
1125 // Visit the statement.
1126 ExplodedNodeSet Dst
;
1127 for (const auto I
: CleanedStates
) {
1128 ExplodedNodeSet DstI
;
1129 // Visit the statement.
1130 Visit(currStmt
, I
, DstI
);
1134 // Enqueue the new nodes onto the work list.
1135 Engine
.enqueue(Dst
, currBldrCtx
->getBlock(), currStmtIdx
);
1138 void ExprEngine::ProcessLoopExit(const Stmt
* S
, ExplodedNode
*Pred
) {
1139 PrettyStackTraceLoc
CrashInfo(getContext().getSourceManager(),
1141 "Error evaluating end of the loop");
1142 ExplodedNodeSet Dst
;
1144 NodeBuilder
Bldr(Pred
, Dst
, *currBldrCtx
);
1145 ProgramStateRef NewState
= Pred
->getState();
1147 if(AMgr
.options
.ShouldUnrollLoops
)
1148 NewState
= processLoopEnd(S
, NewState
);
1150 LoopExit
PP(S
, Pred
->getLocationContext());
1151 Bldr
.generateNode(PP
, NewState
, Pred
);
1152 // Enqueue the new nodes onto the work list.
1153 Engine
.enqueue(Dst
, currBldrCtx
->getBlock(), currStmtIdx
);
1156 void ExprEngine::ProcessInitializer(const CFGInitializer CFGInit
,
1157 ExplodedNode
*Pred
) {
1158 const CXXCtorInitializer
*BMI
= CFGInit
.getInitializer();
1159 const Expr
*Init
= BMI
->getInit()->IgnoreImplicit();
1160 const LocationContext
*LC
= Pred
->getLocationContext();
1162 PrettyStackTraceLoc
CrashInfo(getContext().getSourceManager(),
1163 BMI
->getSourceLocation(),
1164 "Error evaluating initializer");
1166 // We don't clean up dead bindings here.
1167 const auto *stackFrame
= cast
<StackFrameContext
>(Pred
->getLocationContext());
1168 const auto *decl
= cast
<CXXConstructorDecl
>(stackFrame
->getDecl());
1170 ProgramStateRef State
= Pred
->getState();
1171 SVal thisVal
= State
->getSVal(svalBuilder
.getCXXThis(decl
, stackFrame
));
1173 ExplodedNodeSet Tmp
;
1176 // Evaluate the initializer, if necessary
1177 if (BMI
->isAnyMemberInitializer()) {
1178 // Constructors build the object directly in the field,
1179 // but non-objects must be copied in from the initializer.
1180 if (getObjectUnderConstruction(State
, BMI
, LC
)) {
1181 // The field was directly constructed, so there is no need to bind.
1182 // But we still need to stop tracking the object under construction.
1183 State
= finishObjectConstruction(State
, BMI
, LC
);
1184 NodeBuilder
Bldr(Pred
, Tmp
, *currBldrCtx
);
1185 PostStore
PS(Init
, LC
, /*Loc*/ nullptr, /*tag*/ nullptr);
1186 Bldr
.generateNode(PS
, State
, Pred
);
1188 const ValueDecl
*Field
;
1189 if (BMI
->isIndirectMemberInitializer()) {
1190 Field
= BMI
->getIndirectMember();
1191 FieldLoc
= State
->getLValue(BMI
->getIndirectMember(), thisVal
);
1193 Field
= BMI
->getMember();
1194 FieldLoc
= State
->getLValue(BMI
->getMember(), thisVal
);
1198 if (Init
->getType()->isArrayType()) {
1199 // Handle arrays of trivial type. We can represent this with a
1200 // primitive load/copy from the base array region.
1201 const ArraySubscriptExpr
*ASE
;
1202 while ((ASE
= dyn_cast
<ArraySubscriptExpr
>(Init
)))
1203 Init
= ASE
->getBase()->IgnoreImplicit();
1205 SVal LValue
= State
->getSVal(Init
, stackFrame
);
1206 if (!Field
->getType()->isReferenceType())
1207 if (std::optional
<Loc
> LValueLoc
= LValue
.getAs
<Loc
>())
1208 InitVal
= State
->getSVal(*LValueLoc
);
1210 // If we fail to get the value for some reason, use a symbolic value.
1211 if (InitVal
.isUnknownOrUndef()) {
1212 SValBuilder
&SVB
= getSValBuilder();
1213 InitVal
= SVB
.conjureSymbolVal(BMI
->getInit(), stackFrame
,
1215 currBldrCtx
->blockCount());
1218 InitVal
= State
->getSVal(BMI
->getInit(), stackFrame
);
1221 PostInitializer
PP(BMI
, FieldLoc
.getAsRegion(), stackFrame
);
1222 evalBind(Tmp
, Init
, Pred
, FieldLoc
, InitVal
, /*isInit=*/true, &PP
);
1225 assert(BMI
->isBaseInitializer() || BMI
->isDelegatingInitializer());
1227 // We already did all the work when visiting the CXXConstructExpr.
1230 // Construct PostInitializer nodes whether the state changed or not,
1231 // so that the diagnostics don't get confused.
1232 PostInitializer
PP(BMI
, FieldLoc
.getAsRegion(), stackFrame
);
1233 ExplodedNodeSet Dst
;
1234 NodeBuilder
Bldr(Tmp
, Dst
, *currBldrCtx
);
1235 for (const auto I
: Tmp
) {
1236 ProgramStateRef State
= I
->getState();
1237 Bldr
.generateNode(PP
, State
, I
);
1240 // Enqueue the new nodes onto the work list.
1241 Engine
.enqueue(Dst
, currBldrCtx
->getBlock(), currStmtIdx
);
1244 std::pair
<ProgramStateRef
, uint64_t>
1245 ExprEngine::prepareStateForArrayDestruction(const ProgramStateRef State
,
1246 const MemRegion
*Region
,
1247 const QualType
&ElementTy
,
1248 const LocationContext
*LCtx
,
1249 SVal
*ElementCountVal
) {
1250 assert(Region
!= nullptr && "Not-null region expected");
1252 QualType Ty
= ElementTy
.getDesugaredType(getContext());
1253 while (const auto *NTy
= dyn_cast
<ArrayType
>(Ty
))
1254 Ty
= NTy
->getElementType().getDesugaredType(getContext());
1256 auto ElementCount
= getDynamicElementCount(State
, Region
, svalBuilder
, Ty
);
1258 if (ElementCountVal
)
1259 *ElementCountVal
= ElementCount
;
1261 // Note: the destructors are called in reverse order.
1263 if (auto OptionalIdx
= getPendingArrayDestruction(State
, LCtx
)) {
1266 // The element count is either unknown, or an SVal that's not an integer.
1267 if (!ElementCount
.isConstant())
1270 Idx
= ElementCount
.getAsInteger()->getLimitedValue();
1278 return {setPendingArrayDestruction(State
, LCtx
, Idx
), Idx
};
1281 void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D
,
1282 ExplodedNode
*Pred
) {
1283 ExplodedNodeSet Dst
;
1284 switch (D
.getKind()) {
1285 case CFGElement::AutomaticObjectDtor
:
1286 ProcessAutomaticObjDtor(D
.castAs
<CFGAutomaticObjDtor
>(), Pred
, Dst
);
1288 case CFGElement::BaseDtor
:
1289 ProcessBaseDtor(D
.castAs
<CFGBaseDtor
>(), Pred
, Dst
);
1291 case CFGElement::MemberDtor
:
1292 ProcessMemberDtor(D
.castAs
<CFGMemberDtor
>(), Pred
, Dst
);
1294 case CFGElement::TemporaryDtor
:
1295 ProcessTemporaryDtor(D
.castAs
<CFGTemporaryDtor
>(), Pred
, Dst
);
1297 case CFGElement::DeleteDtor
:
1298 ProcessDeleteDtor(D
.castAs
<CFGDeleteDtor
>(), Pred
, Dst
);
1301 llvm_unreachable("Unexpected dtor kind.");
1304 // Enqueue the new nodes onto the work list.
1305 Engine
.enqueue(Dst
, currBldrCtx
->getBlock(), currStmtIdx
);
1308 void ExprEngine::ProcessNewAllocator(const CXXNewExpr
*NE
,
1309 ExplodedNode
*Pred
) {
1310 ExplodedNodeSet Dst
;
1311 AnalysisManager
&AMgr
= getAnalysisManager();
1312 AnalyzerOptions
&Opts
= AMgr
.options
;
1313 // TODO: We're not evaluating allocators for all cases just yet as
1314 // we're not handling the return value correctly, which causes false
1315 // positives when the alpha.cplusplus.NewDeleteLeaks check is on.
1316 if (Opts
.MayInlineCXXAllocator
)
1317 VisitCXXNewAllocatorCall(NE
, Pred
, Dst
);
1319 NodeBuilder
Bldr(Pred
, Dst
, *currBldrCtx
);
1320 const LocationContext
*LCtx
= Pred
->getLocationContext();
1321 PostImplicitCall
PP(NE
->getOperatorNew(), NE
->getBeginLoc(), LCtx
,
1322 getCFGElementRef());
1323 Bldr
.generateNode(PP
, Pred
->getState(), Pred
);
1325 Engine
.enqueue(Dst
, currBldrCtx
->getBlock(), currStmtIdx
);
1328 void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor
,
1330 ExplodedNodeSet
&Dst
) {
1331 const auto *DtorDecl
= Dtor
.getDestructorDecl(getContext());
1332 const VarDecl
*varDecl
= Dtor
.getVarDecl();
1333 QualType varType
= varDecl
->getType();
1335 ProgramStateRef state
= Pred
->getState();
1336 const LocationContext
*LCtx
= Pred
->getLocationContext();
1338 SVal dest
= state
->getLValue(varDecl
, LCtx
);
1339 const MemRegion
*Region
= dest
.castAs
<loc::MemRegionVal
>().getRegion();
1341 if (varType
->isReferenceType()) {
1342 const MemRegion
*ValueRegion
= state
->getSVal(Region
).getAsRegion();
1344 // FIXME: This should not happen. The language guarantees a presence
1345 // of a valid initializer here, so the reference shall not be undefined.
1346 // It seems that we're calling destructors over variables that
1347 // were not initialized yet.
1350 Region
= ValueRegion
->getBaseRegion();
1351 varType
= cast
<TypedValueRegion
>(Region
)->getValueType();
1355 if (isa
<ArrayType
>(varType
)) {
1357 std::tie(state
, Idx
) = prepareStateForArrayDestruction(
1358 state
, Region
, varType
, LCtx
, &ElementCount
);
1360 if (ElementCount
.isConstant()) {
1361 uint64_t ArrayLength
= ElementCount
.getAsInteger()->getLimitedValue();
1362 assert(ArrayLength
&&
1363 "An automatic dtor for a 0 length array shouldn't be triggered!");
1365 // Still handle this case if we don't have assertions enabled.
1367 static SimpleProgramPointTag
PT(
1368 "ExprEngine", "Skipping automatic 0 length array destruction, "
1369 "which shouldn't be in the CFG.");
1370 PostImplicitCall
PP(DtorDecl
, varDecl
->getLocation(), LCtx
,
1371 getCFGElementRef(), &PT
);
1372 NodeBuilder
Bldr(Pred
, Dst
, *currBldrCtx
);
1373 Bldr
.generateSink(PP
, Pred
->getState(), Pred
);
1379 EvalCallOptions CallOpts
;
1380 Region
= makeElementRegion(state
, loc::MemRegionVal(Region
), varType
,
1381 CallOpts
.IsArrayCtorOrDtor
, Idx
)
1384 NodeBuilder
Bldr(Pred
, Dst
, getBuilderContext());
1386 static SimpleProgramPointTag
PT("ExprEngine",
1387 "Prepare for object destruction");
1388 PreImplicitCall
PP(DtorDecl
, varDecl
->getLocation(), LCtx
, getCFGElementRef(),
1390 Pred
= Bldr
.generateNode(PP
, state
, Pred
);
1394 Bldr
.takeNodes(Pred
);
1396 VisitCXXDestructor(varType
, Region
, Dtor
.getTriggerStmt(),
1397 /*IsBase=*/false, Pred
, Dst
, CallOpts
);
1400 void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor
,
1402 ExplodedNodeSet
&Dst
) {
1403 ProgramStateRef State
= Pred
->getState();
1404 const LocationContext
*LCtx
= Pred
->getLocationContext();
1405 const CXXDeleteExpr
*DE
= Dtor
.getDeleteExpr();
1406 const Stmt
*Arg
= DE
->getArgument();
1407 QualType DTy
= DE
->getDestroyedType();
1408 SVal ArgVal
= State
->getSVal(Arg
, LCtx
);
1410 // If the argument to delete is known to be a null value,
1411 // don't run destructor.
1412 if (State
->isNull(ArgVal
).isConstrainedTrue()) {
1413 QualType BTy
= getContext().getBaseElementType(DTy
);
1414 const CXXRecordDecl
*RD
= BTy
->getAsCXXRecordDecl();
1415 const CXXDestructorDecl
*Dtor
= RD
->getDestructor();
1417 PostImplicitCall
PP(Dtor
, DE
->getBeginLoc(), LCtx
, getCFGElementRef());
1418 NodeBuilder
Bldr(Pred
, Dst
, *currBldrCtx
);
1419 Bldr
.generateNode(PP
, Pred
->getState(), Pred
);
1423 auto getDtorDecl
= [](const QualType
&DTy
) {
1424 const CXXRecordDecl
*RD
= DTy
->getAsCXXRecordDecl();
1425 return RD
->getDestructor();
1429 EvalCallOptions CallOpts
;
1430 const MemRegion
*ArgR
= ArgVal
.getAsRegion();
1432 if (DE
->isArrayForm()) {
1433 CallOpts
.IsArrayCtorOrDtor
= true;
1434 // Yes, it may even be a multi-dimensional array.
1435 while (const auto *AT
= getContext().getAsArrayType(DTy
))
1436 DTy
= AT
->getElementType();
1440 std::tie(State
, Idx
) = prepareStateForArrayDestruction(
1441 State
, ArgR
, DTy
, LCtx
, &ElementCount
);
1443 // If we're about to destruct a 0 length array, don't run any of the
1445 if (ElementCount
.isConstant() &&
1446 ElementCount
.getAsInteger()->getLimitedValue() == 0) {
1448 static SimpleProgramPointTag
PT(
1449 "ExprEngine", "Skipping 0 length array delete destruction");
1450 PostImplicitCall
PP(getDtorDecl(DTy
), DE
->getBeginLoc(), LCtx
,
1451 getCFGElementRef(), &PT
);
1452 NodeBuilder
Bldr(Pred
, Dst
, *currBldrCtx
);
1453 Bldr
.generateNode(PP
, Pred
->getState(), Pred
);
1457 ArgR
= State
->getLValue(DTy
, svalBuilder
.makeArrayIndex(Idx
), ArgVal
)
1462 NodeBuilder
Bldr(Pred
, Dst
, getBuilderContext());
1463 static SimpleProgramPointTag
PT("ExprEngine",
1464 "Prepare for object destruction");
1465 PreImplicitCall
PP(getDtorDecl(DTy
), DE
->getBeginLoc(), LCtx
,
1466 getCFGElementRef(), &PT
);
1467 Pred
= Bldr
.generateNode(PP
, State
, Pred
);
1471 Bldr
.takeNodes(Pred
);
1473 VisitCXXDestructor(DTy
, ArgR
, DE
, /*IsBase=*/false, Pred
, Dst
, CallOpts
);
1476 void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D
,
1477 ExplodedNode
*Pred
, ExplodedNodeSet
&Dst
) {
1478 const LocationContext
*LCtx
= Pred
->getLocationContext();
1480 const auto *CurDtor
= cast
<CXXDestructorDecl
>(LCtx
->getDecl());
1481 Loc ThisPtr
= getSValBuilder().getCXXThis(CurDtor
,
1482 LCtx
->getStackFrame());
1483 SVal ThisVal
= Pred
->getState()->getSVal(ThisPtr
);
1485 // Create the base object region.
1486 const CXXBaseSpecifier
*Base
= D
.getBaseSpecifier();
1487 QualType BaseTy
= Base
->getType();
1488 SVal BaseVal
= getStoreManager().evalDerivedToBase(ThisVal
, BaseTy
,
1491 EvalCallOptions CallOpts
;
1492 VisitCXXDestructor(BaseTy
, BaseVal
.getAsRegion(), CurDtor
->getBody(),
1493 /*IsBase=*/true, Pred
, Dst
, CallOpts
);
1496 void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D
,
1497 ExplodedNode
*Pred
, ExplodedNodeSet
&Dst
) {
1498 const auto *DtorDecl
= D
.getDestructorDecl(getContext());
1499 const FieldDecl
*Member
= D
.getFieldDecl();
1500 QualType T
= Member
->getType();
1501 ProgramStateRef State
= Pred
->getState();
1502 const LocationContext
*LCtx
= Pred
->getLocationContext();
1504 const auto *CurDtor
= cast
<CXXDestructorDecl
>(LCtx
->getDecl());
1505 Loc ThisStorageLoc
=
1506 getSValBuilder().getCXXThis(CurDtor
, LCtx
->getStackFrame());
1507 Loc ThisLoc
= State
->getSVal(ThisStorageLoc
).castAs
<Loc
>();
1508 SVal FieldVal
= State
->getLValue(Member
, ThisLoc
);
1511 if (isa
<ArrayType
>(T
)) {
1513 std::tie(State
, Idx
) = prepareStateForArrayDestruction(
1514 State
, FieldVal
.getAsRegion(), T
, LCtx
, &ElementCount
);
1516 if (ElementCount
.isConstant()) {
1517 uint64_t ArrayLength
= ElementCount
.getAsInteger()->getLimitedValue();
1518 assert(ArrayLength
&&
1519 "A member dtor for a 0 length array shouldn't be triggered!");
1521 // Still handle this case if we don't have assertions enabled.
1523 static SimpleProgramPointTag
PT(
1524 "ExprEngine", "Skipping member 0 length array destruction, which "
1525 "shouldn't be in the CFG.");
1526 PostImplicitCall
PP(DtorDecl
, Member
->getLocation(), LCtx
,
1527 getCFGElementRef(), &PT
);
1528 NodeBuilder
Bldr(Pred
, Dst
, *currBldrCtx
);
1529 Bldr
.generateSink(PP
, Pred
->getState(), Pred
);
1535 EvalCallOptions CallOpts
;
1537 makeElementRegion(State
, FieldVal
, T
, CallOpts
.IsArrayCtorOrDtor
, Idx
);
1539 NodeBuilder
Bldr(Pred
, Dst
, getBuilderContext());
1541 static SimpleProgramPointTag
PT("ExprEngine",
1542 "Prepare for object destruction");
1543 PreImplicitCall
PP(DtorDecl
, Member
->getLocation(), LCtx
, getCFGElementRef(),
1545 Pred
= Bldr
.generateNode(PP
, State
, Pred
);
1549 Bldr
.takeNodes(Pred
);
1551 VisitCXXDestructor(T
, FieldVal
.getAsRegion(), CurDtor
->getBody(),
1552 /*IsBase=*/false, Pred
, Dst
, CallOpts
);
1555 void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D
,
1557 ExplodedNodeSet
&Dst
) {
1558 const CXXBindTemporaryExpr
*BTE
= D
.getBindTemporaryExpr();
1559 ProgramStateRef State
= Pred
->getState();
1560 const LocationContext
*LC
= Pred
->getLocationContext();
1561 const MemRegion
*MR
= nullptr;
1563 if (std::optional
<SVal
> V
= getObjectUnderConstruction(
1564 State
, D
.getBindTemporaryExpr(), Pred
->getLocationContext())) {
1565 // FIXME: Currently we insert temporary destructors for default parameters,
1566 // but we don't insert the constructors, so the entry in
1567 // ObjectsUnderConstruction may be missing.
1568 State
= finishObjectConstruction(State
, D
.getBindTemporaryExpr(),
1569 Pred
->getLocationContext());
1570 MR
= V
->getAsRegion();
1573 // If copy elision has occurred, and the constructor corresponding to the
1574 // destructor was elided, we need to skip the destructor as well.
1575 if (isDestructorElided(State
, BTE
, LC
)) {
1576 State
= cleanupElidedDestructor(State
, BTE
, LC
);
1577 NodeBuilder
Bldr(Pred
, Dst
, *currBldrCtx
);
1578 PostImplicitCall
PP(D
.getDestructorDecl(getContext()),
1579 D
.getBindTemporaryExpr()->getBeginLoc(),
1580 Pred
->getLocationContext(), getCFGElementRef());
1581 Bldr
.generateNode(PP
, State
, Pred
);
1585 ExplodedNodeSet CleanDtorState
;
1586 StmtNodeBuilder
StmtBldr(Pred
, CleanDtorState
, *currBldrCtx
);
1587 StmtBldr
.generateNode(D
.getBindTemporaryExpr(), Pred
, State
);
1589 QualType T
= D
.getBindTemporaryExpr()->getSubExpr()->getType();
1590 // FIXME: Currently CleanDtorState can be empty here due to temporaries being
1591 // bound to default parameters.
1592 assert(CleanDtorState
.size() <= 1);
1593 ExplodedNode
*CleanPred
=
1594 CleanDtorState
.empty() ? Pred
: *CleanDtorState
.begin();
1596 EvalCallOptions CallOpts
;
1597 CallOpts
.IsTemporaryCtorOrDtor
= true;
1599 // FIXME: If we have no MR, we still need to unwrap the array to avoid
1600 // destroying the whole array at once.
1602 // For this case there is no universal solution as there is no way to
1603 // directly create an array of temporary objects. There are some expressions
1604 // however which can create temporary objects and have an array type.
1606 // E.g.: std::initializer_list<S>{S(), S()};
1608 // The expression above has a type of 'const struct S[2]' but it's a single
1609 // 'std::initializer_list<>'. The destructors of the 2 temporary 'S()'
1610 // objects will be called anyway, because they are 2 separate objects in 2
1611 // separate clusters, i.e.: not an array.
1613 // Now the 'std::initializer_list<>' is not an array either even though it
1614 // has the type of an array. The point is, we only want to invoke the
1615 // destructor for the initializer list once not twice or so.
1616 while (const ArrayType
*AT
= getContext().getAsArrayType(T
)) {
1617 T
= AT
->getElementType();
1619 // FIXME: Enable this flag once we handle this case properly.
1620 // CallOpts.IsArrayCtorOrDtor = true;
1623 // FIXME: We'd eventually need to makeElementRegion() trick here,
1624 // but for now we don't have the respective construction contexts,
1625 // so MR would always be null in this case. Do nothing for now.
1627 VisitCXXDestructor(T
, MR
, D
.getBindTemporaryExpr(),
1628 /*IsBase=*/false, CleanPred
, Dst
, CallOpts
);
1631 void ExprEngine::processCleanupTemporaryBranch(const CXXBindTemporaryExpr
*BTE
,
1632 NodeBuilderContext
&BldCtx
,
1634 ExplodedNodeSet
&Dst
,
1635 const CFGBlock
*DstT
,
1636 const CFGBlock
*DstF
) {
1637 BranchNodeBuilder
TempDtorBuilder(Pred
, Dst
, BldCtx
, DstT
, DstF
);
1638 ProgramStateRef State
= Pred
->getState();
1639 const LocationContext
*LC
= Pred
->getLocationContext();
1640 if (getObjectUnderConstruction(State
, BTE
, LC
)) {
1641 TempDtorBuilder
.markInfeasible(false);
1642 TempDtorBuilder
.generateNode(State
, true, Pred
);
1644 TempDtorBuilder
.markInfeasible(true);
1645 TempDtorBuilder
.generateNode(State
, false, Pred
);
1649 void ExprEngine::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr
*BTE
,
1650 ExplodedNodeSet
&PreVisit
,
1651 ExplodedNodeSet
&Dst
) {
1652 // This is a fallback solution in case we didn't have a construction
1653 // context when we were constructing the temporary. Otherwise the map should
1654 // have been populated there.
1655 if (!getAnalysisManager().options
.ShouldIncludeTemporaryDtorsInCFG
) {
1656 // In case we don't have temporary destructors in the CFG, do not mark
1657 // the initialization - we would otherwise never clean it up.
1661 StmtNodeBuilder
StmtBldr(PreVisit
, Dst
, *currBldrCtx
);
1662 for (ExplodedNode
*Node
: PreVisit
) {
1663 ProgramStateRef State
= Node
->getState();
1664 const LocationContext
*LC
= Node
->getLocationContext();
1665 if (!getObjectUnderConstruction(State
, BTE
, LC
)) {
1666 // FIXME: Currently the state might also already contain the marker due to
1667 // incorrect handling of temporaries bound to default parameters; for
1668 // those, we currently skip the CXXBindTemporaryExpr but rely on adding
1669 // temporary destructor nodes.
1670 State
= addObjectUnderConstruction(State
, BTE
, LC
, UnknownVal());
1672 StmtBldr
.generateNode(BTE
, Node
, State
);
1676 ProgramStateRef
ExprEngine::escapeValues(ProgramStateRef State
,
1678 PointerEscapeKind K
,
1679 const CallEvent
*Call
) const {
1680 class CollectReachableSymbolsCallback final
: public SymbolVisitor
{
1681 InvalidatedSymbols
&Symbols
;
1684 explicit CollectReachableSymbolsCallback(InvalidatedSymbols
&Symbols
)
1685 : Symbols(Symbols
) {}
1687 const InvalidatedSymbols
&getSymbols() const { return Symbols
; }
1689 bool VisitSymbol(SymbolRef Sym
) override
{
1690 Symbols
.insert(Sym
);
1694 InvalidatedSymbols Symbols
;
1695 CollectReachableSymbolsCallback
CallBack(Symbols
);
1697 State
->scanReachableSymbols(V
, CallBack
);
1699 return getCheckerManager().runCheckersForPointerEscape(
1700 State
, CallBack
.getSymbols(), Call
, K
, nullptr);
1703 void ExprEngine::Visit(const Stmt
*S
, ExplodedNode
*Pred
,
1704 ExplodedNodeSet
&DstTop
) {
1705 PrettyStackTraceLoc
CrashInfo(getContext().getSourceManager(),
1706 S
->getBeginLoc(), "Error evaluating statement");
1707 ExplodedNodeSet Dst
;
1708 StmtNodeBuilder
Bldr(Pred
, DstTop
, *currBldrCtx
);
1710 assert(!isa
<Expr
>(S
) || S
== cast
<Expr
>(S
)->IgnoreParens());
1712 switch (S
->getStmtClass()) {
1713 // C++, OpenMP and ARC stuff we don't support yet.
1714 case Stmt::CXXDependentScopeMemberExprClass
:
1715 case Stmt::CXXTryStmtClass
:
1716 case Stmt::CXXTypeidExprClass
:
1717 case Stmt::CXXUuidofExprClass
:
1718 case Stmt::CXXFoldExprClass
:
1719 case Stmt::MSPropertyRefExprClass
:
1720 case Stmt::MSPropertySubscriptExprClass
:
1721 case Stmt::CXXUnresolvedConstructExprClass
:
1722 case Stmt::DependentScopeDeclRefExprClass
:
1723 case Stmt::ArrayTypeTraitExprClass
:
1724 case Stmt::ExpressionTraitExprClass
:
1725 case Stmt::UnresolvedLookupExprClass
:
1726 case Stmt::UnresolvedMemberExprClass
:
1727 case Stmt::TypoExprClass
:
1728 case Stmt::RecoveryExprClass
:
1729 case Stmt::CXXNoexceptExprClass
:
1730 case Stmt::PackExpansionExprClass
:
1731 case Stmt::SubstNonTypeTemplateParmPackExprClass
:
1732 case Stmt::FunctionParmPackExprClass
:
1733 case Stmt::CoroutineBodyStmtClass
:
1734 case Stmt::CoawaitExprClass
:
1735 case Stmt::DependentCoawaitExprClass
:
1736 case Stmt::CoreturnStmtClass
:
1737 case Stmt::CoyieldExprClass
:
1738 case Stmt::SEHTryStmtClass
:
1739 case Stmt::SEHExceptStmtClass
:
1740 case Stmt::SEHLeaveStmtClass
:
1741 case Stmt::SEHFinallyStmtClass
:
1742 case Stmt::OMPCanonicalLoopClass
:
1743 case Stmt::OMPParallelDirectiveClass
:
1744 case Stmt::OMPSimdDirectiveClass
:
1745 case Stmt::OMPForDirectiveClass
:
1746 case Stmt::OMPForSimdDirectiveClass
:
1747 case Stmt::OMPSectionsDirectiveClass
:
1748 case Stmt::OMPSectionDirectiveClass
:
1749 case Stmt::OMPScopeDirectiveClass
:
1750 case Stmt::OMPSingleDirectiveClass
:
1751 case Stmt::OMPMasterDirectiveClass
:
1752 case Stmt::OMPCriticalDirectiveClass
:
1753 case Stmt::OMPParallelForDirectiveClass
:
1754 case Stmt::OMPParallelForSimdDirectiveClass
:
1755 case Stmt::OMPParallelSectionsDirectiveClass
:
1756 case Stmt::OMPParallelMasterDirectiveClass
:
1757 case Stmt::OMPParallelMaskedDirectiveClass
:
1758 case Stmt::OMPTaskDirectiveClass
:
1759 case Stmt::OMPTaskyieldDirectiveClass
:
1760 case Stmt::OMPBarrierDirectiveClass
:
1761 case Stmt::OMPTaskwaitDirectiveClass
:
1762 case Stmt::OMPErrorDirectiveClass
:
1763 case Stmt::OMPTaskgroupDirectiveClass
:
1764 case Stmt::OMPFlushDirectiveClass
:
1765 case Stmt::OMPDepobjDirectiveClass
:
1766 case Stmt::OMPScanDirectiveClass
:
1767 case Stmt::OMPOrderedDirectiveClass
:
1768 case Stmt::OMPAtomicDirectiveClass
:
1769 case Stmt::OMPTargetDirectiveClass
:
1770 case Stmt::OMPTargetDataDirectiveClass
:
1771 case Stmt::OMPTargetEnterDataDirectiveClass
:
1772 case Stmt::OMPTargetExitDataDirectiveClass
:
1773 case Stmt::OMPTargetParallelDirectiveClass
:
1774 case Stmt::OMPTargetParallelForDirectiveClass
:
1775 case Stmt::OMPTargetUpdateDirectiveClass
:
1776 case Stmt::OMPTeamsDirectiveClass
:
1777 case Stmt::OMPCancellationPointDirectiveClass
:
1778 case Stmt::OMPCancelDirectiveClass
:
1779 case Stmt::OMPTaskLoopDirectiveClass
:
1780 case Stmt::OMPTaskLoopSimdDirectiveClass
:
1781 case Stmt::OMPMasterTaskLoopDirectiveClass
:
1782 case Stmt::OMPMaskedTaskLoopDirectiveClass
:
1783 case Stmt::OMPMasterTaskLoopSimdDirectiveClass
:
1784 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass
:
1785 case Stmt::OMPParallelMasterTaskLoopDirectiveClass
:
1786 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass
:
1787 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass
:
1788 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass
:
1789 case Stmt::OMPDistributeDirectiveClass
:
1790 case Stmt::OMPDistributeParallelForDirectiveClass
:
1791 case Stmt::OMPDistributeParallelForSimdDirectiveClass
:
1792 case Stmt::OMPDistributeSimdDirectiveClass
:
1793 case Stmt::OMPTargetParallelForSimdDirectiveClass
:
1794 case Stmt::OMPTargetSimdDirectiveClass
:
1795 case Stmt::OMPTeamsDistributeDirectiveClass
:
1796 case Stmt::OMPTeamsDistributeSimdDirectiveClass
:
1797 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass
:
1798 case Stmt::OMPTeamsDistributeParallelForDirectiveClass
:
1799 case Stmt::OMPTargetTeamsDirectiveClass
:
1800 case Stmt::OMPTargetTeamsDistributeDirectiveClass
:
1801 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass
:
1802 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass
:
1803 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass
:
1804 case Stmt::OMPTileDirectiveClass
:
1805 case Stmt::OMPInteropDirectiveClass
:
1806 case Stmt::OMPDispatchDirectiveClass
:
1807 case Stmt::OMPMaskedDirectiveClass
:
1808 case Stmt::OMPGenericLoopDirectiveClass
:
1809 case Stmt::OMPTeamsGenericLoopDirectiveClass
:
1810 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass
:
1811 case Stmt::OMPParallelGenericLoopDirectiveClass
:
1812 case Stmt::OMPTargetParallelGenericLoopDirectiveClass
:
1813 case Stmt::CapturedStmtClass
:
1814 case Stmt::OMPUnrollDirectiveClass
:
1815 case Stmt::OMPMetaDirectiveClass
: {
1816 const ExplodedNode
*node
= Bldr
.generateSink(S
, Pred
, Pred
->getState());
1817 Engine
.addAbortedBlock(node
, currBldrCtx
->getBlock());
1821 case Stmt::ParenExprClass
:
1822 llvm_unreachable("ParenExprs already handled.");
1823 case Stmt::GenericSelectionExprClass
:
1824 llvm_unreachable("GenericSelectionExprs already handled.");
1825 // Cases that should never be evaluated simply because they shouldn't
1826 // appear in the CFG.
1827 case Stmt::BreakStmtClass
:
1828 case Stmt::CaseStmtClass
:
1829 case Stmt::CompoundStmtClass
:
1830 case Stmt::ContinueStmtClass
:
1831 case Stmt::CXXForRangeStmtClass
:
1832 case Stmt::DefaultStmtClass
:
1833 case Stmt::DoStmtClass
:
1834 case Stmt::ForStmtClass
:
1835 case Stmt::GotoStmtClass
:
1836 case Stmt::IfStmtClass
:
1837 case Stmt::IndirectGotoStmtClass
:
1838 case Stmt::LabelStmtClass
:
1839 case Stmt::NoStmtClass
:
1840 case Stmt::NullStmtClass
:
1841 case Stmt::SwitchStmtClass
:
1842 case Stmt::WhileStmtClass
:
1843 case Expr::MSDependentExistsStmtClass
:
1844 llvm_unreachable("Stmt should not be in analyzer evaluation loop");
1845 case Stmt::ImplicitValueInitExprClass
:
1846 // These nodes are shared in the CFG and would case caching out.
1847 // Moreover, no additional evaluation required for them, the
1848 // analyzer can reconstruct these values from the AST.
1849 llvm_unreachable("Should be pruned from CFG");
1851 case Stmt::ObjCSubscriptRefExprClass
:
1852 case Stmt::ObjCPropertyRefExprClass
:
1853 llvm_unreachable("These are handled by PseudoObjectExpr");
1855 case Stmt::GNUNullExprClass
: {
1856 // GNU __null is a pointer-width integer, not an actual pointer.
1857 ProgramStateRef state
= Pred
->getState();
1858 state
= state
->BindExpr(
1859 S
, Pred
->getLocationContext(),
1860 svalBuilder
.makeIntValWithWidth(getContext().VoidPtrTy
, 0));
1861 Bldr
.generateNode(S
, Pred
, state
);
1865 case Stmt::ObjCAtSynchronizedStmtClass
:
1866 Bldr
.takeNodes(Pred
);
1867 VisitObjCAtSynchronizedStmt(cast
<ObjCAtSynchronizedStmt
>(S
), Pred
, Dst
);
1871 case Expr::ConstantExprClass
:
1872 case Stmt::ExprWithCleanupsClass
:
1873 // Handled due to fully linearised CFG.
1876 case Stmt::CXXBindTemporaryExprClass
: {
1877 Bldr
.takeNodes(Pred
);
1878 ExplodedNodeSet PreVisit
;
1879 getCheckerManager().runCheckersForPreStmt(PreVisit
, Pred
, S
, *this);
1880 ExplodedNodeSet Next
;
1881 VisitCXXBindTemporaryExpr(cast
<CXXBindTemporaryExpr
>(S
), PreVisit
, Next
);
1882 getCheckerManager().runCheckersForPostStmt(Dst
, Next
, S
, *this);
1887 case Stmt::ArrayInitLoopExprClass
:
1888 Bldr
.takeNodes(Pred
);
1889 VisitArrayInitLoopExpr(cast
<ArrayInitLoopExpr
>(S
), Pred
, Dst
);
1892 // Cases not handled yet; but will handle some day.
1893 case Stmt::DesignatedInitExprClass
:
1894 case Stmt::DesignatedInitUpdateExprClass
:
1895 case Stmt::ArrayInitIndexExprClass
:
1896 case Stmt::ExtVectorElementExprClass
:
1897 case Stmt::ImaginaryLiteralClass
:
1898 case Stmt::ObjCAtCatchStmtClass
:
1899 case Stmt::ObjCAtFinallyStmtClass
:
1900 case Stmt::ObjCAtTryStmtClass
:
1901 case Stmt::ObjCAutoreleasePoolStmtClass
:
1902 case Stmt::ObjCEncodeExprClass
:
1903 case Stmt::ObjCIsaExprClass
:
1904 case Stmt::ObjCProtocolExprClass
:
1905 case Stmt::ObjCSelectorExprClass
:
1906 case Stmt::ParenListExprClass
:
1907 case Stmt::ShuffleVectorExprClass
:
1908 case Stmt::ConvertVectorExprClass
:
1909 case Stmt::VAArgExprClass
:
1910 case Stmt::CUDAKernelCallExprClass
:
1911 case Stmt::OpaqueValueExprClass
:
1912 case Stmt::AsTypeExprClass
:
1913 case Stmt::ConceptSpecializationExprClass
:
1914 case Stmt::CXXRewrittenBinaryOperatorClass
:
1915 case Stmt::RequiresExprClass
:
1916 case Expr::CXXParenListInitExprClass
:
1919 // Cases we intentionally don't evaluate, since they don't need
1920 // to be explicitly evaluated.
1921 case Stmt::PredefinedExprClass
:
1922 case Stmt::AddrLabelExprClass
:
1923 case Stmt::AttributedStmtClass
:
1924 case Stmt::IntegerLiteralClass
:
1925 case Stmt::FixedPointLiteralClass
:
1926 case Stmt::CharacterLiteralClass
:
1927 case Stmt::CXXScalarValueInitExprClass
:
1928 case Stmt::CXXBoolLiteralExprClass
:
1929 case Stmt::ObjCBoolLiteralExprClass
:
1930 case Stmt::ObjCAvailabilityCheckExprClass
:
1931 case Stmt::FloatingLiteralClass
:
1932 case Stmt::NoInitExprClass
:
1933 case Stmt::SizeOfPackExprClass
:
1934 case Stmt::StringLiteralClass
:
1935 case Stmt::SourceLocExprClass
:
1936 case Stmt::ObjCStringLiteralClass
:
1937 case Stmt::CXXPseudoDestructorExprClass
:
1938 case Stmt::SubstNonTypeTemplateParmExprClass
:
1939 case Stmt::CXXNullPtrLiteralExprClass
:
1940 case Stmt::OMPArraySectionExprClass
:
1941 case Stmt::OMPArrayShapingExprClass
:
1942 case Stmt::OMPIteratorExprClass
:
1943 case Stmt::SYCLUniqueStableNameExprClass
:
1944 case Stmt::TypeTraitExprClass
: {
1945 Bldr
.takeNodes(Pred
);
1946 ExplodedNodeSet preVisit
;
1947 getCheckerManager().runCheckersForPreStmt(preVisit
, Pred
, S
, *this);
1948 getCheckerManager().runCheckersForPostStmt(Dst
, preVisit
, S
, *this);
1953 case Stmt::CXXDefaultArgExprClass
:
1954 case Stmt::CXXDefaultInitExprClass
: {
1955 Bldr
.takeNodes(Pred
);
1956 ExplodedNodeSet PreVisit
;
1957 getCheckerManager().runCheckersForPreStmt(PreVisit
, Pred
, S
, *this);
1959 ExplodedNodeSet Tmp
;
1960 StmtNodeBuilder
Bldr2(PreVisit
, Tmp
, *currBldrCtx
);
1963 if (const auto *DefE
= dyn_cast
<CXXDefaultArgExpr
>(S
))
1964 ArgE
= DefE
->getExpr();
1965 else if (const auto *DefE
= dyn_cast
<CXXDefaultInitExpr
>(S
))
1966 ArgE
= DefE
->getExpr();
1968 llvm_unreachable("unknown constant wrapper kind");
1970 bool IsTemporary
= false;
1971 if (const auto *MTE
= dyn_cast
<MaterializeTemporaryExpr
>(ArgE
)) {
1972 ArgE
= MTE
->getSubExpr();
1976 std::optional
<SVal
> ConstantVal
= svalBuilder
.getConstantVal(ArgE
);
1978 ConstantVal
= UnknownVal();
1980 const LocationContext
*LCtx
= Pred
->getLocationContext();
1981 for (const auto I
: PreVisit
) {
1982 ProgramStateRef State
= I
->getState();
1983 State
= State
->BindExpr(S
, LCtx
, *ConstantVal
);
1985 State
= createTemporaryRegionIfNeeded(State
, LCtx
,
1988 Bldr2
.generateNode(S
, I
, State
);
1991 getCheckerManager().runCheckersForPostStmt(Dst
, Tmp
, S
, *this);
1996 // Cases we evaluate as opaque expressions, conjuring a symbol.
1997 case Stmt::CXXStdInitializerListExprClass
:
1998 case Expr::ObjCArrayLiteralClass
:
1999 case Expr::ObjCDictionaryLiteralClass
:
2000 case Expr::ObjCBoxedExprClass
: {
2001 Bldr
.takeNodes(Pred
);
2003 ExplodedNodeSet preVisit
;
2004 getCheckerManager().runCheckersForPreStmt(preVisit
, Pred
, S
, *this);
2006 ExplodedNodeSet Tmp
;
2007 StmtNodeBuilder
Bldr2(preVisit
, Tmp
, *currBldrCtx
);
2009 const auto *Ex
= cast
<Expr
>(S
);
2010 QualType resultType
= Ex
->getType();
2012 for (const auto N
: preVisit
) {
2013 const LocationContext
*LCtx
= N
->getLocationContext();
2014 SVal result
= svalBuilder
.conjureSymbolVal(nullptr, Ex
, LCtx
,
2016 currBldrCtx
->blockCount());
2017 ProgramStateRef State
= N
->getState()->BindExpr(Ex
, LCtx
, result
);
2019 // Escape pointers passed into the list, unless it's an ObjC boxed
2020 // expression which is not a boxable C structure.
2021 if (!(isa
<ObjCBoxedExpr
>(Ex
) &&
2022 !cast
<ObjCBoxedExpr
>(Ex
)->getSubExpr()
2023 ->getType()->isRecordType()))
2024 for (auto Child
: Ex
->children()) {
2026 SVal Val
= State
->getSVal(Child
, LCtx
);
2027 State
= escapeValues(State
, Val
, PSK_EscapeOther
);
2030 Bldr2
.generateNode(S
, N
, State
);
2033 getCheckerManager().runCheckersForPostStmt(Dst
, Tmp
, S
, *this);
2038 case Stmt::ArraySubscriptExprClass
:
2039 Bldr
.takeNodes(Pred
);
2040 VisitArraySubscriptExpr(cast
<ArraySubscriptExpr
>(S
), Pred
, Dst
);
2044 case Stmt::MatrixSubscriptExprClass
:
2045 llvm_unreachable("Support for MatrixSubscriptExpr is not implemented.");
2048 case Stmt::GCCAsmStmtClass
:
2049 Bldr
.takeNodes(Pred
);
2050 VisitGCCAsmStmt(cast
<GCCAsmStmt
>(S
), Pred
, Dst
);
2054 case Stmt::MSAsmStmtClass
:
2055 Bldr
.takeNodes(Pred
);
2056 VisitMSAsmStmt(cast
<MSAsmStmt
>(S
), Pred
, Dst
);
2060 case Stmt::BlockExprClass
:
2061 Bldr
.takeNodes(Pred
);
2062 VisitBlockExpr(cast
<BlockExpr
>(S
), Pred
, Dst
);
2066 case Stmt::LambdaExprClass
:
2067 if (AMgr
.options
.ShouldInlineLambdas
) {
2068 Bldr
.takeNodes(Pred
);
2069 VisitLambdaExpr(cast
<LambdaExpr
>(S
), Pred
, Dst
);
2072 const ExplodedNode
*node
= Bldr
.generateSink(S
, Pred
, Pred
->getState());
2073 Engine
.addAbortedBlock(node
, currBldrCtx
->getBlock());
2077 case Stmt::BinaryOperatorClass
: {
2078 const auto *B
= cast
<BinaryOperator
>(S
);
2079 if (B
->isLogicalOp()) {
2080 Bldr
.takeNodes(Pred
);
2081 VisitLogicalExpr(B
, Pred
, Dst
);
2085 else if (B
->getOpcode() == BO_Comma
) {
2086 ProgramStateRef state
= Pred
->getState();
2087 Bldr
.generateNode(B
, Pred
,
2088 state
->BindExpr(B
, Pred
->getLocationContext(),
2089 state
->getSVal(B
->getRHS(),
2090 Pred
->getLocationContext())));
2094 Bldr
.takeNodes(Pred
);
2096 if (AMgr
.options
.ShouldEagerlyAssume
&&
2097 (B
->isRelationalOp() || B
->isEqualityOp())) {
2098 ExplodedNodeSet Tmp
;
2099 VisitBinaryOperator(cast
<BinaryOperator
>(S
), Pred
, Tmp
);
2100 evalEagerlyAssumeBinOpBifurcation(Dst
, Tmp
, cast
<Expr
>(S
));
2103 VisitBinaryOperator(cast
<BinaryOperator
>(S
), Pred
, Dst
);
2109 case Stmt::CXXOperatorCallExprClass
: {
2110 const auto *OCE
= cast
<CXXOperatorCallExpr
>(S
);
2112 // For instance method operators, make sure the 'this' argument has a
2114 const Decl
*Callee
= OCE
->getCalleeDecl();
2115 if (const auto *MD
= dyn_cast_or_null
<CXXMethodDecl
>(Callee
)) {
2116 if (MD
->isInstance()) {
2117 ProgramStateRef State
= Pred
->getState();
2118 const LocationContext
*LCtx
= Pred
->getLocationContext();
2119 ProgramStateRef NewState
=
2120 createTemporaryRegionIfNeeded(State
, LCtx
, OCE
->getArg(0));
2121 if (NewState
!= State
) {
2122 Pred
= Bldr
.generateNode(OCE
, Pred
, NewState
, /*tag=*/nullptr,
2123 ProgramPoint::PreStmtKind
);
2124 // Did we cache out?
2133 case Stmt::CallExprClass
:
2134 case Stmt::CXXMemberCallExprClass
:
2135 case Stmt::UserDefinedLiteralClass
:
2136 Bldr
.takeNodes(Pred
);
2137 VisitCallExpr(cast
<CallExpr
>(S
), Pred
, Dst
);
2141 case Stmt::CXXCatchStmtClass
:
2142 Bldr
.takeNodes(Pred
);
2143 VisitCXXCatchStmt(cast
<CXXCatchStmt
>(S
), Pred
, Dst
);
2147 case Stmt::CXXTemporaryObjectExprClass
:
2148 case Stmt::CXXConstructExprClass
:
2149 Bldr
.takeNodes(Pred
);
2150 VisitCXXConstructExpr(cast
<CXXConstructExpr
>(S
), Pred
, Dst
);
2154 case Stmt::CXXInheritedCtorInitExprClass
:
2155 Bldr
.takeNodes(Pred
);
2156 VisitCXXInheritedCtorInitExpr(cast
<CXXInheritedCtorInitExpr
>(S
), Pred
,
2161 case Stmt::CXXNewExprClass
: {
2162 Bldr
.takeNodes(Pred
);
2164 ExplodedNodeSet PreVisit
;
2165 getCheckerManager().runCheckersForPreStmt(PreVisit
, Pred
, S
, *this);
2167 ExplodedNodeSet PostVisit
;
2168 for (const auto i
: PreVisit
)
2169 VisitCXXNewExpr(cast
<CXXNewExpr
>(S
), i
, PostVisit
);
2171 getCheckerManager().runCheckersForPostStmt(Dst
, PostVisit
, S
, *this);
2176 case Stmt::CXXDeleteExprClass
: {
2177 Bldr
.takeNodes(Pred
);
2178 ExplodedNodeSet PreVisit
;
2179 const auto *CDE
= cast
<CXXDeleteExpr
>(S
);
2180 getCheckerManager().runCheckersForPreStmt(PreVisit
, Pred
, S
, *this);
2181 ExplodedNodeSet PostVisit
;
2182 getCheckerManager().runCheckersForPostStmt(PostVisit
, PreVisit
, S
, *this);
2184 for (const auto i
: PostVisit
)
2185 VisitCXXDeleteExpr(CDE
, i
, Dst
);
2190 // FIXME: ChooseExpr is really a constant. We need to fix
2191 // the CFG do not model them as explicit control-flow.
2193 case Stmt::ChooseExprClass
: { // __builtin_choose_expr
2194 Bldr
.takeNodes(Pred
);
2195 const auto *C
= cast
<ChooseExpr
>(S
);
2196 VisitGuardedExpr(C
, C
->getLHS(), C
->getRHS(), Pred
, Dst
);
2201 case Stmt::CompoundAssignOperatorClass
:
2202 Bldr
.takeNodes(Pred
);
2203 VisitBinaryOperator(cast
<BinaryOperator
>(S
), Pred
, Dst
);
2207 case Stmt::CompoundLiteralExprClass
:
2208 Bldr
.takeNodes(Pred
);
2209 VisitCompoundLiteralExpr(cast
<CompoundLiteralExpr
>(S
), Pred
, Dst
);
2213 case Stmt::BinaryConditionalOperatorClass
:
2214 case Stmt::ConditionalOperatorClass
: { // '?' operator
2215 Bldr
.takeNodes(Pred
);
2216 const auto *C
= cast
<AbstractConditionalOperator
>(S
);
2217 VisitGuardedExpr(C
, C
->getTrueExpr(), C
->getFalseExpr(), Pred
, Dst
);
2222 case Stmt::CXXThisExprClass
:
2223 Bldr
.takeNodes(Pred
);
2224 VisitCXXThisExpr(cast
<CXXThisExpr
>(S
), Pred
, Dst
);
2228 case Stmt::DeclRefExprClass
: {
2229 Bldr
.takeNodes(Pred
);
2230 const auto *DE
= cast
<DeclRefExpr
>(S
);
2231 VisitCommonDeclRefExpr(DE
, DE
->getDecl(), Pred
, Dst
);
2236 case Stmt::DeclStmtClass
:
2237 Bldr
.takeNodes(Pred
);
2238 VisitDeclStmt(cast
<DeclStmt
>(S
), Pred
, Dst
);
2242 case Stmt::ImplicitCastExprClass
:
2243 case Stmt::CStyleCastExprClass
:
2244 case Stmt::CXXStaticCastExprClass
:
2245 case Stmt::CXXDynamicCastExprClass
:
2246 case Stmt::CXXReinterpretCastExprClass
:
2247 case Stmt::CXXConstCastExprClass
:
2248 case Stmt::CXXFunctionalCastExprClass
:
2249 case Stmt::BuiltinBitCastExprClass
:
2250 case Stmt::ObjCBridgedCastExprClass
:
2251 case Stmt::CXXAddrspaceCastExprClass
: {
2252 Bldr
.takeNodes(Pred
);
2253 const auto *C
= cast
<CastExpr
>(S
);
2254 ExplodedNodeSet dstExpr
;
2255 VisitCast(C
, C
->getSubExpr(), Pred
, dstExpr
);
2257 // Handle the postvisit checks.
2258 getCheckerManager().runCheckersForPostStmt(Dst
, dstExpr
, C
, *this);
2263 case Expr::MaterializeTemporaryExprClass
: {
2264 Bldr
.takeNodes(Pred
);
2265 const auto *MTE
= cast
<MaterializeTemporaryExpr
>(S
);
2266 ExplodedNodeSet dstPrevisit
;
2267 getCheckerManager().runCheckersForPreStmt(dstPrevisit
, Pred
, MTE
, *this);
2268 ExplodedNodeSet dstExpr
;
2269 for (const auto i
: dstPrevisit
)
2270 CreateCXXTemporaryObject(MTE
, i
, dstExpr
);
2271 getCheckerManager().runCheckersForPostStmt(Dst
, dstExpr
, MTE
, *this);
2276 case Stmt::InitListExprClass
:
2277 Bldr
.takeNodes(Pred
);
2278 VisitInitListExpr(cast
<InitListExpr
>(S
), Pred
, Dst
);
2282 case Stmt::MemberExprClass
:
2283 Bldr
.takeNodes(Pred
);
2284 VisitMemberExpr(cast
<MemberExpr
>(S
), Pred
, Dst
);
2288 case Stmt::AtomicExprClass
:
2289 Bldr
.takeNodes(Pred
);
2290 VisitAtomicExpr(cast
<AtomicExpr
>(S
), Pred
, Dst
);
2294 case Stmt::ObjCIvarRefExprClass
:
2295 Bldr
.takeNodes(Pred
);
2296 VisitLvalObjCIvarRefExpr(cast
<ObjCIvarRefExpr
>(S
), Pred
, Dst
);
2300 case Stmt::ObjCForCollectionStmtClass
:
2301 Bldr
.takeNodes(Pred
);
2302 VisitObjCForCollectionStmt(cast
<ObjCForCollectionStmt
>(S
), Pred
, Dst
);
2306 case Stmt::ObjCMessageExprClass
:
2307 Bldr
.takeNodes(Pred
);
2308 VisitObjCMessage(cast
<ObjCMessageExpr
>(S
), Pred
, Dst
);
2312 case Stmt::ObjCAtThrowStmtClass
:
2313 case Stmt::CXXThrowExprClass
:
2314 // FIXME: This is not complete. We basically treat @throw as
2316 Bldr
.generateSink(S
, Pred
, Pred
->getState());
2319 case Stmt::ReturnStmtClass
:
2320 Bldr
.takeNodes(Pred
);
2321 VisitReturnStmt(cast
<ReturnStmt
>(S
), Pred
, Dst
);
2325 case Stmt::OffsetOfExprClass
: {
2326 Bldr
.takeNodes(Pred
);
2327 ExplodedNodeSet PreVisit
;
2328 getCheckerManager().runCheckersForPreStmt(PreVisit
, Pred
, S
, *this);
2330 ExplodedNodeSet PostVisit
;
2331 for (const auto Node
: PreVisit
)
2332 VisitOffsetOfExpr(cast
<OffsetOfExpr
>(S
), Node
, PostVisit
);
2334 getCheckerManager().runCheckersForPostStmt(Dst
, PostVisit
, S
, *this);
2339 case Stmt::UnaryExprOrTypeTraitExprClass
:
2340 Bldr
.takeNodes(Pred
);
2341 VisitUnaryExprOrTypeTraitExpr(cast
<UnaryExprOrTypeTraitExpr
>(S
),
2346 case Stmt::StmtExprClass
: {
2347 const auto *SE
= cast
<StmtExpr
>(S
);
2349 if (SE
->getSubStmt()->body_empty()) {
2350 // Empty statement expression.
2351 assert(SE
->getType() == getContext().VoidTy
2352 && "Empty statement expression must have void type.");
2356 if (const auto *LastExpr
=
2357 dyn_cast
<Expr
>(*SE
->getSubStmt()->body_rbegin())) {
2358 ProgramStateRef state
= Pred
->getState();
2359 Bldr
.generateNode(SE
, Pred
,
2360 state
->BindExpr(SE
, Pred
->getLocationContext(),
2361 state
->getSVal(LastExpr
,
2362 Pred
->getLocationContext())));
2367 case Stmt::UnaryOperatorClass
: {
2368 Bldr
.takeNodes(Pred
);
2369 const auto *U
= cast
<UnaryOperator
>(S
);
2370 if (AMgr
.options
.ShouldEagerlyAssume
&& (U
->getOpcode() == UO_LNot
)) {
2371 ExplodedNodeSet Tmp
;
2372 VisitUnaryOperator(U
, Pred
, Tmp
);
2373 evalEagerlyAssumeBinOpBifurcation(Dst
, Tmp
, U
);
2376 VisitUnaryOperator(U
, Pred
, Dst
);
2381 case Stmt::PseudoObjectExprClass
: {
2382 Bldr
.takeNodes(Pred
);
2383 ProgramStateRef state
= Pred
->getState();
2384 const auto *PE
= cast
<PseudoObjectExpr
>(S
);
2385 if (const Expr
*Result
= PE
->getResultExpr()) {
2386 SVal V
= state
->getSVal(Result
, Pred
->getLocationContext());
2387 Bldr
.generateNode(S
, Pred
,
2388 state
->BindExpr(S
, Pred
->getLocationContext(), V
));
2391 Bldr
.generateNode(S
, Pred
,
2392 state
->BindExpr(S
, Pred
->getLocationContext(),
2399 case Expr::ObjCIndirectCopyRestoreExprClass
: {
2400 // ObjCIndirectCopyRestoreExpr implies passing a temporary for
2401 // correctness of lifetime management. Due to limited analysis
2402 // of ARC, this is implemented as direct arg passing.
2403 Bldr
.takeNodes(Pred
);
2404 ProgramStateRef state
= Pred
->getState();
2405 const auto *OIE
= cast
<ObjCIndirectCopyRestoreExpr
>(S
);
2406 const Expr
*E
= OIE
->getSubExpr();
2407 SVal V
= state
->getSVal(E
, Pred
->getLocationContext());
2408 Bldr
.generateNode(S
, Pred
,
2409 state
->BindExpr(S
, Pred
->getLocationContext(), V
));
2416 bool ExprEngine::replayWithoutInlining(ExplodedNode
*N
,
2417 const LocationContext
*CalleeLC
) {
2418 const StackFrameContext
*CalleeSF
= CalleeLC
->getStackFrame();
2419 const StackFrameContext
*CallerSF
= CalleeSF
->getParent()->getStackFrame();
2420 assert(CalleeSF
&& CallerSF
);
2421 ExplodedNode
*BeforeProcessingCall
= nullptr;
2422 const Stmt
*CE
= CalleeSF
->getCallSite();
2424 // Find the first node before we started processing the call expression.
2426 ProgramPoint L
= N
->getLocation();
2427 BeforeProcessingCall
= N
;
2428 N
= N
->pred_empty() ? nullptr : *(N
->pred_begin());
2430 // Skip the nodes corresponding to the inlined code.
2431 if (L
.getStackFrame() != CallerSF
)
2433 // We reached the caller. Find the node right before we started
2434 // processing the call.
2435 if (L
.isPurgeKind())
2437 if (L
.getAs
<PreImplicitCall
>())
2439 if (L
.getAs
<CallEnter
>())
2441 if (std::optional
<StmtPoint
> SP
= L
.getAs
<StmtPoint
>())
2442 if (SP
->getStmt() == CE
)
2447 if (!BeforeProcessingCall
)
2450 // TODO: Clean up the unneeded nodes.
2452 // Build an Epsilon node from which we will restart the analyzes.
2453 // Note that CE is permitted to be NULL!
2454 static SimpleProgramPointTag
PT("ExprEngine", "Replay without inlining");
2455 ProgramPoint NewNodeLoc
= EpsilonPoint(
2456 BeforeProcessingCall
->getLocationContext(), CE
, nullptr, &PT
);
2457 // Add the special flag to GDM to signal retrying with no inlining.
2458 // Note, changing the state ensures that we are not going to cache out.
2459 ProgramStateRef NewNodeState
= BeforeProcessingCall
->getState();
2461 NewNodeState
->set
<ReplayWithoutInlining
>(const_cast<Stmt
*>(CE
));
2463 // Make the new node a successor of BeforeProcessingCall.
2465 ExplodedNode
*NewNode
= G
.getNode(NewNodeLoc
, NewNodeState
, false, &IsNew
);
2466 // We cached out at this point. Caching out is common due to us backtracking
2467 // from the inlined function, which might spawn several paths.
2471 NewNode
->addPredecessor(BeforeProcessingCall
, G
);
2473 // Add the new node to the work list.
2474 Engine
.enqueueStmtNode(NewNode
, CalleeSF
->getCallSiteBlock(),
2475 CalleeSF
->getIndex());
2476 NumTimesRetriedWithoutInlining
++;
2480 /// Block entrance. (Update counters).
2481 void ExprEngine::processCFGBlockEntrance(const BlockEdge
&L
,
2482 NodeBuilderWithSinks
&nodeBuilder
,
2483 ExplodedNode
*Pred
) {
2484 PrettyStackTraceLocationContext
CrashInfo(Pred
->getLocationContext());
2485 // If we reach a loop which has a known bound (and meets
2486 // other constraints) then consider completely unrolling it.
2487 if(AMgr
.options
.ShouldUnrollLoops
) {
2488 unsigned maxBlockVisitOnPath
= AMgr
.options
.maxBlockVisitOnPath
;
2489 const Stmt
*Term
= nodeBuilder
.getContext().getBlock()->getTerminatorStmt();
2491 ProgramStateRef NewState
= updateLoopStack(Term
, AMgr
.getASTContext(),
2492 Pred
, maxBlockVisitOnPath
);
2493 if (NewState
!= Pred
->getState()) {
2494 ExplodedNode
*UpdatedNode
= nodeBuilder
.generateNode(NewState
, Pred
);
2500 // Is we are inside an unrolled loop then no need the check the counters.
2501 if(isUnrolledState(Pred
->getState()))
2505 // If this block is terminated by a loop and it has already been visited the
2506 // maximum number of times, widen the loop.
2507 unsigned int BlockCount
= nodeBuilder
.getContext().blockCount();
2508 if (BlockCount
== AMgr
.options
.maxBlockVisitOnPath
- 1 &&
2509 AMgr
.options
.ShouldWidenLoops
) {
2510 const Stmt
*Term
= nodeBuilder
.getContext().getBlock()->getTerminatorStmt();
2511 if (!isa_and_nonnull
<ForStmt
, WhileStmt
, DoStmt
>(Term
))
2514 const LocationContext
*LCtx
= Pred
->getLocationContext();
2515 ProgramStateRef WidenedState
=
2516 getWidenedLoopState(Pred
->getState(), LCtx
, BlockCount
, Term
);
2517 nodeBuilder
.generateNode(WidenedState
, Pred
);
2521 // FIXME: Refactor this into a checker.
2522 if (BlockCount
>= AMgr
.options
.maxBlockVisitOnPath
) {
2523 static SimpleProgramPointTag
tag(TagProviderName
, "Block count exceeded");
2524 const ExplodedNode
*Sink
=
2525 nodeBuilder
.generateSink(Pred
->getState(), Pred
, &tag
);
2527 // Check if we stopped at the top level function or not.
2528 // Root node should have the location context of the top most function.
2529 const LocationContext
*CalleeLC
= Pred
->getLocation().getLocationContext();
2530 const LocationContext
*CalleeSF
= CalleeLC
->getStackFrame();
2531 const LocationContext
*RootLC
=
2532 (*G
.roots_begin())->getLocation().getLocationContext();
2533 if (RootLC
->getStackFrame() != CalleeSF
) {
2534 Engine
.FunctionSummaries
->markReachedMaxBlockCount(CalleeSF
->getDecl());
2536 // Re-run the call evaluation without inlining it, by storing the
2537 // no-inlining policy in the state and enqueuing the new work item on
2538 // the list. Replay should almost never fail. Use the stats to catch it
2540 if ((!AMgr
.options
.NoRetryExhausted
&&
2541 replayWithoutInlining(Pred
, CalleeLC
)))
2543 NumMaxBlockCountReachedInInlined
++;
2545 NumMaxBlockCountReached
++;
2547 // Make sink nodes as exhausted(for stats) only if retry failed.
2548 Engine
.blocksExhausted
.push_back(std::make_pair(L
, Sink
));
2552 //===----------------------------------------------------------------------===//
2553 // Branch processing.
2554 //===----------------------------------------------------------------------===//
2556 /// RecoverCastedSymbol - A helper function for ProcessBranch that is used
2557 /// to try to recover some path-sensitivity for casts of symbolic
2558 /// integers that promote their values (which are currently not tracked well).
2559 /// This function returns the SVal bound to Condition->IgnoreCasts if all the
2560 // cast(s) did was sign-extend the original value.
2561 static SVal
RecoverCastedSymbol(ProgramStateRef state
,
2562 const Stmt
*Condition
,
2563 const LocationContext
*LCtx
,
2566 const auto *Ex
= dyn_cast
<Expr
>(Condition
);
2568 return UnknownVal();
2571 bool bitsInit
= false;
2573 while (const auto *CE
= dyn_cast
<CastExpr
>(Ex
)) {
2574 QualType T
= CE
->getType();
2576 if (!T
->isIntegralOrEnumerationType())
2577 return UnknownVal();
2579 uint64_t newBits
= Ctx
.getTypeSize(T
);
2580 if (!bitsInit
|| newBits
< bits
) {
2585 Ex
= CE
->getSubExpr();
2588 // We reached a non-cast. Is it a symbolic value?
2589 QualType T
= Ex
->getType();
2591 if (!bitsInit
|| !T
->isIntegralOrEnumerationType() ||
2592 Ctx
.getTypeSize(T
) > bits
)
2593 return UnknownVal();
2595 return state
->getSVal(Ex
, LCtx
);
2599 static const Stmt
*getRightmostLeaf(const Stmt
*Condition
) {
2601 const auto *BO
= dyn_cast
<BinaryOperator
>(Condition
);
2602 if (!BO
|| !BO
->isLogicalOp()) {
2605 Condition
= BO
->getRHS()->IgnoreParens();
2611 // Returns the condition the branch at the end of 'B' depends on and whose value
2612 // has been evaluated within 'B'.
2613 // In most cases, the terminator condition of 'B' will be evaluated fully in
2614 // the last statement of 'B'; in those cases, the resolved condition is the
2615 // given 'Condition'.
2616 // If the condition of the branch is a logical binary operator tree, the CFG is
2617 // optimized: in that case, we know that the expression formed by all but the
2618 // rightmost leaf of the logical binary operator tree must be true, and thus
2619 // the branch condition is at this point equivalent to the truth value of that
2620 // rightmost leaf; the CFG block thus only evaluates this rightmost leaf
2621 // expression in its final statement. As the full condition in that case was
2622 // not evaluated, and is thus not in the SVal cache, we need to use that leaf
2623 // expression to evaluate the truth value of the condition in the current state
2625 static const Stmt
*ResolveCondition(const Stmt
*Condition
,
2626 const CFGBlock
*B
) {
2627 if (const auto *Ex
= dyn_cast
<Expr
>(Condition
))
2628 Condition
= Ex
->IgnoreParens();
2630 const auto *BO
= dyn_cast
<BinaryOperator
>(Condition
);
2631 if (!BO
|| !BO
->isLogicalOp())
2634 assert(B
->getTerminator().isStmtBranch() &&
2635 "Other kinds of branches are handled separately!");
2637 // For logical operations, we still have the case where some branches
2638 // use the traditional "merge" approach and others sink the branch
2639 // directly into the basic blocks representing the logical operation.
2640 // We need to distinguish between those two cases here.
2642 // The invariants are still shifting, but it is possible that the
2643 // last element in a CFGBlock is not a CFGStmt. Look for the last
2644 // CFGStmt as the value of the condition.
2645 for (CFGElement Elem
: llvm::reverse(*B
)) {
2646 std::optional
<CFGStmt
> CS
= Elem
.getAs
<CFGStmt
>();
2649 const Stmt
*LastStmt
= CS
->getStmt();
2650 assert(LastStmt
== Condition
|| LastStmt
== getRightmostLeaf(Condition
));
2653 llvm_unreachable("could not resolve condition");
2656 using ObjCForLctxPair
=
2657 std::pair
<const ObjCForCollectionStmt
*, const LocationContext
*>;
2659 REGISTER_MAP_WITH_PROGRAMSTATE(ObjCForHasMoreIterations
, ObjCForLctxPair
, bool)
2661 ProgramStateRef
ExprEngine::setWhetherHasMoreIteration(
2662 ProgramStateRef State
, const ObjCForCollectionStmt
*O
,
2663 const LocationContext
*LC
, bool HasMoreIteraton
) {
2664 assert(!State
->contains
<ObjCForHasMoreIterations
>({O
, LC
}));
2665 return State
->set
<ObjCForHasMoreIterations
>({O
, LC
}, HasMoreIteraton
);
2669 ExprEngine::removeIterationState(ProgramStateRef State
,
2670 const ObjCForCollectionStmt
*O
,
2671 const LocationContext
*LC
) {
2672 assert(State
->contains
<ObjCForHasMoreIterations
>({O
, LC
}));
2673 return State
->remove
<ObjCForHasMoreIterations
>({O
, LC
});
2676 bool ExprEngine::hasMoreIteration(ProgramStateRef State
,
2677 const ObjCForCollectionStmt
*O
,
2678 const LocationContext
*LC
) {
2679 assert(State
->contains
<ObjCForHasMoreIterations
>({O
, LC
}));
2680 return *State
->get
<ObjCForHasMoreIterations
>({O
, LC
});
2683 /// Split the state on whether there are any more iterations left for this loop.
2684 /// Returns a (HasMoreIteration, HasNoMoreIteration) pair, or std::nullopt when
2685 /// the acquisition of the loop condition value failed.
2686 static std::optional
<std::pair
<ProgramStateRef
, ProgramStateRef
>>
2687 assumeCondition(const Stmt
*Condition
, ExplodedNode
*N
) {
2688 ProgramStateRef State
= N
->getState();
2689 if (const auto *ObjCFor
= dyn_cast
<ObjCForCollectionStmt
>(Condition
)) {
2690 bool HasMoreIteraton
=
2691 ExprEngine::hasMoreIteration(State
, ObjCFor
, N
->getLocationContext());
2692 // Checkers have already ran on branch conditions, so the current
2693 // information as to whether the loop has more iteration becomes outdated
2694 // after this point.
2695 State
= ExprEngine::removeIterationState(State
, ObjCFor
,
2696 N
->getLocationContext());
2697 if (HasMoreIteraton
)
2698 return std::pair
<ProgramStateRef
, ProgramStateRef
>{State
, nullptr};
2700 return std::pair
<ProgramStateRef
, ProgramStateRef
>{nullptr, State
};
2702 SVal X
= State
->getSVal(Condition
, N
->getLocationContext());
2704 if (X
.isUnknownOrUndef()) {
2705 // Give it a chance to recover from unknown.
2706 if (const auto *Ex
= dyn_cast
<Expr
>(Condition
)) {
2707 if (Ex
->getType()->isIntegralOrEnumerationType()) {
2708 // Try to recover some path-sensitivity. Right now casts of symbolic
2709 // integers that promote their values are currently not tracked well.
2710 // If 'Condition' is such an expression, try and recover the
2711 // underlying value and use that instead.
2713 RecoverCastedSymbol(State
, Condition
, N
->getLocationContext(),
2714 N
->getState()->getStateManager().getContext());
2716 if (!recovered
.isUnknown()) {
2723 // If the condition is still unknown, give up.
2724 if (X
.isUnknownOrUndef())
2725 return std::nullopt
;
2727 DefinedSVal V
= X
.castAs
<DefinedSVal
>();
2729 ProgramStateRef StTrue
, StFalse
;
2730 return State
->assume(V
);
2733 void ExprEngine::processBranch(const Stmt
*Condition
,
2734 NodeBuilderContext
& BldCtx
,
2736 ExplodedNodeSet
&Dst
,
2737 const CFGBlock
*DstT
,
2738 const CFGBlock
*DstF
) {
2739 assert((!Condition
|| !isa
<CXXBindTemporaryExpr
>(Condition
)) &&
2740 "CXXBindTemporaryExprs are handled by processBindTemporary.");
2741 const LocationContext
*LCtx
= Pred
->getLocationContext();
2742 PrettyStackTraceLocationContext
StackCrashInfo(LCtx
);
2743 currBldrCtx
= &BldCtx
;
2745 // Check for NULL conditions; e.g. "for(;;)"
2747 BranchNodeBuilder
NullCondBldr(Pred
, Dst
, BldCtx
, DstT
, DstF
);
2748 NullCondBldr
.markInfeasible(false);
2749 NullCondBldr
.generateNode(Pred
->getState(), true, Pred
);
2753 if (const auto *Ex
= dyn_cast
<Expr
>(Condition
))
2754 Condition
= Ex
->IgnoreParens();
2756 Condition
= ResolveCondition(Condition
, BldCtx
.getBlock());
2757 PrettyStackTraceLoc
CrashInfo(getContext().getSourceManager(),
2758 Condition
->getBeginLoc(),
2759 "Error evaluating branch");
2761 ExplodedNodeSet CheckersOutSet
;
2762 getCheckerManager().runCheckersForBranchCondition(Condition
, CheckersOutSet
,
2764 // We generated only sinks.
2765 if (CheckersOutSet
.empty())
2768 BranchNodeBuilder
builder(CheckersOutSet
, Dst
, BldCtx
, DstT
, DstF
);
2769 for (ExplodedNode
*PredN
: CheckersOutSet
) {
2770 if (PredN
->isSink())
2773 ProgramStateRef PrevState
= PredN
->getState();
2775 ProgramStateRef StTrue
, StFalse
;
2776 if (const auto KnownCondValueAssumption
= assumeCondition(Condition
, PredN
))
2777 std::tie(StTrue
, StFalse
) = *KnownCondValueAssumption
;
2779 assert(!isa
<ObjCForCollectionStmt
>(Condition
));
2780 builder
.generateNode(PrevState
, true, PredN
);
2781 builder
.generateNode(PrevState
, false, PredN
);
2784 if (StTrue
&& StFalse
)
2785 assert(!isa
<ObjCForCollectionStmt
>(Condition
));
2787 // Process the true branch.
2788 if (builder
.isFeasible(true)) {
2790 builder
.generateNode(StTrue
, true, PredN
);
2792 builder
.markInfeasible(true);
2795 // Process the false branch.
2796 if (builder
.isFeasible(false)) {
2798 builder
.generateNode(StFalse
, false, PredN
);
2800 builder
.markInfeasible(false);
2803 currBldrCtx
= nullptr;
2806 /// The GDM component containing the set of global variables which have been
2807 /// previously initialized with explicit initializers.
2808 REGISTER_TRAIT_WITH_PROGRAMSTATE(InitializedGlobalsSet
,
2809 llvm::ImmutableSet
<const VarDecl
*>)
2811 void ExprEngine::processStaticInitializer(const DeclStmt
*DS
,
2812 NodeBuilderContext
&BuilderCtx
,
2814 ExplodedNodeSet
&Dst
,
2815 const CFGBlock
*DstT
,
2816 const CFGBlock
*DstF
) {
2817 PrettyStackTraceLocationContext
CrashInfo(Pred
->getLocationContext());
2818 currBldrCtx
= &BuilderCtx
;
2820 const auto *VD
= cast
<VarDecl
>(DS
->getSingleDecl());
2821 ProgramStateRef state
= Pred
->getState();
2822 bool initHasRun
= state
->contains
<InitializedGlobalsSet
>(VD
);
2823 BranchNodeBuilder
builder(Pred
, Dst
, BuilderCtx
, DstT
, DstF
);
2826 state
= state
->add
<InitializedGlobalsSet
>(VD
);
2829 builder
.generateNode(state
, initHasRun
, Pred
);
2830 builder
.markInfeasible(!initHasRun
);
2832 currBldrCtx
= nullptr;
2835 /// processIndirectGoto - Called by CoreEngine. Used to generate successor
2836 /// nodes by processing the 'effects' of a computed goto jump.
2837 void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder
&builder
) {
2838 ProgramStateRef state
= builder
.getState();
2839 SVal V
= state
->getSVal(builder
.getTarget(), builder
.getLocationContext());
2841 // Three possibilities:
2843 // (1) We know the computed label.
2844 // (2) The label is NULL (or some other constant), or Undefined.
2845 // (3) We have no clue about the label. Dispatch to all targets.
2848 using iterator
= IndirectGotoNodeBuilder::iterator
;
2850 if (std::optional
<loc::GotoLabel
> LV
= V
.getAs
<loc::GotoLabel
>()) {
2851 const LabelDecl
*L
= LV
->getLabel();
2853 for (iterator Succ
: builder
) {
2854 if (Succ
.getLabel() == L
) {
2855 builder
.generateNode(Succ
, state
);
2860 llvm_unreachable("No block with label.");
2863 if (isa
<UndefinedVal
, loc::ConcreteInt
>(V
)) {
2864 // Dispatch to the first target and mark it as a sink.
2865 //ExplodedNode* N = builder.generateNode(builder.begin(), state, true);
2866 // FIXME: add checker visit.
2867 // UndefBranches.insert(N);
2871 // This is really a catch-all. We don't support symbolics yet.
2872 // FIXME: Implement dispatch for symbolic pointers.
2874 for (iterator Succ
: builder
)
2875 builder
.generateNode(Succ
, state
);
2878 void ExprEngine::processBeginOfFunction(NodeBuilderContext
&BC
,
2880 ExplodedNodeSet
&Dst
,
2881 const BlockEdge
&L
) {
2882 SaveAndRestore
<const NodeBuilderContext
*> NodeContextRAII(currBldrCtx
, &BC
);
2883 getCheckerManager().runCheckersForBeginFunction(Dst
, L
, Pred
, *this);
2886 /// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path
2887 /// nodes when the control reaches the end of a function.
2888 void ExprEngine::processEndOfFunction(NodeBuilderContext
& BC
,
2890 const ReturnStmt
*RS
) {
2891 ProgramStateRef State
= Pred
->getState();
2893 if (!Pred
->getStackFrame()->inTopFrame())
2894 State
= finishArgumentConstruction(
2895 State
, *getStateManager().getCallEventManager().getCaller(
2896 Pred
->getStackFrame(), Pred
->getState()));
2898 // FIXME: We currently cannot assert that temporaries are clear, because
2899 // lifetime extended temporaries are not always modelled correctly. In some
2900 // cases when we materialize the temporary, we do
2901 // createTemporaryRegionIfNeeded(), and the region changes, and also the
2902 // respective destructor becomes automatic from temporary. So for now clean up
2903 // the state manually before asserting. Ideally, this braced block of code
2906 const LocationContext
*FromLC
= Pred
->getLocationContext();
2907 const LocationContext
*ToLC
= FromLC
->getStackFrame()->getParent();
2908 const LocationContext
*LC
= FromLC
;
2909 while (LC
!= ToLC
) {
2910 assert(LC
&& "ToLC must be a parent of FromLC!");
2911 for (auto I
: State
->get
<ObjectsUnderConstruction
>())
2912 if (I
.first
.getLocationContext() == LC
) {
2913 // The comment above only pardons us for not cleaning up a
2914 // temporary destructor. If any other statements are found here,
2915 // it must be a separate problem.
2916 assert(I
.first
.getItem().getKind() ==
2917 ConstructionContextItem::TemporaryDestructorKind
||
2918 I
.first
.getItem().getKind() ==
2919 ConstructionContextItem::ElidedDestructorKind
);
2920 State
= State
->remove
<ObjectsUnderConstruction
>(I
.first
);
2922 LC
= LC
->getParent();
2926 // Perform the transition with cleanups.
2927 if (State
!= Pred
->getState()) {
2928 ExplodedNodeSet PostCleanup
;
2929 NodeBuilder
Bldr(Pred
, PostCleanup
, BC
);
2930 Pred
= Bldr
.generateNode(Pred
->getLocation(), State
, Pred
);
2932 // The node with clean temporaries already exists. We might have reached
2933 // it on a path on which we initialize different temporaries.
2938 assert(areAllObjectsFullyConstructed(Pred
->getState(),
2939 Pred
->getLocationContext(),
2940 Pred
->getStackFrame()->getParent()));
2942 PrettyStackTraceLocationContext
CrashInfo(Pred
->getLocationContext());
2944 ExplodedNodeSet Dst
;
2945 if (Pred
->getLocationContext()->inTopFrame()) {
2946 // Remove dead symbols.
2947 ExplodedNodeSet AfterRemovedDead
;
2948 removeDeadOnEndOfFunction(BC
, Pred
, AfterRemovedDead
);
2951 for (const auto I
: AfterRemovedDead
)
2952 getCheckerManager().runCheckersForEndFunction(BC
, Dst
, I
, *this, RS
);
2954 getCheckerManager().runCheckersForEndFunction(BC
, Dst
, Pred
, *this, RS
);
2957 Engine
.enqueueEndOfFunction(Dst
, RS
);
2960 /// ProcessSwitch - Called by CoreEngine. Used to generate successor
2961 /// nodes by processing the 'effects' of a switch statement.
2962 void ExprEngine::processSwitch(SwitchNodeBuilder
& builder
) {
2963 using iterator
= SwitchNodeBuilder::iterator
;
2965 ProgramStateRef state
= builder
.getState();
2966 const Expr
*CondE
= builder
.getCondition();
2967 SVal CondV_untested
= state
->getSVal(CondE
, builder
.getLocationContext());
2969 if (CondV_untested
.isUndef()) {
2970 //ExplodedNode* N = builder.generateDefaultCaseNode(state, true);
2971 // FIXME: add checker
2972 //UndefBranches.insert(N);
2976 DefinedOrUnknownSVal CondV
= CondV_untested
.castAs
<DefinedOrUnknownSVal
>();
2978 ProgramStateRef DefaultSt
= state
;
2980 iterator I
= builder
.begin(), EI
= builder
.end();
2981 bool defaultIsFeasible
= I
== EI
;
2983 for ( ; I
!= EI
; ++I
) {
2984 // Successor may be pruned out during CFG construction.
2988 const CaseStmt
*Case
= I
.getCase();
2990 // Evaluate the LHS of the case value.
2991 llvm::APSInt V1
= Case
->getLHS()->EvaluateKnownConstInt(getContext());
2992 assert(V1
.getBitWidth() == getContext().getIntWidth(CondE
->getType()));
2994 // Get the RHS of the case, if it exists.
2996 if (const Expr
*E
= Case
->getRHS())
2997 V2
= E
->EvaluateKnownConstInt(getContext());
3001 ProgramStateRef StateCase
;
3002 if (std::optional
<NonLoc
> NL
= CondV
.getAs
<NonLoc
>())
3003 std::tie(StateCase
, DefaultSt
) =
3004 DefaultSt
->assumeInclusiveRange(*NL
, V1
, V2
);
3006 StateCase
= DefaultSt
;
3009 builder
.generateCaseStmtNode(I
, StateCase
);
3011 // Now "assume" that the case doesn't match. Add this state
3012 // to the default state (if it is feasible).
3014 defaultIsFeasible
= true;
3016 defaultIsFeasible
= false;
3021 if (!defaultIsFeasible
)
3024 // If we have switch(enum value), the default branch is not
3025 // feasible if all of the enum constants not covered by 'case:' statements
3026 // are not feasible values for the switch condition.
3028 // Note that this isn't as accurate as it could be. Even if there isn't
3029 // a case for a particular enum value as long as that enum value isn't
3030 // feasible then it shouldn't be considered for making 'default:' reachable.
3031 const SwitchStmt
*SS
= builder
.getSwitch();
3032 const Expr
*CondExpr
= SS
->getCond()->IgnoreParenImpCasts();
3033 if (CondExpr
->getType()->getAs
<EnumType
>()) {
3034 if (SS
->isAllEnumCasesCovered())
3038 builder
.generateDefaultCaseNode(DefaultSt
);
3041 //===----------------------------------------------------------------------===//
3042 // Transfer functions: Loads and stores.
3043 //===----------------------------------------------------------------------===//
3045 void ExprEngine::VisitCommonDeclRefExpr(const Expr
*Ex
, const NamedDecl
*D
,
3047 ExplodedNodeSet
&Dst
) {
3048 StmtNodeBuilder
Bldr(Pred
, Dst
, *currBldrCtx
);
3050 ProgramStateRef state
= Pred
->getState();
3051 const LocationContext
*LCtx
= Pred
->getLocationContext();
3053 if (const auto *VD
= dyn_cast
<VarDecl
>(D
)) {
3054 // C permits "extern void v", and if you cast the address to a valid type,
3055 // you can even do things with it. We simply pretend
3056 assert(Ex
->isGLValue() || VD
->getType()->isVoidType());
3057 const LocationContext
*LocCtxt
= Pred
->getLocationContext();
3058 const Decl
*D
= LocCtxt
->getDecl();
3059 const auto *MD
= dyn_cast_or_null
<CXXMethodDecl
>(D
);
3060 const auto *DeclRefEx
= dyn_cast
<DeclRefExpr
>(Ex
);
3061 std::optional
<std::pair
<SVal
, QualType
>> VInfo
;
3063 if (AMgr
.options
.ShouldInlineLambdas
&& DeclRefEx
&&
3064 DeclRefEx
->refersToEnclosingVariableOrCapture() && MD
&&
3065 MD
->getParent()->isLambda()) {
3066 // Lookup the field of the lambda.
3067 const CXXRecordDecl
*CXXRec
= MD
->getParent();
3068 llvm::DenseMap
<const ValueDecl
*, FieldDecl
*> LambdaCaptureFields
;
3069 FieldDecl
*LambdaThisCaptureField
;
3070 CXXRec
->getCaptureFields(LambdaCaptureFields
, LambdaThisCaptureField
);
3072 // Sema follows a sequence of complex rules to determine whether the
3073 // variable should be captured.
3074 if (const FieldDecl
*FD
= LambdaCaptureFields
[VD
]) {
3076 svalBuilder
.getCXXThis(MD
, LocCtxt
->getStackFrame());
3077 SVal CXXThisVal
= state
->getSVal(CXXThis
);
3078 VInfo
= std::make_pair(state
->getLValue(FD
, CXXThisVal
), FD
->getType());
3083 VInfo
= std::make_pair(state
->getLValue(VD
, LocCtxt
), VD
->getType());
3085 SVal V
= VInfo
->first
;
3086 bool IsReference
= VInfo
->second
->isReferenceType();
3088 // For references, the 'lvalue' is the pointer address stored in the
3089 // reference region.
3091 if (const MemRegion
*R
= V
.getAsRegion())
3092 V
= state
->getSVal(R
);
3097 Bldr
.generateNode(Ex
, Pred
, state
->BindExpr(Ex
, LCtx
, V
), nullptr,
3098 ProgramPoint::PostLValueKind
);
3101 if (const auto *ED
= dyn_cast
<EnumConstantDecl
>(D
)) {
3102 assert(!Ex
->isGLValue());
3103 SVal V
= svalBuilder
.makeIntVal(ED
->getInitVal());
3104 Bldr
.generateNode(Ex
, Pred
, state
->BindExpr(Ex
, LCtx
, V
));
3107 if (const auto *FD
= dyn_cast
<FunctionDecl
>(D
)) {
3108 SVal V
= svalBuilder
.getFunctionPointer(FD
);
3109 Bldr
.generateNode(Ex
, Pred
, state
->BindExpr(Ex
, LCtx
, V
), nullptr,
3110 ProgramPoint::PostLValueKind
);
3113 if (isa
<FieldDecl
, IndirectFieldDecl
>(D
)) {
3114 // Delegate all work related to pointer to members to the surrounding
3118 if (const auto *BD
= dyn_cast
<BindingDecl
>(D
)) {
3119 const auto *DD
= cast
<DecompositionDecl
>(BD
->getDecomposedDecl());
3121 SVal Base
= state
->getLValue(DD
, LCtx
);
3122 if (DD
->getType()->isReferenceType()) {
3123 if (const MemRegion
*R
= Base
.getAsRegion())
3124 Base
= state
->getSVal(R
);
3126 Base
= UnknownVal();
3129 SVal V
= UnknownVal();
3131 // Handle binding to data members
3132 if (const auto *ME
= dyn_cast
<MemberExpr
>(BD
->getBinding())) {
3133 const auto *Field
= cast
<FieldDecl
>(ME
->getMemberDecl());
3134 V
= state
->getLValue(Field
, Base
);
3136 // Handle binding to arrays
3137 else if (const auto *ASE
= dyn_cast
<ArraySubscriptExpr
>(BD
->getBinding())) {
3138 SVal Idx
= state
->getSVal(ASE
->getIdx(), LCtx
);
3140 // Note: the index of an element in a structured binding is automatically
3141 // created and it is a unique identifier of the specific element. Thus it
3142 // cannot be a value that varies at runtime.
3143 assert(Idx
.isConstant() && "BindingDecl array index is not a constant!");
3145 V
= state
->getLValue(BD
->getType(), Idx
, Base
);
3147 // Handle binding to tuple-like structures
3148 else if (const auto *HV
= BD
->getHoldingVar()) {
3149 V
= state
->getLValue(HV
, LCtx
);
3151 if (HV
->getType()->isReferenceType()) {
3152 if (const MemRegion
*R
= V
.getAsRegion())
3153 V
= state
->getSVal(R
);
3158 llvm_unreachable("An unknown case of structured binding encountered!");
3160 // In case of tuple-like types the references are already handled, so we
3161 // don't want to handle them again.
3162 if (BD
->getType()->isReferenceType() && !BD
->getHoldingVar()) {
3163 if (const MemRegion
*R
= V
.getAsRegion())
3164 V
= state
->getSVal(R
);
3169 Bldr
.generateNode(Ex
, Pred
, state
->BindExpr(Ex
, LCtx
, V
), nullptr,
3170 ProgramPoint::PostLValueKind
);
3175 if (const auto *TPO
= dyn_cast
<TemplateParamObjectDecl
>(D
)) {
3176 // FIXME: We should meaningfully implement this.
3181 llvm_unreachable("Support for this Decl not implemented.");
3184 /// VisitArrayInitLoopExpr - Transfer function for array init loop.
3185 void ExprEngine::VisitArrayInitLoopExpr(const ArrayInitLoopExpr
*Ex
,
3187 ExplodedNodeSet
&Dst
) {
3188 ExplodedNodeSet CheckerPreStmt
;
3189 getCheckerManager().runCheckersForPreStmt(CheckerPreStmt
, Pred
, Ex
, *this);
3191 ExplodedNodeSet EvalSet
;
3192 StmtNodeBuilder
Bldr(CheckerPreStmt
, EvalSet
, *currBldrCtx
);
3194 const Expr
*Arr
= Ex
->getCommonExpr()->getSourceExpr();
3196 for (auto *Node
: CheckerPreStmt
) {
3198 // The constructor visitior has already taken care of everything.
3199 if (isa
<CXXConstructExpr
>(Ex
->getSubExpr()))
3202 const LocationContext
*LCtx
= Node
->getLocationContext();
3203 ProgramStateRef state
= Node
->getState();
3205 SVal Base
= UnknownVal();
3207 // As in case of this expression the sub-expressions are not visited by any
3208 // other transfer functions, they are handled by matching their AST.
3210 // Case of implicit copy or move ctor of object with array member
3212 // Note: ExprEngine::VisitMemberExpr is not able to bind the array to the
3223 // The AST in case of a *copy constructor* looks like this:
3224 // ArrayInitLoopExpr
3225 // |-OpaqueValueExpr
3226 // | `-MemberExpr <-- match this
3232 // S d = std::move(d);
3234 // In case of a *move constructor* the resulting AST looks like:
3235 // ArrayInitLoopExpr
3236 // |-OpaqueValueExpr
3237 // | `-MemberExpr <-- match this first
3238 // | `-CXXStaticCastExpr <-- match this after
3241 if (const auto *ME
= dyn_cast
<MemberExpr
>(Arr
)) {
3242 Expr
*MEBase
= ME
->getBase();
3245 if (auto CXXSCE
= dyn_cast
<CXXStaticCastExpr
>(MEBase
)) {
3246 MEBase
= CXXSCE
->getSubExpr();
3249 auto ObjDeclExpr
= cast
<DeclRefExpr
>(MEBase
);
3250 SVal Obj
= state
->getLValue(cast
<VarDecl
>(ObjDeclExpr
->getDecl()), LCtx
);
3252 Base
= state
->getLValue(cast
<FieldDecl
>(ME
->getMemberDecl()), Obj
);
3255 // Case of lambda capture and decomposition declaration
3259 // [arr]{ int a = arr[0]; }();
3260 // auto[a, b] = arr;
3262 // In both of these cases the AST looks like the following:
3263 // ArrayInitLoopExpr
3264 // |-OpaqueValueExpr
3265 // | `-DeclRefExpr <-- match this
3267 if (const DeclRefExpr
*DRE
= dyn_cast
<DeclRefExpr
>(Arr
))
3268 Base
= state
->getLValue(cast
<VarDecl
>(DRE
->getDecl()), LCtx
);
3270 // Create a lazy compound value to the original array
3271 if (const MemRegion
*R
= Base
.getAsRegion())
3272 Base
= state
->getSVal(R
);
3274 Base
= UnknownVal();
3276 Bldr
.generateNode(Ex
, Pred
, state
->BindExpr(Ex
, LCtx
, Base
));
3279 getCheckerManager().runCheckersForPostStmt(Dst
, EvalSet
, Ex
, *this);
3282 /// VisitArraySubscriptExpr - Transfer function for array accesses
3283 void ExprEngine::VisitArraySubscriptExpr(const ArraySubscriptExpr
*A
,
3285 ExplodedNodeSet
&Dst
){
3286 const Expr
*Base
= A
->getBase()->IgnoreParens();
3287 const Expr
*Idx
= A
->getIdx()->IgnoreParens();
3289 ExplodedNodeSet CheckerPreStmt
;
3290 getCheckerManager().runCheckersForPreStmt(CheckerPreStmt
, Pred
, A
, *this);
3292 ExplodedNodeSet EvalSet
;
3293 StmtNodeBuilder
Bldr(CheckerPreStmt
, EvalSet
, *currBldrCtx
);
3295 bool IsVectorType
= A
->getBase()->getType()->isVectorType();
3297 // The "like" case is for situations where C standard prohibits the type to
3298 // be an lvalue, e.g. taking the address of a subscript of an expression of
3300 bool IsGLValueLike
= A
->isGLValue() ||
3301 (A
->getType().isCForbiddenLValueType() && !AMgr
.getLangOpts().CPlusPlus
);
3303 for (auto *Node
: CheckerPreStmt
) {
3304 const LocationContext
*LCtx
= Node
->getLocationContext();
3305 ProgramStateRef state
= Node
->getState();
3307 if (IsGLValueLike
) {
3308 QualType T
= A
->getType();
3310 // One of the forbidden LValue types! We still need to have sensible
3311 // symbolic locations to represent this stuff. Note that arithmetic on
3312 // void pointers is a GCC extension.
3313 if (T
->isVoidType())
3314 T
= getContext().CharTy
;
3316 SVal V
= state
->getLValue(T
,
3317 state
->getSVal(Idx
, LCtx
),
3318 state
->getSVal(Base
, LCtx
));
3319 Bldr
.generateNode(A
, Node
, state
->BindExpr(A
, LCtx
, V
), nullptr,
3320 ProgramPoint::PostLValueKind
);
3321 } else if (IsVectorType
) {
3322 // FIXME: non-glvalue vector reads are not modelled.
3323 Bldr
.generateNode(A
, Node
, state
, nullptr);
3325 llvm_unreachable("Array subscript should be an lValue when not \
3326 a vector and not a forbidden lvalue type");
3330 getCheckerManager().runCheckersForPostStmt(Dst
, EvalSet
, A
, *this);
3333 /// VisitMemberExpr - Transfer function for member expressions.
3334 void ExprEngine::VisitMemberExpr(const MemberExpr
*M
, ExplodedNode
*Pred
,
3335 ExplodedNodeSet
&Dst
) {
3336 // FIXME: Prechecks eventually go in ::Visit().
3337 ExplodedNodeSet CheckedSet
;
3338 getCheckerManager().runCheckersForPreStmt(CheckedSet
, Pred
, M
, *this);
3340 ExplodedNodeSet EvalSet
;
3341 ValueDecl
*Member
= M
->getMemberDecl();
3343 // Handle static member variables and enum constants accessed via
3345 if (isa
<VarDecl
, EnumConstantDecl
>(Member
)) {
3346 for (const auto I
: CheckedSet
)
3347 VisitCommonDeclRefExpr(M
, Member
, I
, EvalSet
);
3349 StmtNodeBuilder
Bldr(CheckedSet
, EvalSet
, *currBldrCtx
);
3350 ExplodedNodeSet Tmp
;
3352 for (const auto I
: CheckedSet
) {
3353 ProgramStateRef state
= I
->getState();
3354 const LocationContext
*LCtx
= I
->getLocationContext();
3355 Expr
*BaseExpr
= M
->getBase();
3357 // Handle C++ method calls.
3358 if (const auto *MD
= dyn_cast
<CXXMethodDecl
>(Member
)) {
3359 if (MD
->isInstance())
3360 state
= createTemporaryRegionIfNeeded(state
, LCtx
, BaseExpr
);
3362 SVal MDVal
= svalBuilder
.getFunctionPointer(MD
);
3363 state
= state
->BindExpr(M
, LCtx
, MDVal
);
3365 Bldr
.generateNode(M
, I
, state
);
3369 // Handle regular struct fields / member variables.
3370 const SubRegion
*MR
= nullptr;
3371 state
= createTemporaryRegionIfNeeded(state
, LCtx
, BaseExpr
,
3373 /*OutRegionWithAdjustments=*/&MR
);
3375 MR
? loc::MemRegionVal(MR
) : state
->getSVal(BaseExpr
, LCtx
);
3377 // FIXME: Copied from RegionStoreManager::bind()
3378 if (const auto *SR
=
3379 dyn_cast_or_null
<SymbolicRegion
>(baseExprVal
.getAsRegion())) {
3380 QualType T
= SR
->getPointeeStaticType();
3382 loc::MemRegionVal(getStoreManager().GetElementZeroRegion(SR
, T
));
3385 const auto *field
= cast
<FieldDecl
>(Member
);
3386 SVal L
= state
->getLValue(field
, baseExprVal
);
3388 if (M
->isGLValue() || M
->getType()->isArrayType()) {
3389 // We special-case rvalues of array type because the analyzer cannot
3390 // reason about them, since we expect all regions to be wrapped in Locs.
3391 // We instead treat these as lvalues and assume that they will decay to
3392 // pointers as soon as they are used.
3393 if (!M
->isGLValue()) {
3394 assert(M
->getType()->isArrayType());
3396 dyn_cast
<ImplicitCastExpr
>(I
->getParentMap().getParentIgnoreParens(M
));
3397 if (!PE
|| PE
->getCastKind() != CK_ArrayToPointerDecay
) {
3398 llvm_unreachable("should always be wrapped in ArrayToPointerDecay");
3402 if (field
->getType()->isReferenceType()) {
3403 if (const MemRegion
*R
= L
.getAsRegion())
3404 L
= state
->getSVal(R
);
3409 Bldr
.generateNode(M
, I
, state
->BindExpr(M
, LCtx
, L
), nullptr,
3410 ProgramPoint::PostLValueKind
);
3413 evalLoad(Tmp
, M
, M
, I
, state
, L
);
3419 getCheckerManager().runCheckersForPostStmt(Dst
, EvalSet
, M
, *this);
3422 void ExprEngine::VisitAtomicExpr(const AtomicExpr
*AE
, ExplodedNode
*Pred
,
3423 ExplodedNodeSet
&Dst
) {
3424 ExplodedNodeSet AfterPreSet
;
3425 getCheckerManager().runCheckersForPreStmt(AfterPreSet
, Pred
, AE
, *this);
3427 // For now, treat all the arguments to C11 atomics as escaping.
3428 // FIXME: Ideally we should model the behavior of the atomics precisely here.
3430 ExplodedNodeSet AfterInvalidateSet
;
3431 StmtNodeBuilder
Bldr(AfterPreSet
, AfterInvalidateSet
, *currBldrCtx
);
3433 for (const auto I
: AfterPreSet
) {
3434 ProgramStateRef State
= I
->getState();
3435 const LocationContext
*LCtx
= I
->getLocationContext();
3437 SmallVector
<SVal
, 8> ValuesToInvalidate
;
3438 for (unsigned SI
= 0, Count
= AE
->getNumSubExprs(); SI
!= Count
; SI
++) {
3439 const Expr
*SubExpr
= AE
->getSubExprs()[SI
];
3440 SVal SubExprVal
= State
->getSVal(SubExpr
, LCtx
);
3441 ValuesToInvalidate
.push_back(SubExprVal
);
3444 State
= State
->invalidateRegions(ValuesToInvalidate
, AE
,
3445 currBldrCtx
->blockCount(),
3447 /*CausedByPointerEscape*/true,
3448 /*Symbols=*/nullptr);
3450 SVal ResultVal
= UnknownVal();
3451 State
= State
->BindExpr(AE
, LCtx
, ResultVal
);
3452 Bldr
.generateNode(AE
, I
, State
, nullptr,
3453 ProgramPoint::PostStmtKind
);
3456 getCheckerManager().runCheckersForPostStmt(Dst
, AfterInvalidateSet
, AE
, *this);
3459 // A value escapes in four possible cases:
3460 // (1) We are binding to something that is not a memory region.
3461 // (2) We are binding to a MemRegion that does not have stack storage.
3462 // (3) We are binding to a top-level parameter region with a non-trivial
3463 // destructor. We won't see the destructor during analysis, but it's there.
3464 // (4) We are binding to a MemRegion with stack storage that the store
3465 // does not understand.
3466 ProgramStateRef
ExprEngine::processPointerEscapedOnBind(
3467 ProgramStateRef State
, ArrayRef
<std::pair
<SVal
, SVal
>> LocAndVals
,
3468 const LocationContext
*LCtx
, PointerEscapeKind Kind
,
3469 const CallEvent
*Call
) {
3470 SmallVector
<SVal
, 8> Escaped
;
3471 for (const std::pair
<SVal
, SVal
> &LocAndVal
: LocAndVals
) {
3472 // Cases (1) and (2).
3473 const MemRegion
*MR
= LocAndVal
.first
.getAsRegion();
3475 !isa
<StackSpaceRegion
, StaticGlobalSpaceRegion
>(MR
->getMemorySpace())) {
3476 Escaped
.push_back(LocAndVal
.second
);
3481 if (const auto *VR
= dyn_cast
<VarRegion
>(MR
->getBaseRegion()))
3482 if (VR
->hasStackParametersStorage() && VR
->getStackFrame()->inTopFrame())
3483 if (const auto *RD
= VR
->getValueType()->getAsCXXRecordDecl())
3484 if (!RD
->hasTrivialDestructor()) {
3485 Escaped
.push_back(LocAndVal
.second
);
3489 // Case (4): in order to test that, generate a new state with the binding
3490 // added. If it is the same state, then it escapes (since the store cannot
3491 // represent the binding).
3492 // Do this only if we know that the store is not supposed to generate the
3494 SVal StoredVal
= State
->getSVal(MR
);
3495 if (StoredVal
!= LocAndVal
.second
)
3497 (State
->bindLoc(loc::MemRegionVal(MR
), LocAndVal
.second
, LCtx
)))
3498 Escaped
.push_back(LocAndVal
.second
);
3501 if (Escaped
.empty())
3504 return escapeValues(State
, Escaped
, Kind
, Call
);
3508 ExprEngine::processPointerEscapedOnBind(ProgramStateRef State
, SVal Loc
,
3509 SVal Val
, const LocationContext
*LCtx
) {
3510 std::pair
<SVal
, SVal
> LocAndVal(Loc
, Val
);
3511 return processPointerEscapedOnBind(State
, LocAndVal
, LCtx
, PSK_EscapeOnBind
,
3516 ExprEngine::notifyCheckersOfPointerEscape(ProgramStateRef State
,
3517 const InvalidatedSymbols
*Invalidated
,
3518 ArrayRef
<const MemRegion
*> ExplicitRegions
,
3519 const CallEvent
*Call
,
3520 RegionAndSymbolInvalidationTraits
&ITraits
) {
3521 if (!Invalidated
|| Invalidated
->empty())
3525 return getCheckerManager().runCheckersForPointerEscape(State
,
3531 // If the symbols were invalidated by a call, we want to find out which ones
3532 // were invalidated directly due to being arguments to the call.
3533 InvalidatedSymbols SymbolsDirectlyInvalidated
;
3534 for (const auto I
: ExplicitRegions
) {
3535 if (const SymbolicRegion
*R
= I
->StripCasts()->getAs
<SymbolicRegion
>())
3536 SymbolsDirectlyInvalidated
.insert(R
->getSymbol());
3539 InvalidatedSymbols SymbolsIndirectlyInvalidated
;
3540 for (const auto &sym
: *Invalidated
) {
3541 if (SymbolsDirectlyInvalidated
.count(sym
))
3543 SymbolsIndirectlyInvalidated
.insert(sym
);
3546 if (!SymbolsDirectlyInvalidated
.empty())
3547 State
= getCheckerManager().runCheckersForPointerEscape(State
,
3548 SymbolsDirectlyInvalidated
, Call
, PSK_DirectEscapeOnCall
, &ITraits
);
3550 // Notify about the symbols that get indirectly invalidated by the call.
3551 if (!SymbolsIndirectlyInvalidated
.empty())
3552 State
= getCheckerManager().runCheckersForPointerEscape(State
,
3553 SymbolsIndirectlyInvalidated
, Call
, PSK_IndirectEscapeOnCall
, &ITraits
);
3558 /// evalBind - Handle the semantics of binding a value to a specific location.
3559 /// This method is used by evalStore and (soon) VisitDeclStmt, and others.
3560 void ExprEngine::evalBind(ExplodedNodeSet
&Dst
, const Stmt
*StoreE
,
3562 SVal location
, SVal Val
,
3563 bool atDeclInit
, const ProgramPoint
*PP
) {
3564 const LocationContext
*LC
= Pred
->getLocationContext();
3565 PostStmt
PS(StoreE
, LC
);
3569 // Do a previsit of the bind.
3570 ExplodedNodeSet CheckedSet
;
3571 getCheckerManager().runCheckersForBind(CheckedSet
, Pred
, location
, Val
,
3572 StoreE
, *this, *PP
);
3574 StmtNodeBuilder
Bldr(CheckedSet
, Dst
, *currBldrCtx
);
3576 // If the location is not a 'Loc', it will already be handled by
3577 // the checkers. There is nothing left to do.
3578 if (!isa
<Loc
>(location
)) {
3579 const ProgramPoint L
= PostStore(StoreE
, LC
, /*Loc*/nullptr,
3581 ProgramStateRef state
= Pred
->getState();
3582 state
= processPointerEscapedOnBind(state
, location
, Val
, LC
);
3583 Bldr
.generateNode(L
, state
, Pred
);
3587 for (const auto PredI
: CheckedSet
) {
3588 ProgramStateRef state
= PredI
->getState();
3590 state
= processPointerEscapedOnBind(state
, location
, Val
, LC
);
3592 // When binding the value, pass on the hint that this is a initialization.
3593 // For initializations, we do not need to inform clients of region
3595 state
= state
->bindLoc(location
.castAs
<Loc
>(),
3596 Val
, LC
, /* notifyChanges = */ !atDeclInit
);
3598 const MemRegion
*LocReg
= nullptr;
3599 if (std::optional
<loc::MemRegionVal
> LocRegVal
=
3600 location
.getAs
<loc::MemRegionVal
>()) {
3601 LocReg
= LocRegVal
->getRegion();
3604 const ProgramPoint L
= PostStore(StoreE
, LC
, LocReg
, nullptr);
3605 Bldr
.generateNode(L
, state
, PredI
);
3609 /// evalStore - Handle the semantics of a store via an assignment.
3610 /// @param Dst The node set to store generated state nodes
3611 /// @param AssignE The assignment expression if the store happens in an
3613 /// @param LocationE The location expression that is stored to.
3614 /// @param state The current simulation state
3615 /// @param location The location to store the value
3616 /// @param Val The value to be stored
3617 void ExprEngine::evalStore(ExplodedNodeSet
&Dst
, const Expr
*AssignE
,
3618 const Expr
*LocationE
,
3620 ProgramStateRef state
, SVal location
, SVal Val
,
3621 const ProgramPointTag
*tag
) {
3622 // Proceed with the store. We use AssignE as the anchor for the PostStore
3623 // ProgramPoint if it is non-NULL, and LocationE otherwise.
3624 const Expr
*StoreE
= AssignE
? AssignE
: LocationE
;
3626 // Evaluate the location (checks for bad dereferences).
3627 ExplodedNodeSet Tmp
;
3628 evalLocation(Tmp
, AssignE
, LocationE
, Pred
, state
, location
, false);
3633 if (location
.isUndef())
3636 for (const auto I
: Tmp
)
3637 evalBind(Dst
, StoreE
, I
, location
, Val
, false);
3640 void ExprEngine::evalLoad(ExplodedNodeSet
&Dst
,
3642 const Expr
*BoundEx
,
3644 ProgramStateRef state
,
3646 const ProgramPointTag
*tag
,
3648 assert(!isa
<NonLoc
>(location
) && "location cannot be a NonLoc.");
3651 // Evaluate the location (checks for bad dereferences).
3652 ExplodedNodeSet Tmp
;
3653 evalLocation(Tmp
, NodeEx
, BoundEx
, Pred
, state
, location
, true);
3657 StmtNodeBuilder
Bldr(Tmp
, Dst
, *currBldrCtx
);
3658 if (location
.isUndef())
3661 // Proceed with the load.
3662 for (const auto I
: Tmp
) {
3663 state
= I
->getState();
3664 const LocationContext
*LCtx
= I
->getLocationContext();
3666 SVal V
= UnknownVal();
3667 if (location
.isValid()) {
3668 if (LoadTy
.isNull())
3669 LoadTy
= BoundEx
->getType();
3670 V
= state
->getSVal(location
.castAs
<Loc
>(), LoadTy
);
3673 Bldr
.generateNode(NodeEx
, I
, state
->BindExpr(BoundEx
, LCtx
, V
), tag
,
3674 ProgramPoint::PostLoadKind
);
3678 void ExprEngine::evalLocation(ExplodedNodeSet
&Dst
,
3680 const Stmt
*BoundEx
,
3682 ProgramStateRef state
,
3685 StmtNodeBuilder
BldrTop(Pred
, Dst
, *currBldrCtx
);
3686 // Early checks for performance reason.
3687 if (location
.isUnknown()) {
3691 ExplodedNodeSet Src
;
3692 BldrTop
.takeNodes(Pred
);
3693 StmtNodeBuilder
Bldr(Pred
, Src
, *currBldrCtx
);
3694 if (Pred
->getState() != state
) {
3695 // Associate this new state with an ExplodedNode.
3696 // FIXME: If I pass null tag, the graph is incorrect, e.g for
3700 // "p = 0" is not noted as "Null pointer value stored to 'p'" but
3701 // instead "int *p" is noted as
3702 // "Variable 'p' initialized to a null pointer value"
3704 static SimpleProgramPointTag
tag(TagProviderName
, "Location");
3705 Bldr
.generateNode(NodeEx
, Pred
, state
, &tag
);
3707 ExplodedNodeSet Tmp
;
3708 getCheckerManager().runCheckersForLocation(Tmp
, Src
, location
, isLoad
,
3709 NodeEx
, BoundEx
, *this);
3710 BldrTop
.addNodes(Tmp
);
3713 std::pair
<const ProgramPointTag
*, const ProgramPointTag
*>
3714 ExprEngine::geteagerlyAssumeBinOpBifurcationTags() {
3715 static SimpleProgramPointTag
3716 eagerlyAssumeBinOpBifurcationTrue(TagProviderName
,
3717 "Eagerly Assume True"),
3718 eagerlyAssumeBinOpBifurcationFalse(TagProviderName
,
3719 "Eagerly Assume False");
3720 return std::make_pair(&eagerlyAssumeBinOpBifurcationTrue
,
3721 &eagerlyAssumeBinOpBifurcationFalse
);
3724 void ExprEngine::evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet
&Dst
,
3725 ExplodedNodeSet
&Src
,
3727 StmtNodeBuilder
Bldr(Src
, Dst
, *currBldrCtx
);
3729 for (const auto Pred
: Src
) {
3730 // Test if the previous node was as the same expression. This can happen
3731 // when the expression fails to evaluate to anything meaningful and
3732 // (as an optimization) we don't generate a node.
3733 ProgramPoint P
= Pred
->getLocation();
3734 if (!P
.getAs
<PostStmt
>() || P
.castAs
<PostStmt
>().getStmt() != Ex
) {
3738 ProgramStateRef state
= Pred
->getState();
3739 SVal V
= state
->getSVal(Ex
, Pred
->getLocationContext());
3740 std::optional
<nonloc::SymbolVal
> SEV
= V
.getAs
<nonloc::SymbolVal
>();
3741 if (SEV
&& SEV
->isExpression()) {
3742 const std::pair
<const ProgramPointTag
*, const ProgramPointTag
*> &tags
=
3743 geteagerlyAssumeBinOpBifurcationTags();
3745 ProgramStateRef StateTrue
, StateFalse
;
3746 std::tie(StateTrue
, StateFalse
) = state
->assume(*SEV
);
3748 // First assume that the condition is true.
3750 SVal Val
= svalBuilder
.makeIntVal(1U, Ex
->getType());
3751 StateTrue
= StateTrue
->BindExpr(Ex
, Pred
->getLocationContext(), Val
);
3752 Bldr
.generateNode(Ex
, Pred
, StateTrue
, tags
.first
);
3755 // Next, assume that the condition is false.
3757 SVal Val
= svalBuilder
.makeIntVal(0U, Ex
->getType());
3758 StateFalse
= StateFalse
->BindExpr(Ex
, Pred
->getLocationContext(), Val
);
3759 Bldr
.generateNode(Ex
, Pred
, StateFalse
, tags
.second
);
3765 void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt
*A
, ExplodedNode
*Pred
,
3766 ExplodedNodeSet
&Dst
) {
3767 StmtNodeBuilder
Bldr(Pred
, Dst
, *currBldrCtx
);
3768 // We have processed both the inputs and the outputs. All of the outputs
3769 // should evaluate to Locs. Nuke all of their values.
3771 // FIXME: Some day in the future it would be nice to allow a "plug-in"
3772 // which interprets the inline asm and stores proper results in the
3775 ProgramStateRef state
= Pred
->getState();
3777 for (const Expr
*O
: A
->outputs()) {
3778 SVal X
= state
->getSVal(O
, Pred
->getLocationContext());
3779 assert(!isa
<NonLoc
>(X
)); // Should be an Lval, or unknown, undef.
3781 if (std::optional
<Loc
> LV
= X
.getAs
<Loc
>())
3782 state
= state
->bindLoc(*LV
, UnknownVal(), Pred
->getLocationContext());
3785 Bldr
.generateNode(A
, Pred
, state
);
3788 void ExprEngine::VisitMSAsmStmt(const MSAsmStmt
*A
, ExplodedNode
*Pred
,
3789 ExplodedNodeSet
&Dst
) {
3790 StmtNodeBuilder
Bldr(Pred
, Dst
, *currBldrCtx
);
3791 Bldr
.generateNode(A
, Pred
, Pred
->getState());
3794 //===----------------------------------------------------------------------===//
3796 //===----------------------------------------------------------------------===//
3801 struct DOTGraphTraits
<ExplodedGraph
*> : public DefaultDOTGraphTraits
{
3802 DOTGraphTraits (bool isSimple
= false) : DefaultDOTGraphTraits(isSimple
) {}
3804 static bool nodeHasBugReport(const ExplodedNode
*N
) {
3805 BugReporter
&BR
= static_cast<ExprEngine
&>(
3806 N
->getState()->getStateManager().getOwningEngine()).getBugReporter();
3808 for (const auto &Class
: BR
.equivalenceClasses()) {
3809 for (const auto &Report
: Class
.getReports()) {
3810 const auto *PR
= dyn_cast
<PathSensitiveBugReport
>(Report
.get());
3813 const ExplodedNode
*EN
= PR
->getErrorNode();
3814 if (EN
->getState() == N
->getState() &&
3815 EN
->getLocation() == N
->getLocation())
3822 /// \p PreCallback: callback before break.
3823 /// \p PostCallback: callback after break.
3824 /// \p Stop: stop iteration if returns @c true
3825 /// \return Whether @c Stop ever returned @c true.
3826 static bool traverseHiddenNodes(
3827 const ExplodedNode
*N
,
3828 llvm::function_ref
<void(const ExplodedNode
*)> PreCallback
,
3829 llvm::function_ref
<void(const ExplodedNode
*)> PostCallback
,
3830 llvm::function_ref
<bool(const ExplodedNode
*)> Stop
) {
3836 if (N
->succ_size() != 1 || !isNodeHidden(N
->getFirstSucc(), nullptr))
3840 N
= N
->getFirstSucc();
3845 static bool isNodeHidden(const ExplodedNode
*N
, const ExplodedGraph
*G
) {
3846 return N
->isTrivial();
3849 static std::string
getNodeLabel(const ExplodedNode
*N
, ExplodedGraph
*G
){
3851 llvm::raw_string_ostream
Out(Buf
);
3853 const bool IsDot
= true;
3854 const unsigned int Space
= 1;
3855 ProgramStateRef State
= N
->getState();
3857 Out
<< "{ \"state_id\": " << State
->getID()
3860 Indent(Out
, Space
, IsDot
) << "\"program_points\": [\\l";
3862 // Dump program point for all the previously skipped nodes.
3863 traverseHiddenNodes(
3865 [&](const ExplodedNode
*OtherNode
) {
3866 Indent(Out
, Space
+ 1, IsDot
) << "{ ";
3867 OtherNode
->getLocation().printJson(Out
, /*NL=*/"\\l");
3868 Out
<< ", \"tag\": ";
3869 if (const ProgramPointTag
*Tag
= OtherNode
->getLocation().getTag())
3870 Out
<< '\"' << Tag
->getTagDescription() << '\"';
3873 Out
<< ", \"node_id\": " << OtherNode
->getID() <<
3874 ", \"is_sink\": " << OtherNode
->isSink() <<
3875 ", \"has_report\": " << nodeHasBugReport(OtherNode
) << " }";
3877 // Adds a comma and a new-line between each program point.
3878 [&](const ExplodedNode
*) { Out
<< ",\\l"; },
3879 [&](const ExplodedNode
*) { return false; });
3881 Out
<< "\\l"; // Adds a new-line to the last program point.
3882 Indent(Out
, Space
, IsDot
) << "],\\l";
3884 State
->printDOT(Out
, N
->getLocationContext(), Space
);
3893 void ExprEngine::ViewGraph(bool trim
) {
3894 std::string Filename
= DumpGraph(trim
);
3895 llvm::DisplayGraph(Filename
, false, llvm::GraphProgram::DOT
);
3898 void ExprEngine::ViewGraph(ArrayRef
<const ExplodedNode
*> Nodes
) {
3899 std::string Filename
= DumpGraph(Nodes
);
3900 llvm::DisplayGraph(Filename
, false, llvm::GraphProgram::DOT
);
3903 std::string
ExprEngine::DumpGraph(bool trim
, StringRef Filename
) {
3905 std::vector
<const ExplodedNode
*> Src
;
3907 // Iterate through the reports and get their nodes.
3908 for (const auto &Class
: BR
.equivalenceClasses()) {
3910 dyn_cast
<PathSensitiveBugReport
>(Class
.getReports()[0].get());
3913 const auto *N
= const_cast<ExplodedNode
*>(R
->getErrorNode());
3916 return DumpGraph(Src
, Filename
);
3919 return llvm::WriteGraph(&G
, "ExprEngine", /*ShortNames=*/false,
3920 /*Title=*/"Exploded Graph",
3921 /*Filename=*/std::string(Filename
));
3924 std::string
ExprEngine::DumpGraph(ArrayRef
<const ExplodedNode
*> Nodes
,
3925 StringRef Filename
) {
3926 std::unique_ptr
<ExplodedGraph
> TrimmedG(G
.trim(Nodes
));
3928 if (!TrimmedG
.get()) {
3929 llvm::errs() << "warning: Trimmed ExplodedGraph is empty.\n";
3933 return llvm::WriteGraph(TrimmedG
.get(), "TrimmedExprEngine",
3934 /*ShortNames=*/false,
3935 /*Title=*/"Trimmed Exploded Graph",
3936 /*Filename=*/std::string(Filename
));
3939 void *ProgramStateTrait
<ReplayWithoutInlining
>::GDMIndex() {
3940 static int index
= 0;
3944 void ExprEngine::anchor() { }