Coverage Report

Created: 2023-09-12 09:32

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