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