Coverage Report

Created: 2023-09-12 09:32

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- BugReporterVisitors.cpp - Helpers for reporting bugs ---------------===//
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 set of BugReporter "visitors" which can be used to
10
//  enhance the diagnostics reported for a bug.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
15
#include "clang/AST/ASTContext.h"
16
#include "clang/AST/Decl.h"
17
#include "clang/AST/DeclBase.h"
18
#include "clang/AST/DeclCXX.h"
19
#include "clang/AST/Expr.h"
20
#include "clang/AST/ExprCXX.h"
21
#include "clang/AST/ExprObjC.h"
22
#include "clang/AST/Stmt.h"
23
#include "clang/AST/Type.h"
24
#include "clang/ASTMatchers/ASTMatchFinder.h"
25
#include "clang/Analysis/Analyses/Dominators.h"
26
#include "clang/Analysis/AnalysisDeclContext.h"
27
#include "clang/Analysis/CFG.h"
28
#include "clang/Analysis/CFGStmtMap.h"
29
#include "clang/Analysis/PathDiagnostic.h"
30
#include "clang/Analysis/ProgramPoint.h"
31
#include "clang/Basic/IdentifierTable.h"
32
#include "clang/Basic/LLVM.h"
33
#include "clang/Basic/SourceLocation.h"
34
#include "clang/Basic/SourceManager.h"
35
#include "clang/Lex/Lexer.h"
36
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
37
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
38
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
39
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
40
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
41
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
42
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
43
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
44
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
45
#include "clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h"
46
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
47
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
48
#include "llvm/ADT/ArrayRef.h"
49
#include "llvm/ADT/STLExtras.h"
50
#include "llvm/ADT/SmallPtrSet.h"
51
#include "llvm/ADT/SmallString.h"
52
#include "llvm/ADT/SmallVector.h"
53
#include "llvm/ADT/StringExtras.h"
54
#include "llvm/ADT/StringRef.h"
55
#include "llvm/Support/Casting.h"
56
#include "llvm/Support/ErrorHandling.h"
57
#include "llvm/Support/raw_ostream.h"
58
#include <cassert>
59
#include <deque>
60
#include <memory>
61
#include <optional>
62
#include <string>
63
#include <utility>
64
65
using namespace clang;
66
using namespace ento;
67
using namespace bugreporter;
68
69
//===----------------------------------------------------------------------===//
70
// Utility functions.
71
//===----------------------------------------------------------------------===//
72
73
1.06k
static const Expr *peelOffPointerArithmetic(const BinaryOperator *B) {
74
1.06k
  if (B->isAdditiveOp() && 
B->getType()->isPointerType()102
) {
75
32
    if (B->getLHS()->getType()->isPointerType()) {
76
30
      return B->getLHS();
77
30
    } else 
if (2
B->getRHS()->getType()->isPointerType()2
) {
78
2
      return B->getRHS();
79
2
    }
80
32
  }
81
1.03k
  return nullptr;
82
1.06k
}
83
84
/// \return A subexpression of @c Ex which represents the
85
/// expression-of-interest.
86
static const Expr *peelOffOuterExpr(const Expr *Ex, const ExplodedNode *N);
87
88
/// Given that expression S represents a pointer that would be dereferenced,
89
/// try to find a sub-expression from which the pointer came from.
90
/// This is used for tracking down origins of a null or undefined value:
91
/// "this is null because that is null because that is null" etc.
92
/// We wipe away field and element offsets because they merely add offsets.
93
/// We also wipe away all casts except lvalue-to-rvalue casts, because the
94
/// latter represent an actual pointer dereference; however, we remove
95
/// the final lvalue-to-rvalue cast before returning from this function
96
/// because it demonstrates more clearly from where the pointer rvalue was
97
/// loaded. Examples:
98
///   x->y.z      ==>  x (lvalue)
99
///   foo()->y.z  ==>  foo() (rvalue)
100
992
const Expr *bugreporter::getDerefExpr(const Stmt *S) {
101
992
  const auto *E = dyn_cast<Expr>(S);
102
992
  if (!E)
103
0
    return nullptr;
104
105
2.16k
  
while (992
true) {
106
2.16k
    if (const auto *CE = dyn_cast<CastExpr>(E)) {
107
961
      if (CE->getCastKind() == CK_LValueToRValue) {
108
        // This cast represents the load we're looking for.
109
843
        break;
110
843
      }
111
118
      E = CE->getSubExpr();
112
1.20k
    } else if (const auto *B = dyn_cast<BinaryOperator>(E)) {
113
      // Pointer arithmetic: '*(x + 2)' -> 'x') etc.
114
15
      if (const Expr *Inner = peelOffPointerArithmetic(B)) {
115
13
        E = Inner;
116
13
      } else {
117
        // Probably more arithmetic can be pattern-matched here,
118
        // but for now give up.
119
2
        break;
120
2
      }
121
1.18k
    } else if (const auto *U = dyn_cast<UnaryOperator>(E)) {
122
851
      if (U->getOpcode() == UO_Deref || 
U->getOpcode() == UO_AddrOf8
||
123
851
          
(4
U->isIncrementDecrementOp()4
&&
U->getType()->isPointerType()4
)) {
124
        // Operators '*' and '&' don't actually mean anything.
125
        // We look at casts instead.
126
851
        E = U->getSubExpr();
127
851
      } else {
128
        // Probably more arithmetic can be pattern-matched here,
129
        // but for now give up.
130
0
        break;
131
0
      }
132
851
    }
133
    // Pattern match for a few useful cases: a[0], p->f, *p etc.
134
338
    else if (const auto *ME = dyn_cast<MemberExpr>(E)) {
135
58
      E = ME->getBase();
136
280
    } else if (const auto *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) {
137
16
      E = IvarRef->getBase();
138
264
    } else if (const auto *AE = dyn_cast<ArraySubscriptExpr>(E)) {
139
72
      E = AE->getBase();
140
192
    } else if (const auto *PE = dyn_cast<ParenExpr>(E)) {
141
44
      E = PE->getSubExpr();
142
148
    } else if (const auto *FE = dyn_cast<FullExpr>(E)) {
143
1
      E = FE->getSubExpr();
144
147
    } else {
145
      // Other arbitrary stuff.
146
147
      break;
147
147
    }
148
2.16k
  }
149
150
  // Special case: remove the final lvalue-to-rvalue cast, but do not recurse
151
  // deeper into the sub-expression. This way we return the lvalue from which
152
  // our pointer rvalue was loaded.
153
992
  if (const auto *CE = dyn_cast<ImplicitCastExpr>(E))
154
843
    if (CE->getCastKind() == CK_LValueToRValue)
155
843
      E = CE->getSubExpr();
156
157
992
  return E;
158
992
}
159
160
static const MemRegion *
161
getLocationRegionIfReference(const Expr *E, const ExplodedNode *N,
162
4.79k
                             bool LookingForReference = true) {
163
4.79k
  if (const auto *DR = dyn_cast<DeclRefExpr>(E)) {
164
3.02k
    if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
165
2.99k
      if (LookingForReference && 
!VD->getType()->isReferenceType()2.82k
)
166
2.77k
        return nullptr;
167
224
      return N->getState()
168
224
          ->getLValue(VD, N->getLocationContext())
169
224
          .getAsRegion();
170
2.99k
    }
171
3.02k
  }
172
173
  // FIXME: This does not handle other kinds of null references,
174
  // for example, references from FieldRegions:
175
  //   struct Wrapper { int &ref; };
176
  //   Wrapper w = { *(int *)0 };
177
  //   w.ref = 1;
178
179
1.79k
  return nullptr;
180
4.79k
}
181
182
/// Comparing internal representations of symbolic values (via
183
/// SVal::operator==()) is a valid way to check if the value was updated,
184
/// unless it's a LazyCompoundVal that may have a different internal
185
/// representation every time it is loaded from the state. In this function we
186
/// do an approximate comparison for lazy compound values, checking that they
187
/// are the immediate snapshots of the tracked region's bindings within the
188
/// node's respective states but not really checking that these snapshots
189
/// actually contain the same set of bindings.
190
static bool hasVisibleUpdate(const ExplodedNode *LeftNode, SVal LeftVal,
191
67.6k
                             const ExplodedNode *RightNode, SVal RightVal) {
192
67.6k
  if (LeftVal == RightVal)
193
66.9k
    return true;
194
195
717
  const auto LLCV = LeftVal.getAs<nonloc::LazyCompoundVal>();
196
717
  if (!LLCV)
197
637
    return false;
198
199
80
  const auto RLCV = RightVal.getAs<nonloc::LazyCompoundVal>();
200
80
  if (!RLCV)
201
0
    return false;
202
203
80
  return LLCV->getRegion() == RLCV->getRegion() &&
204
80
    LLCV->getStore() == LeftNode->getState()->getStore() &&
205
80
    RLCV->getStore() == RightNode->getState()->getStore();
206
80
}
207
208
static std::optional<SVal> getSValForVar(const Expr *CondVarExpr,
209
2.50k
                                         const ExplodedNode *N) {
210
2.50k
  ProgramStateRef State = N->getState();
211
2.50k
  const LocationContext *LCtx = N->getLocationContext();
212
213
2.50k
  assert(CondVarExpr);
214
2.50k
  CondVarExpr = CondVarExpr->IgnoreImpCasts();
215
216
  // The declaration of the value may rely on a pointer so take its l-value.
217
  // FIXME: As seen in VisitCommonDeclRefExpr, sometimes DeclRefExpr may
218
  // evaluate to a FieldRegion when it refers to a declaration of a lambda
219
  // capture variable. We most likely need to duplicate that logic here.
220
2.50k
  if (const auto *DRE = dyn_cast<DeclRefExpr>(CondVarExpr))
221
1.69k
    if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
222
1.69k
      return State->getSVal(State->getLValue(VD, LCtx));
223
224
811
  if (const auto *ME = dyn_cast<MemberExpr>(CondVarExpr))
225
284
    if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
226
284
      if (auto FieldL = State->getSVal(ME, LCtx).getAs<Loc>())
227
284
        return State->getRawSVal(*FieldL, FD->getType());
228
229
527
  return std::nullopt;
230
811
}
231
232
static std::optional<const llvm::APSInt *>
233
528
getConcreteIntegerValue(const Expr *CondVarExpr, const ExplodedNode *N) {
234
235
528
  if (std::optional<SVal> V = getSValForVar(CondVarExpr, N))
236
528
    if (auto CI = V->getAs<nonloc::ConcreteInt>())
237
174
      return &CI->getValue();
238
354
  return std::nullopt;
239
528
}
240
241
static bool isVarAnInterestingCondition(const Expr *CondVarExpr,
242
                                        const ExplodedNode *N,
243
11.0k
                                        const PathSensitiveBugReport *B) {
244
  // Even if this condition is marked as interesting, it isn't *that*
245
  // interesting if it didn't happen in a nested stackframe, the user could just
246
  // follow the arrows.
247
11.0k
  if (!B->getErrorNode()->getStackFrame()->isParentOf(N->getStackFrame()))
248
10.1k
    return false;
249
250
964
  if (std::optional<SVal> V = getSValForVar(CondVarExpr, N))
251
437
    if (std::optional<bugreporter::TrackingKind> K =
252
437
            B->getInterestingnessKind(*V))
253
79
      return *K == bugreporter::TrackingKind::Condition;
254
255
885
  return false;
256
964
}
257
258
static bool isInterestingExpr(const Expr *E, const ExplodedNode *N,
259
1.01k
                              const PathSensitiveBugReport *B) {
260
1.01k
  if (std::optional<SVal> V = getSValForVar(E, N))
261
1.01k
    return B->getInterestingnessKind(*V).has_value();
262
0
  return false;
263
1.01k
}
264
265
/// \return name of the macro inside the location \p Loc.
266
static StringRef getMacroName(SourceLocation Loc,
267
33
    BugReporterContext &BRC) {
268
33
  return Lexer::getImmediateMacroName(
269
33
      Loc,
270
33
      BRC.getSourceManager(),
271
33
      BRC.getASTContext().getLangOpts());
272
33
}
273
274
/// \return Whether given spelling location corresponds to an expansion
275
/// of a function-like macro.
276
static bool isFunctionMacroExpansion(SourceLocation Loc,
277
1.43k
                                const SourceManager &SM) {
278
1.43k
  if (!Loc.isMacroID())
279
1.22k
    return false;
280
207
  while (SM.isMacroArgExpansion(Loc))
281
0
    Loc = SM.getImmediateExpansionRange(Loc).getBegin();
282
207
  std::pair<FileID, unsigned> TLInfo = SM.getDecomposedLoc(Loc);
283
207
  SrcMgr::SLocEntry SE = SM.getSLocEntry(TLInfo.first);
284
207
  const SrcMgr::ExpansionInfo &EInfo = SE.getExpansion();
285
207
  return EInfo.isFunctionMacroExpansion();
286
1.43k
}
287
288
/// \return Whether \c RegionOfInterest was modified at \p N,
289
/// where \p ValueAfter is \c RegionOfInterest's value at the end of the
290
/// stack frame.
291
static bool wasRegionOfInterestModifiedAt(const SubRegion *RegionOfInterest,
292
                                          const ExplodedNode *N,
293
41.7k
                                          SVal ValueAfter) {
294
41.7k
  ProgramStateRef State = N->getState();
295
41.7k
  ProgramStateManager &Mgr = N->getState()->getStateManager();
296
297
41.7k
  if (!N->getLocationAs<PostStore>() && 
!N->getLocationAs<PostInitializer>()40.3k
&&
298
41.7k
      
!N->getLocationAs<PostStmt>()40.1k
)
299
15.0k
    return false;
300
301
  // Writing into region of interest.
302
26.7k
  if (auto PS = N->getLocationAs<PostStmt>())
303
26.5k
    if (auto *BO = PS->getStmtAs<BinaryOperator>())
304
2.00k
      if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(
305
1.53k
                                      N->getSVal(BO->getLHS()).getAsRegion()))
306
405
        return true;
307
308
  // SVal after the state is possibly different.
309
26.3k
  SVal ValueAtN = N->getState()->getSVal(RegionOfInterest);
310
26.3k
  if (!Mgr.getSValBuilder()
311
26.3k
           .areEqual(State, ValueAtN, ValueAfter)
312
26.3k
           .isConstrainedTrue() &&
313
26.3k
      
(7.38k
!ValueAtN.isUndef()7.38k
||
!ValueAfter.isUndef()6.19k
))
314
2.41k
    return true;
315
316
23.9k
  return false;
317
26.3k
}
318
319
//===----------------------------------------------------------------------===//
320
// Implementation of BugReporterVisitor.
321
//===----------------------------------------------------------------------===//
322
323
PathDiagnosticPieceRef BugReporterVisitor::getEndPath(BugReporterContext &,
324
                                                      const ExplodedNode *,
325
100k
                                                      PathSensitiveBugReport &) {
326
100k
  return nullptr;
327
100k
}
328
329
void BugReporterVisitor::finalizeVisitor(BugReporterContext &,
330
                                         const ExplodedNode *,
331
81.0k
                                         PathSensitiveBugReport &) {}
332
333
PathDiagnosticPieceRef
334
BugReporterVisitor::getDefaultEndPath(const BugReporterContext &BRC,
335
                                      const ExplodedNode *EndPathNode,
336
2.02k
                                      const PathSensitiveBugReport &BR) {
337
2.02k
  PathDiagnosticLocation L = BR.getLocation();
338
2.02k
  const auto &Ranges = BR.getRanges();
339
340
  // Only add the statement itself as a range if we didn't specify any
341
  // special ranges for this report.
342
2.02k
  auto P = std::make_shared<PathDiagnosticEventPiece>(
343
2.02k
      L, BR.getDescription(), Ranges.begin() == Ranges.end());
344
2.02k
  for (SourceRange Range : Ranges)
345
1.94k
    P->addRange(Range);
346
347
2.02k
  return P;
348
2.02k
}
349
350
//===----------------------------------------------------------------------===//
351
// Implementation of NoStateChangeFuncVisitor.
352
//===----------------------------------------------------------------------===//
353
354
1.37k
bool NoStateChangeFuncVisitor::isModifiedInFrame(const ExplodedNode *N) {
355
1.37k
  const LocationContext *Ctx = N->getLocationContext();
356
1.37k
  const StackFrameContext *SCtx = Ctx->getStackFrame();
357
1.37k
  if (!FramesModifyingCalculated.count(SCtx))
358
1.17k
    findModifyingFrames(N);
359
1.37k
  return FramesModifying.count(SCtx);
360
1.37k
}
361
362
void NoStateChangeFuncVisitor::markFrameAsModifying(
363
3.08k
    const StackFrameContext *SCtx) {
364
3.44k
  while (!SCtx->inTopFrame()) {
365
2.02k
    auto p = FramesModifying.insert(SCtx);
366
2.02k
    if (!p.second)
367
1.66k
      break; // Frame and all its parents already inserted.
368
369
361
    SCtx = SCtx->getParent()->getStackFrame();
370
361
  }
371
3.08k
}
372
373
1.34k
static const ExplodedNode *getMatchingCallExitEnd(const ExplodedNode *N) {
374
1.34k
  assert(N->getLocationAs<CallEnter>());
375
  // The stackframe of the callee is only found in the nodes succeeding
376
  // the CallEnter node. CallEnter's stack frame refers to the caller.
377
1.34k
  const StackFrameContext *OrigSCtx = N->getFirstSucc()->getStackFrame();
378
379
  // Similarly, the nodes preceding CallExitEnd refer to the callee's stack
380
  // frame.
381
35.7k
  auto IsMatchingCallExitEnd = [OrigSCtx](const ExplodedNode *N) {
382
35.7k
    return N->getLocationAs<CallExitEnd>() &&
383
35.7k
           
OrigSCtx == N->getFirstPred()->getStackFrame()1.58k
;
384
35.7k
  };
385
35.7k
  while (N && 
!IsMatchingCallExitEnd(N)35.7k
) {
386
34.4k
    assert(N->succ_size() <= 1 &&
387
34.4k
           "This function is to be used on the trimmed ExplodedGraph!");
388
34.4k
    N = N->getFirstSucc();
389
34.4k
  }
390
1.34k
  return N;
391
1.34k
}
392
393
void NoStateChangeFuncVisitor::findModifyingFrames(
394
1.17k
    const ExplodedNode *const CallExitBeginN) {
395
396
1.17k
  assert(CallExitBeginN->getLocationAs<CallExitBegin>());
397
398
1.17k
  const StackFrameContext *const OriginalSCtx =
399
1.17k
      CallExitBeginN->getLocationContext()->getStackFrame();
400
401
1.17k
  const ExplodedNode *CurrCallExitBeginN = CallExitBeginN;
402
1.17k
  const StackFrameContext *CurrentSCtx = OriginalSCtx;
403
404
26.2k
  for (const ExplodedNode *CurrN = CallExitBeginN; CurrN;
405
26.2k
       
CurrN = CurrN->getFirstPred()25.0k
) {
406
    // Found a new inlined call.
407
26.2k
    if (CurrN->getLocationAs<CallExitBegin>()) {
408
1.34k
      CurrCallExitBeginN = CurrN;
409
1.34k
      CurrentSCtx = CurrN->getStackFrame();
410
1.34k
      FramesModifyingCalculated.insert(CurrentSCtx);
411
      // We won't see a change in between two identical exploded nodes: skip.
412
1.34k
      continue;
413
1.34k
    }
414
415
24.8k
    if (auto CE = CurrN->getLocationAs<CallEnter>()) {
416
1.34k
      if (const ExplodedNode *CallExitEndN = getMatchingCallExitEnd(CurrN))
417
1.34k
        if (wasModifiedInFunction(CurrN, CallExitEndN))
418
84
          markFrameAsModifying(CurrentSCtx);
419
420
      // We exited this inlined call, lets actualize the stack frame.
421
1.34k
      CurrentSCtx = CurrN->getStackFrame();
422
423
      // Stop calculating at the current function, but always regard it as
424
      // modifying, so we can avoid notes like this:
425
      //   void f(Foo &F) {
426
      //     F.field = 0; // note: 0 assigned to 'F.field'
427
      //                  // note: returning without writing to 'F.field'
428
      //   }
429
1.34k
      if (CE->getCalleeContext() == OriginalSCtx) {
430
1.17k
        markFrameAsModifying(CurrentSCtx);
431
1.17k
        break;
432
1.17k
      }
433
1.34k
    }
434
435
23.7k
    if (wasModifiedBeforeCallExit(CurrN, CurrCallExitBeginN))
436
1.82k
      markFrameAsModifying(CurrentSCtx);
437
23.7k
  }
438
1.17k
}
439
440
PathDiagnosticPieceRef NoStateChangeFuncVisitor::VisitNode(
441
135k
    const ExplodedNode *N, BugReporterContext &BR, PathSensitiveBugReport &R) {
442
443
135k
  const LocationContext *Ctx = N->getLocationContext();
444
135k
  const StackFrameContext *SCtx = Ctx->getStackFrame();
445
135k
  ProgramStateRef State = N->getState();
446
135k
  auto CallExitLoc = N->getLocationAs<CallExitBegin>();
447
448
  // No diagnostic if region was modified inside the frame.
449
135k
  if (!CallExitLoc || 
isModifiedInFrame(N)1.37k
)
450
134k
    return nullptr;
451
452
1.07k
  CallEventRef<> Call =
453
1.07k
      BR.getStateManager().getCallEventManager().getCaller(SCtx, State);
454
455
  // Optimistically suppress uninitialized value bugs that result
456
  // from system headers having a chance to initialize the value
457
  // but failing to do so. It's too unlikely a system header's fault.
458
  // It's much more likely a situation in which the function has a failure
459
  // mode that the user decided not to check. If we want to hunt such
460
  // omitted checks, we should provide an explicit function-specific note
461
  // describing the precondition under which the function isn't supposed to
462
  // initialize its out-parameter, and additionally check that such
463
  // precondition can actually be fulfilled on the current path.
464
1.07k
  if (Call->isInSystemHeader()) {
465
    // We make an exception for system header functions that have no branches.
466
    // Such functions unconditionally fail to initialize the variable.
467
    // If they call other functions that have more paths within them,
468
    // this suppression would still apply when we visit these inner functions.
469
    // One common example of a standard function that doesn't ever initialize
470
    // its out parameter is operator placement new; it's up to the follow-up
471
    // constructor (if any) to initialize the memory.
472
20
    if (!N->getStackFrame()->getCFG()->isLinear()) {
473
1
      static int i = 0;
474
1
      R.markInvalid(&i, nullptr);
475
1
    }
476
20
    return nullptr;
477
20
  }
478
479
1.05k
  if (const auto *MC = dyn_cast<ObjCMethodCall>(Call)) {
480
    // If we failed to construct a piece for self, we still want to check
481
    // whether the entity of interest is in a parameter.
482
118
    if (PathDiagnosticPieceRef Piece = maybeEmitNoteForObjCSelf(R, *MC, N))
483
2
      return Piece;
484
118
  }
485
486
1.05k
  if (const auto *CCall = dyn_cast<CXXConstructorCall>(Call)) {
487
    // Do not generate diagnostics for not modified parameters in
488
    // constructors.
489
230
    return maybeEmitNoteForCXXThis(R, *CCall, N);
490
230
  }
491
492
824
  return maybeEmitNoteForParameters(R, *Call, N);
493
1.05k
}
494
495
//===----------------------------------------------------------------------===//
496
// Implementation of NoStoreFuncVisitor.
497
//===----------------------------------------------------------------------===//
498
499
namespace {
500
/// Put a diagnostic on return statement of all inlined functions
501
/// for which  the region of interest \p RegionOfInterest was passed into,
502
/// but not written inside, and it has caused an undefined read or a null
503
/// pointer dereference outside.
504
class NoStoreFuncVisitor final : public NoStateChangeFuncVisitor {
505
  const SubRegion *RegionOfInterest;
506
  MemRegionManager &MmrMgr;
507
  const SourceManager &SM;
508
  const PrintingPolicy &PP;
509
510
  /// Recursion limit for dereferencing fields when looking for the
511
  /// region of interest.
512
  /// The limit of two indicates that we will dereference fields only once.
513
  static const unsigned DEREFERENCE_LIMIT = 2;
514
515
  using RegionVector = SmallVector<const MemRegion *, 5>;
516
517
public:
518
  NoStoreFuncVisitor(const SubRegion *R, bugreporter::TrackingKind TKind)
519
      : NoStateChangeFuncVisitor(TKind), RegionOfInterest(R),
520
        MmrMgr(R->getMemRegionManager()),
521
        SM(MmrMgr.getContext().getSourceManager()),
522
3.08k
        PP(MmrMgr.getContext().getPrintingPolicy()) {}
523
524
3.08k
  void Profile(llvm::FoldingSetNodeID &ID) const override {
525
3.08k
    static int Tag = 0;
526
3.08k
    ID.AddPointer(&Tag);
527
3.08k
    ID.AddPointer(RegionOfInterest);
528
3.08k
  }
529
530
private:
531
  /// \return Whether \c RegionOfInterest was modified at \p CurrN compared to
532
  /// the value it holds in \p CallExitBeginN.
533
  bool wasModifiedBeforeCallExit(const ExplodedNode *CurrN,
534
                                 const ExplodedNode *CallExitBeginN) override;
535
536
  /// Attempts to find the region of interest in a given record decl,
537
  /// by either following the base classes or fields.
538
  /// Dereferences fields up to a given recursion limit.
539
  /// Note that \p Vec is passed by value, leading to quadratic copying cost,
540
  /// but it's OK in practice since its length is limited to DEREFERENCE_LIMIT.
541
  /// \return A chain fields leading to the region of interest or std::nullopt.
542
  const std::optional<RegionVector>
543
  findRegionOfInterestInRecord(const RecordDecl *RD, ProgramStateRef State,
544
                               const MemRegion *R, const RegionVector &Vec = {},
545
                               int depth = 0);
546
547
  // Region of interest corresponds to an IVar, exiting a method
548
  // which could have written into that IVar, but did not.
549
  PathDiagnosticPieceRef maybeEmitNoteForObjCSelf(PathSensitiveBugReport &R,
550
                                                  const ObjCMethodCall &Call,
551
                                                  const ExplodedNode *N) final;
552
553
  PathDiagnosticPieceRef maybeEmitNoteForCXXThis(PathSensitiveBugReport &R,
554
                                                 const CXXConstructorCall &Call,
555
                                                 const ExplodedNode *N) final;
556
557
  PathDiagnosticPieceRef
558
  maybeEmitNoteForParameters(PathSensitiveBugReport &R, const CallEvent &Call,
559
                             const ExplodedNode *N) final;
560
561
  /// Consume the information on the no-store stack frame in order to
562
  /// either emit a note or suppress the report enirely.
563
  /// \return Diagnostics piece for region not modified in the current function,
564
  /// if it decides to emit one.
565
  PathDiagnosticPieceRef
566
  maybeEmitNote(PathSensitiveBugReport &R, const CallEvent &Call,
567
                const ExplodedNode *N, const RegionVector &FieldChain,
568
                const MemRegion *MatchedRegion, StringRef FirstElement,
569
                bool FirstIsReferenceType, unsigned IndirectionLevel);
570
571
  bool prettyPrintRegionName(const RegionVector &FieldChain,
572
                             const MemRegion *MatchedRegion,
573
                             StringRef FirstElement, bool FirstIsReferenceType,
574
                             unsigned IndirectionLevel,
575
                             llvm::raw_svector_ostream &os);
576
577
  StringRef prettyPrintFirstElement(StringRef FirstElement,
578
                                    bool MoreItemsExpected,
579
                                    int IndirectionLevel,
580
                                    llvm::raw_svector_ostream &os);
581
};
582
} // namespace
583
584
/// \return Whether the method declaration \p Parent
585
/// syntactically has a binary operation writing into the ivar \p Ivar.
586
static bool potentiallyWritesIntoIvar(const Decl *Parent,
587
9
                                      const ObjCIvarDecl *Ivar) {
588
9
  using namespace ast_matchers;
589
9
  const char *IvarBind = "Ivar";
590
9
  if (!Parent || !Parent->hasBody())
591
0
    return false;
592
9
  StatementMatcher WriteIntoIvarM = binaryOperator(
593
9
      hasOperatorName("="),
594
9
      hasLHS(ignoringParenImpCasts(
595
9
          objcIvarRefExpr(hasDeclaration(equalsNode(Ivar))).bind(IvarBind))));
596
9
  StatementMatcher ParentM = stmt(hasDescendant(WriteIntoIvarM));
597
9
  auto Matches = match(ParentM, *Parent->getBody(), Parent->getASTContext());
598
9
  for (BoundNodes &Match : Matches) {
599
2
    auto IvarRef = Match.getNodeAs<ObjCIvarRefExpr>(IvarBind);
600
2
    if (IvarRef->isFreeIvar())
601
1
      return true;
602
603
1
    const Expr *Base = IvarRef->getBase();
604
1
    if (const auto *ICE = dyn_cast<ImplicitCastExpr>(Base))
605
1
      Base = ICE->getSubExpr();
606
607
1
    if (const auto *DRE = dyn_cast<DeclRefExpr>(Base))
608
1
      if (const auto *ID = dyn_cast<ImplicitParamDecl>(DRE->getDecl()))
609
1
        if (ID->getParameterKind() == ImplicitParamDecl::ObjCSelf)
610
1
          return true;
611
612
0
    return false;
613
1
  }
614
7
  return false;
615
9
}
616
617
/// Attempts to find the region of interest in a given CXX decl,
618
/// by either following the base classes or fields.
619
/// Dereferences fields up to a given recursion limit.
620
/// Note that \p Vec is passed by value, leading to quadratic copying cost,
621
/// but it's OK in practice since its length is limited to DEREFERENCE_LIMIT.
622
/// \return A chain fields leading to the region of interest or std::nullopt.
623
const std::optional<NoStoreFuncVisitor::RegionVector>
624
NoStoreFuncVisitor::findRegionOfInterestInRecord(
625
    const RecordDecl *RD, ProgramStateRef State, const MemRegion *R,
626
    const NoStoreFuncVisitor::RegionVector &Vec /* = {} */,
627
62
    int depth /* = 0 */) {
628
629
62
  if (depth == DEREFERENCE_LIMIT) // Limit the recursion depth.
630
5
    return std::nullopt;
631
632
57
  if (const auto *RDX = dyn_cast<CXXRecordDecl>(RD))
633
56
    if (!RDX->hasDefinition())
634
0
      return std::nullopt;
635
636
  // Recursively examine the base classes.
637
  // Note that following base classes does not increase the recursion depth.
638
57
  if (const auto *RDX = dyn_cast<CXXRecordDecl>(RD))
639
56
    for (const auto &II : RDX->bases())
640
1
      if (const RecordDecl *RRD = II.getType()->getAsRecordDecl())
641
1
        if (std::optional<RegionVector> Out =
642
1
                findRegionOfInterestInRecord(RRD, State, R, Vec, depth))
643
1
          return Out;
644
645
60
  
for (const FieldDecl *I : RD->fields())56
{
646
60
    QualType FT = I->getType();
647
60
    const FieldRegion *FR = MmrMgr.getFieldRegion(I, cast<SubRegion>(R));
648
60
    const SVal V = State->getSVal(FR);
649
60
    const MemRegion *VR = V.getAsRegion();
650
651
60
    RegionVector VecF = Vec;
652
60
    VecF.push_back(FR);
653
654
60
    if (RegionOfInterest == VR)
655
10
      return VecF;
656
657
50
    if (const RecordDecl *RRD = FT->getAsRecordDecl())
658
13
      if (auto Out =
659
13
              findRegionOfInterestInRecord(RRD, State, FR, VecF, depth + 1))
660
1
        return Out;
661
662
49
    QualType PT = FT->getPointeeType();
663
49
    if (PT.isNull() || 
PT->isVoidType()8
||
!VR8
)
664
41
      continue;
665
666
8
    if (const RecordDecl *RRD = PT->getAsRecordDecl())
667
4
      if (std::optional<RegionVector> Out =
668
4
              findRegionOfInterestInRecord(RRD, State, VR, VecF, depth + 1))
669
3
        return Out;
670
8
  }
671
672
42
  return std::nullopt;
673
56
}
674
675
PathDiagnosticPieceRef
676
NoStoreFuncVisitor::maybeEmitNoteForObjCSelf(PathSensitiveBugReport &R,
677
                                             const ObjCMethodCall &Call,
678
118
                                             const ExplodedNode *N) {
679
118
  if (const auto *IvarR = dyn_cast<ObjCIvarRegion>(RegionOfInterest)) {
680
10
    const MemRegion *SelfRegion = Call.getReceiverSVal().getAsRegion();
681
10
    if (RegionOfInterest->isSubRegionOf(SelfRegion) &&
682
10
        potentiallyWritesIntoIvar(Call.getRuntimeDefinition().getDecl(),
683
9
                                  IvarR->getDecl()))
684
2
      return maybeEmitNote(R, Call, N, {}, SelfRegion, "self",
685
2
                           /*FirstIsReferenceType=*/false, 1);
686
10
  }
687
116
  return nullptr;
688
118
}
689
690
PathDiagnosticPieceRef
691
NoStoreFuncVisitor::maybeEmitNoteForCXXThis(PathSensitiveBugReport &R,
692
                                            const CXXConstructorCall &Call,
693
230
                                            const ExplodedNode *N) {
694
230
  const MemRegion *ThisR = Call.getCXXThisVal().getAsRegion();
695
230
  if (RegionOfInterest->isSubRegionOf(ThisR) && 
!Call.getDecl()->isImplicit()70
)
696
28
    return maybeEmitNote(R, Call, N, {}, ThisR, "this",
697
28
                         /*FirstIsReferenceType=*/false, 1);
698
699
  // Do not generate diagnostics for not modified parameters in
700
  // constructors.
701
202
  return nullptr;
702
230
}
703
704
/// \return whether \p Ty points to a const type, or is a const reference.
705
43
static bool isPointerToConst(QualType Ty) {
706
43
  return !Ty->getPointeeType().isNull() &&
707
43
         Ty->getPointeeType().getCanonicalType().isConstQualified();
708
43
}
709
710
PathDiagnosticPieceRef NoStoreFuncVisitor::maybeEmitNoteForParameters(
711
816
    PathSensitiveBugReport &R, const CallEvent &Call, const ExplodedNode *N) {
712
816
  ArrayRef<ParmVarDecl *> Parameters = Call.parameters();
713
1.23k
  for (unsigned I = 0; I < Call.getNumArgs() && 
I < Parameters.size()469
;
++I415
) {
714
466
    const ParmVarDecl *PVD = Parameters[I];
715
466
    SVal V = Call.getArgSVal(I);
716
466
    bool ParamIsReferenceType = PVD->getType()->isReferenceType();
717
466
    std::string ParamName = PVD->getNameAsString();
718
719
466
    unsigned IndirectionLevel = 1;
720
466
    QualType T = PVD->getType();
721
577
    while (const MemRegion *MR = V.getAsRegion()) {
722
231
      if (RegionOfInterest->isSubRegionOf(MR) && 
!isPointerToConst(T)43
)
723
41
        return maybeEmitNote(R, Call, N, {}, MR, ParamName,
724
41
                             ParamIsReferenceType, IndirectionLevel);
725
726
190
      QualType PT = T->getPointeeType();
727
190
      if (PT.isNull() || 
PT->isVoidType()184
)
728
69
        break;
729
730
121
      ProgramStateRef State = N->getState();
731
732
121
      if (const RecordDecl *RD = PT->getAsRecordDecl())
733
44
        if (std::optional<RegionVector> P =
734
44
                findRegionOfInterestInRecord(RD, State, MR))
735
10
          return maybeEmitNote(R, Call, N, *P, RegionOfInterest, ParamName,
736
10
                               ParamIsReferenceType, IndirectionLevel);
737
738
111
      V = State->getSVal(MR, PT);
739
111
      T = PT;
740
111
      IndirectionLevel++;
741
111
    }
742
466
  }
743
744
765
  return nullptr;
745
816
}
746
747
bool NoStoreFuncVisitor::wasModifiedBeforeCallExit(
748
22.5k
    const ExplodedNode *CurrN, const ExplodedNode *CallExitBeginN) {
749
22.5k
  return ::wasRegionOfInterestModifiedAt(
750
22.5k
      RegionOfInterest, CurrN,
751
22.5k
      CallExitBeginN->getState()->getSVal(RegionOfInterest));
752
22.5k
}
753
754
static llvm::StringLiteral WillBeUsedForACondition =
755
    ", which participates in a condition later";
756
757
PathDiagnosticPieceRef NoStoreFuncVisitor::maybeEmitNote(
758
    PathSensitiveBugReport &R, const CallEvent &Call, const ExplodedNode *N,
759
    const RegionVector &FieldChain, const MemRegion *MatchedRegion,
760
    StringRef FirstElement, bool FirstIsReferenceType,
761
81
    unsigned IndirectionLevel) {
762
763
81
  PathDiagnosticLocation L =
764
81
      PathDiagnosticLocation::create(N->getLocation(), SM);
765
766
  // For now this shouldn't trigger, but once it does (as we add more
767
  // functions to the body farm), we'll need to decide if these reports
768
  // are worth suppressing as well.
769
81
  if (!L.hasValidLocation())
770
0
    return nullptr;
771
772
81
  SmallString<256> sbuf;
773
81
  llvm::raw_svector_ostream os(sbuf);
774
81
  os << "Returning without writing to '";
775
776
  // Do not generate the note if failed to pretty-print.
777
81
  if (!prettyPrintRegionName(FieldChain, MatchedRegion, FirstElement,
778
81
                             FirstIsReferenceType, IndirectionLevel, os))
779
6
    return nullptr;
780
781
75
  os << "'";
782
75
  if (TKind == bugreporter::TrackingKind::Condition)
783
0
    os << WillBeUsedForACondition;
784
75
  return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
785
81
}
786
787
bool NoStoreFuncVisitor::prettyPrintRegionName(const RegionVector &FieldChain,
788
                                               const MemRegion *MatchedRegion,
789
                                               StringRef FirstElement,
790
                                               bool FirstIsReferenceType,
791
                                               unsigned IndirectionLevel,
792
81
                                               llvm::raw_svector_ostream &os) {
793
794
81
  if (FirstIsReferenceType)
795
25
    IndirectionLevel--;
796
797
81
  RegionVector RegionSequence;
798
799
  // Add the regions in the reverse order, then reverse the resulting array.
800
81
  assert(RegionOfInterest->isSubRegionOf(MatchedRegion));
801
81
  const MemRegion *R = RegionOfInterest;
802
150
  while (R != MatchedRegion) {
803
69
    RegionSequence.push_back(R);
804
69
    R = cast<SubRegion>(R)->getSuperRegion();
805
69
  }
806
81
  std::reverse(RegionSequence.begin(), RegionSequence.end());
807
81
  RegionSequence.append(FieldChain.begin(), FieldChain.end());
808
809
81
  StringRef Sep;
810
81
  for (const MemRegion *R : RegionSequence) {
811
812
    // Just keep going up to the base region.
813
    // Element regions may appear due to casts.
814
77
    if (isa<CXXBaseObjectRegion, CXXTempObjectRegion>(R))
815
5
      continue;
816
817
72
    if (Sep.empty())
818
63
      Sep = prettyPrintFirstElement(FirstElement,
819
63
                                    /*MoreItemsExpected=*/true,
820
63
                                    IndirectionLevel, os);
821
822
72
    os << Sep;
823
824
    // Can only reasonably pretty-print DeclRegions.
825
72
    if (!isa<DeclRegion>(R))
826
6
      return false;
827
828
66
    const auto *DR = cast<DeclRegion>(R);
829
66
    Sep = DR->getValueType()->isAnyPointerType() ? 
"->"7
:
"."59
;
830
66
    DR->getDecl()->getDeclName().print(os, PP);
831
66
  }
832
833
75
  if (Sep.empty())
834
18
    prettyPrintFirstElement(FirstElement,
835
18
                            /*MoreItemsExpected=*/false, IndirectionLevel, os);
836
75
  return true;
837
81
}
838
839
StringRef NoStoreFuncVisitor::prettyPrintFirstElement(
840
    StringRef FirstElement, bool MoreItemsExpected, int IndirectionLevel,
841
81
    llvm::raw_svector_ostream &os) {
842
81
  StringRef Out = ".";
843
844
81
  if (IndirectionLevel > 0 && 
MoreItemsExpected57
) {
845
42
    IndirectionLevel--;
846
42
    Out = "->";
847
42
  }
848
849
81
  if (IndirectionLevel > 0 && 
MoreItemsExpected16
)
850
1
    os << "(";
851
852
98
  for (int i = 0; i < IndirectionLevel; 
i++17
)
853
17
    os << "*";
854
81
  os << FirstElement;
855
856
81
  if (IndirectionLevel > 0 && 
MoreItemsExpected16
)
857
1
    os << ")";
858
859
81
  return Out;
860
81
}
861
862
//===----------------------------------------------------------------------===//
863
// Implementation of MacroNullReturnSuppressionVisitor.
864
//===----------------------------------------------------------------------===//
865
866
namespace {
867
868
/// Suppress null-pointer-dereference bugs where dereferenced null was returned
869
/// the macro.
870
class MacroNullReturnSuppressionVisitor final : public BugReporterVisitor {
871
  const SubRegion *RegionOfInterest;
872
  const SVal ValueAtDereference;
873
874
  // Do not invalidate the reports where the value was modified
875
  // after it got assigned to from the macro.
876
  bool WasModified = false;
877
878
public:
879
  MacroNullReturnSuppressionVisitor(const SubRegion *R, const SVal V)
880
1.35k
      : RegionOfInterest(R), ValueAtDereference(V) {}
881
882
  PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
883
                                   BugReporterContext &BRC,
884
47.7k
                                   PathSensitiveBugReport &BR) override {
885
47.7k
    if (WasModified)
886
28.3k
      return nullptr;
887
888
19.3k
    auto BugPoint = BR.getErrorNode()->getLocation().getAs<StmtPoint>();
889
19.3k
    if (!BugPoint)
890
152
      return nullptr;
891
892
19.2k
    const SourceManager &SMgr = BRC.getSourceManager();
893
19.2k
    if (auto Loc = matchAssignment(N)) {
894
1.43k
      if (isFunctionMacroExpansion(*Loc, SMgr)) {
895
8
        std::string MacroName = std::string(getMacroName(*Loc, BRC));
896
8
        SourceLocation BugLoc = BugPoint->getStmt()->getBeginLoc();
897
8
        if (!BugLoc.isMacroID() || 
getMacroName(BugLoc, BRC) != MacroName3
)
898
5
          BR.markInvalid(getTag(), MacroName.c_str());
899
8
      }
900
1.43k
    }
901
902
19.2k
    if (wasRegionOfInterestModifiedAt(RegionOfInterest, N, ValueAtDereference))
903
1.00k
      WasModified = true;
904
905
19.2k
    return nullptr;
906
19.3k
  }
907
908
  static void addMacroVisitorIfNecessary(
909
        const ExplodedNode *N, const MemRegion *R,
910
        bool EnableNullFPSuppression, PathSensitiveBugReport &BR,
911
3.08k
        const SVal V) {
912
3.08k
    AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
913
3.08k
    if (EnableNullFPSuppression && 
Options.ShouldSuppressNullReturnPaths2.47k
&&
914
3.08k
        
isa<Loc>(V)2.35k
)
915
1.35k
      BR.addVisitor<MacroNullReturnSuppressionVisitor>(R->getAs<SubRegion>(),
916
1.35k
                                                       V);
917
3.08k
  }
918
919
1.35k
  void* getTag() const {
920
1.35k
    static int Tag = 0;
921
1.35k
    return static_cast<void *>(&Tag);
922
1.35k
  }
923
924
1.35k
  void Profile(llvm::FoldingSetNodeID &ID) const override {
925
1.35k
    ID.AddPointer(getTag());
926
1.35k
  }
927
928
private:
929
  /// \return Source location of right hand side of an assignment
930
  /// into \c RegionOfInterest, empty optional if none found.
931
19.2k
  std::optional<SourceLocation> matchAssignment(const ExplodedNode *N) {
932
19.2k
    const Stmt *S = N->getStmtForDiagnostics();
933
19.2k
    ProgramStateRef State = N->getState();
934
19.2k
    auto *LCtx = N->getLocationContext();
935
19.2k
    if (!S)
936
1.28k
      return std::nullopt;
937
938
17.9k
    if (const auto *DS = dyn_cast<DeclStmt>(S)) {
939
1.83k
      if (const auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl()))
940
1.83k
        if (const Expr *RHS = VD->getInit())
941
1.77k
          if (RegionOfInterest->isSubRegionOf(
942
1.77k
                  State->getLValue(VD, LCtx).getAsRegion()))
943
1.35k
            return RHS->getBeginLoc();
944
16.1k
    } else if (const auto *BO = dyn_cast<BinaryOperator>(S)) {
945
1.17k
      const MemRegion *R = N->getSVal(BO->getLHS()).getAsRegion();
946
1.17k
      const Expr *RHS = BO->getRHS();
947
1.17k
      if (BO->isAssignmentOp() && 
RegionOfInterest->isSubRegionOf(R)805
) {
948
85
        return RHS->getBeginLoc();
949
85
      }
950
1.17k
    }
951
16.5k
    return std::nullopt;
952
17.9k
  }
953
};
954
955
} // end of anonymous namespace
956
957
namespace {
958
959
/// Emits an extra note at the return statement of an interesting stack frame.
960
///
961
/// The returned value is marked as an interesting value, and if it's null,
962
/// adds a visitor to track where it became null.
963
///
964
/// This visitor is intended to be used when another visitor discovers that an
965
/// interesting value comes from an inlined function call.
966
class ReturnVisitor : public TrackingBugReporterVisitor {
967
  const StackFrameContext *CalleeSFC;
968
  enum {
969
    Initial,
970
    MaybeUnsuppress,
971
    Satisfied
972
  } Mode = Initial;
973
974
  bool EnableNullFPSuppression;
975
  bool ShouldInvalidate = true;
976
  AnalyzerOptions& Options;
977
  bugreporter::TrackingKind TKind;
978
979
public:
980
  ReturnVisitor(TrackerRef ParentTracker, const StackFrameContext *Frame,
981
                bool Suppressed, AnalyzerOptions &Options,
982
                bugreporter::TrackingKind TKind)
983
      : TrackingBugReporterVisitor(ParentTracker), CalleeSFC(Frame),
984
321
        EnableNullFPSuppression(Suppressed), Options(Options), TKind(TKind) {}
985
986
428
  static void *getTag() {
987
428
    static int Tag = 0;
988
428
    return static_cast<void *>(&Tag);
989
428
  }
990
991
321
  void Profile(llvm::FoldingSetNodeID &ID) const override {
992
321
    ID.AddPointer(ReturnVisitor::getTag());
993
321
    ID.AddPointer(CalleeSFC);
994
321
    ID.AddBoolean(EnableNullFPSuppression);
995
321
  }
996
997
  PathDiagnosticPieceRef visitNodeInitial(const ExplodedNode *N,
998
                                          BugReporterContext &BRC,
999
2.61k
                                          PathSensitiveBugReport &BR) {
1000
    // Only print a message at the interesting return statement.
1001
2.61k
    if (N->getLocationContext() != CalleeSFC)
1002
1.74k
      return nullptr;
1003
1004
863
    std::optional<StmtPoint> SP = N->getLocationAs<StmtPoint>();
1005
863
    if (!SP)
1006
96
      return nullptr;
1007
1008
767
    const auto *Ret = dyn_cast<ReturnStmt>(SP->getStmt());
1009
767
    if (!Ret)
1010
424
      return nullptr;
1011
1012
    // Okay, we're at the right return statement, but do we have the return
1013
    // value available?
1014
343
    ProgramStateRef State = N->getState();
1015
343
    SVal V = State->getSVal(Ret, CalleeSFC);
1016
343
    if (V.isUnknownOrUndef())
1017
43
      return nullptr;
1018
1019
    // Don't print any more notes after this one.
1020
300
    Mode = Satisfied;
1021
1022
300
    const Expr *RetE = Ret->getRetValue();
1023
300
    assert(RetE && "Tracking a return value for a void function");
1024
1025
    // Handle cases where a reference is returned and then immediately used.
1026
300
    std::optional<Loc> LValue;
1027
300
    if (RetE->isGLValue()) {
1028
24
      if ((LValue = V.getAs<Loc>())) {
1029
24
        SVal RValue = State->getRawSVal(*LValue, RetE->getType());
1030
24
        if (isa<DefinedSVal>(RValue))
1031
22
          V = RValue;
1032
24
      }
1033
24
    }
1034
1035
    // Ignore aggregate rvalues.
1036
300
    if (isa<nonloc::LazyCompoundVal, nonloc::CompoundVal>(V))
1037
10
      return nullptr;
1038
1039
290
    RetE = RetE->IgnoreParenCasts();
1040
1041
    // Let's track the return value.
1042
290
    getParentTracker().track(RetE, N, {TKind, EnableNullFPSuppression});
1043
1044
    // Build an appropriate message based on the return value.
1045
290
    SmallString<64> Msg;
1046
290
    llvm::raw_svector_ostream Out(Msg);
1047
1048
290
    bool WouldEventBeMeaningless = false;
1049
1050
290
    if (State->isNull(V).isConstrainedTrue()) {
1051
254
      if (isa<Loc>(V)) {
1052
1053
        // If we have counter-suppression enabled, make sure we keep visiting
1054
        // future nodes. We want to emit a path note as well, in case
1055
        // the report is resurrected as valid later on.
1056
209
        if (EnableNullFPSuppression &&
1057
209
            
Options.ShouldAvoidSuppressingNullArgumentPaths112
)
1058
31
          Mode = MaybeUnsuppress;
1059
1060
209
        if (RetE->getType()->isObjCObjectPointerType()) {
1061
5
          Out << "Returning nil";
1062
204
        } else {
1063
204
          Out << "Returning null pointer";
1064
204
        }
1065
209
      } else {
1066
45
        Out << "Returning zero";
1067
45
      }
1068
1069
254
    } else {
1070
36
      if (auto CI = V.getAs<nonloc::ConcreteInt>()) {
1071
5
        Out << "Returning the value " << CI->getValue();
1072
31
      } else {
1073
        // There is nothing interesting about returning a value, when it is
1074
        // plain value without any constraints, and the function is guaranteed
1075
        // to return that every time. We could use CFG::isLinear() here, but
1076
        // constexpr branches are obvious to the compiler, not necesserily to
1077
        // the programmer.
1078
31
        if (N->getCFG().size() == 3)
1079
29
          WouldEventBeMeaningless = true;
1080
1081
31
        Out << (isa<Loc>(V) ? 
"Returning pointer"29
:
"Returning value"2
);
1082
31
      }
1083
36
    }
1084
1085
290
    if (LValue) {
1086
16
      if (const MemRegion *MR = LValue->getAsRegion()) {
1087
16
        if (MR->canPrintPretty()) {
1088
10
          Out << " (reference to ";
1089
10
          MR->printPretty(Out);
1090
10
          Out << ")";
1091
10
        }
1092
16
      }
1093
274
    } else {
1094
      // FIXME: We should have a more generalized location printing mechanism.
1095
274
      if (const auto *DR = dyn_cast<DeclRefExpr>(RetE))
1096
30
        if (const auto *DD = dyn_cast<DeclaratorDecl>(DR->getDecl()))
1097
30
          Out << " (loaded from '" << *DD << "')";
1098
274
    }
1099
1100
290
    PathDiagnosticLocation L(Ret, BRC.getSourceManager(), CalleeSFC);
1101
290
    if (!L.isValid() || !L.asLocation().isValid())
1102
23
      return nullptr;
1103
1104
267
    if (TKind == bugreporter::TrackingKind::Condition)
1105
18
      Out << WillBeUsedForACondition;
1106
1107
267
    auto EventPiece = std::make_shared<PathDiagnosticEventPiece>(L, Out.str());
1108
1109
    // If we determined that the note is meaningless, make it prunable, and
1110
    // don't mark the stackframe interesting.
1111
267
    if (WouldEventBeMeaningless)
1112
15
      EventPiece->setPrunable(true);
1113
252
    else
1114
252
      BR.markInteresting(CalleeSFC);
1115
1116
267
    return EventPiece;
1117
290
  }
1118
1119
  PathDiagnosticPieceRef visitNodeMaybeUnsuppress(const ExplodedNode *N,
1120
                                                  BugReporterContext &BRC,
1121
465
                                                  PathSensitiveBugReport &BR) {
1122
465
    assert(Options.ShouldAvoidSuppressingNullArgumentPaths);
1123
1124
    // Are we at the entry node for this call?
1125
465
    std::optional<CallEnter> CE = N->getLocationAs<CallEnter>();
1126
465
    if (!CE)
1127
433
      return nullptr;
1128
1129
32
    if (CE->getCalleeContext() != CalleeSFC)
1130
1
      return nullptr;
1131
1132
31
    Mode = Satisfied;
1133
1134
    // Don't automatically suppress a report if one of the arguments is
1135
    // known to be a null pointer. Instead, start tracking /that/ null
1136
    // value back to its origin.
1137
31
    ProgramStateManager &StateMgr = BRC.getStateManager();
1138
31
    CallEventManager &CallMgr = StateMgr.getCallEventManager();
1139
1140
31
    ProgramStateRef State = N->getState();
1141
31
    CallEventRef<> Call = CallMgr.getCaller(CalleeSFC, State);
1142
43
    for (unsigned I = 0, E = Call->getNumArgs(); I != E; 
++I12
) {
1143
12
      std::optional<Loc> ArgV = Call->getArgSVal(I).getAs<Loc>();
1144
12
      if (!ArgV)
1145
2
        continue;
1146
1147
10
      const Expr *ArgE = Call->getArgExpr(I);
1148
10
      if (!ArgE)
1149
0
        continue;
1150
1151
      // Is it possible for this argument to be non-null?
1152
10
      if (!State->isNull(*ArgV).isConstrainedTrue())
1153
6
        continue;
1154
1155
4
      if (getParentTracker()
1156
4
              .track(ArgE, N, {TKind, EnableNullFPSuppression})
1157
4
              .FoundSomethingToTrack)
1158
4
        ShouldInvalidate = false;
1159
1160
      // If we /can't/ track the null pointer, we should err on the side of
1161
      // false negatives, and continue towards marking this report invalid.
1162
      // (We will still look at the other arguments, though.)
1163
4
    }
1164
1165
31
    return nullptr;
1166
32
  }
1167
1168
  PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
1169
                                   BugReporterContext &BRC,
1170
22.6k
                                   PathSensitiveBugReport &BR) override {
1171
22.6k
    switch (Mode) {
1172
2.61k
    case Initial:
1173
2.61k
      return visitNodeInitial(N, BRC, BR);
1174
465
    case MaybeUnsuppress:
1175
465
      return visitNodeMaybeUnsuppress(N, BRC, BR);
1176
19.6k
    case Satisfied:
1177
19.6k
      return nullptr;
1178
22.6k
    }
1179
1180
0
    llvm_unreachable("Invalid visit mode!");
1181
0
  }
1182
1183
  void finalizeVisitor(BugReporterContext &, const ExplodedNode *,
1184
320
                       PathSensitiveBugReport &BR) override {
1185
320
    if (EnableNullFPSuppression && 
ShouldInvalidate111
)
1186
107
      BR.markInvalid(ReturnVisitor::getTag(), CalleeSFC);
1187
320
  }
1188
};
1189
1190
//===----------------------------------------------------------------------===//
1191
//                               StoreSiteFinder
1192
//===----------------------------------------------------------------------===//
1193
1194
/// Finds last store into the given region,
1195
/// which is different from a given symbolic value.
1196
class StoreSiteFinder final : public TrackingBugReporterVisitor {
1197
  const MemRegion *R;
1198
  SVal V;
1199
  bool Satisfied = false;
1200
1201
  TrackingOptions Options;
1202
  const StackFrameContext *OriginSFC;
1203
1204
public:
1205
  /// \param V We're searching for the store where \c R received this value.
1206
  /// \param R The region we're tracking.
1207
  /// \param Options Tracking behavior options.
1208
  /// \param OriginSFC Only adds notes when the last store happened in a
1209
  ///        different stackframe to this one. Disregarded if the tracking kind
1210
  ///        is thorough.
1211
  ///        This is useful, because for non-tracked regions, notes about
1212
  ///        changes to its value in a nested stackframe could be pruned, and
1213
  ///        this visitor can prevent that without polluting the bugpath too
1214
  ///        much.
1215
  StoreSiteFinder(bugreporter::TrackerRef ParentTracker, KnownSVal V,
1216
                  const MemRegion *R, TrackingOptions Options,
1217
                  const StackFrameContext *OriginSFC = nullptr)
1218
      : TrackingBugReporterVisitor(ParentTracker), R(R), V(V), Options(Options),
1219
3.34k
        OriginSFC(OriginSFC) {
1220
3.34k
    assert(R);
1221
3.34k
  }
1222
1223
  void Profile(llvm::FoldingSetNodeID &ID) const override;
1224
1225
  PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
1226
                                   BugReporterContext &BRC,
1227
                                   PathSensitiveBugReport &BR) override;
1228
};
1229
} // namespace
1230
1231
3.34k
void StoreSiteFinder::Profile(llvm::FoldingSetNodeID &ID) const {
1232
3.34k
  static int tag = 0;
1233
3.34k
  ID.AddPointer(&tag);
1234
3.34k
  ID.AddPointer(R);
1235
3.34k
  ID.Add(V);
1236
3.34k
  ID.AddInteger(static_cast<int>(Options.Kind));
1237
3.34k
  ID.AddBoolean(Options.EnableNullFPSuppression);
1238
3.34k
}
1239
1240
/// Returns true if \p N represents the DeclStmt declaring and initializing
1241
/// \p VR.
1242
58.6k
static bool isInitializationOfVar(const ExplodedNode *N, const VarRegion *VR) {
1243
58.6k
  std::optional<PostStmt> P = N->getLocationAs<PostStmt>();
1244
58.6k
  if (!P)
1245
19.8k
    return false;
1246
1247
38.7k
  const DeclStmt *DS = P->getStmtAs<DeclStmt>();
1248
38.7k
  if (!DS)
1249
36.2k
    return false;
1250
1251
2.55k
  if (DS->getSingleDecl() != VR->getDecl())
1252
950
    return false;
1253
1254
1.60k
  const MemSpaceRegion *VarSpace = VR->getMemorySpace();
1255
1.60k
  const auto *FrameSpace = dyn_cast<StackSpaceRegion>(VarSpace);
1256
1.60k
  if (!FrameSpace) {
1257
    // If we ever directly evaluate global DeclStmts, this assertion will be
1258
    // invalid, but this still seems preferable to silently accepting an
1259
    // initialization that may be for a path-sensitive variable.
1260
5
    assert(VR->getDecl()->isStaticLocal() && "non-static stackless VarRegion");
1261
5
    return true;
1262
5
  }
1263
1264
1.59k
  assert(VR->getDecl()->hasLocalStorage());
1265
1.59k
  const LocationContext *LCtx = N->getLocationContext();
1266
1.59k
  return FrameSpace->getStackFrame() == LCtx->getStackFrame();
1267
1.59k
}
1268
1269
932
static bool isObjCPointer(const MemRegion *R) {
1270
932
  if (R->isBoundable())
1271
932
    if (const auto *TR = dyn_cast<TypedValueRegion>(R))
1272
915
      return TR->getValueType()->isObjCObjectPointerType();
1273
1274
17
  return false;
1275
932
}
1276
1277
89
static bool isObjCPointer(const ValueDecl *D) {
1278
89
  return D->getType()->isObjCObjectPointerType();
1279
89
}
1280
1281
/// Show diagnostics for initializing or declaring a region \p R with a bad value.
1282
1.55k
static void showBRDiagnostics(llvm::raw_svector_ostream &OS, StoreInfo SI) {
1283
1.55k
  const bool HasPrefix = SI.Dest->canPrintPretty();
1284
1285
1.55k
  if (HasPrefix) {
1286
1.55k
    SI.Dest->printPretty(OS);
1287
1.55k
    OS << " ";
1288
1.55k
  }
1289
1290
1.55k
  const char *Action = nullptr;
1291
1292
1.55k
  switch (SI.StoreKind) {
1293
1.55k
  case StoreInfo::Initialization:
1294
1.55k
    Action = HasPrefix ? 
"initialized to "1.55k
:
"Initializing to "3
;
1295
1.55k
    break;
1296
4
  case StoreInfo::BlockCapture:
1297
4
    Action = HasPrefix ? "captured by block as " : 
"Captured by block as "0
;
1298
4
    break;
1299
0
  default:
1300
0
    llvm_unreachable("Unexpected store kind");
1301
1.55k
  }
1302
1303
1.55k
  if (isa<loc::ConcreteInt>(SI.Value)) {
1304
658
    OS << Action << (isObjCPointer(SI.Dest) ? 
"nil"74
:
"a null pointer value"584
);
1305
1306
900
  } else if (auto CVal = SI.Value.getAs<nonloc::ConcreteInt>()) {
1307
137
    OS << Action << CVal->getValue();
1308
1309
763
  } else if (SI.Origin && 
SI.Origin->canPrintPretty()15
) {
1310
15
    OS << Action << "the value of ";
1311
15
    SI.Origin->printPretty(OS);
1312
1313
748
  } else if (SI.StoreKind == StoreInfo::Initialization) {
1314
    // We don't need to check here, all these conditions were
1315
    // checked by StoreSiteFinder, when it figured out that it is
1316
    // initialization.
1317
748
    const auto *DS =
1318
748
        cast<DeclStmt>(SI.StoreSite->getLocationAs<PostStmt>()->getStmt());
1319
1320
748
    if (SI.Value.isUndef()) {
1321
461
      if (isa<VarRegion>(SI.Dest)) {
1322
461
        const auto *VD = cast<VarDecl>(DS->getSingleDecl());
1323
1324
461
        if (VD->getInit()) {
1325
0
          OS << (HasPrefix ? "initialized" : "Initializing")
1326
0
             << " to a garbage value";
1327
461
        } else {
1328
461
          OS << (HasPrefix ? "declared" : 
"Declaring"0
)
1329
461
             << " without an initial value";
1330
461
        }
1331
461
      }
1332
461
    } else {
1333
287
      OS << (HasPrefix ? "initialized" : 
"Initialized"0
) << " here";
1334
287
    }
1335
748
  }
1336
1.55k
}
1337
1338
/// Display diagnostics for passing bad region as a parameter.
1339
static void showBRParamDiagnostics(llvm::raw_svector_ostream &OS,
1340
126
                                   StoreInfo SI) {
1341
126
  const auto *VR = cast<VarRegion>(SI.Dest);
1342
126
  const auto *D = VR->getDecl();
1343
1344
126
  OS << "Passing ";
1345
1346
126
  if (isa<loc::ConcreteInt>(SI.Value)) {
1347
89
    OS << (isObjCPointer(D) ? 
"nil object reference"4
:
"null pointer value"85
);
1348
1349
89
  } else 
if (37
SI.Value.isUndef()37
) {
1350
0
    OS << "uninitialized value";
1351
1352
37
  } else if (auto CI = SI.Value.getAs<nonloc::ConcreteInt>()) {
1353
17
    OS << "the value " << CI->getValue();
1354
1355
20
  } else if (SI.Origin && 
SI.Origin->canPrintPretty()1
) {
1356
1
    SI.Origin->printPretty(OS);
1357
1358
19
  } else {
1359
19
    OS << "value";
1360
19
  }
1361
1362
126
  if (const auto *Param = dyn_cast<ParmVarDecl>(VR->getDecl())) {
1363
    // Printed parameter indexes are 1-based, not 0-based.
1364
125
    unsigned Idx = Param->getFunctionScopeIndex() + 1;
1365
125
    OS << " via " << Idx << llvm::getOrdinalSuffix(Idx) << " parameter";
1366
125
    if (VR->canPrintPretty()) {
1367
125
      OS << " ";
1368
125
      VR->printPretty(OS);
1369
125
    }
1370
125
  } else 
if (const auto *1
ImplParam1
= dyn_cast<ImplicitParamDecl>(D)) {
1371
1
    if (ImplParam->getParameterKind() ==
1372
1
        ImplicitParamDecl::ImplicitParamKind::ObjCSelf) {
1373
1
      OS << " via implicit parameter 'self'";
1374
1
    }
1375
1
  }
1376
126
}
1377
1378
/// Show default diagnostics for storing bad region.
1379
static void showBRDefaultDiagnostics(llvm::raw_svector_ostream &OS,
1380
452
                                     StoreInfo SI) {
1381
452
  const bool HasSuffix = SI.Dest->canPrintPretty();
1382
1383
452
  if (isa<loc::ConcreteInt>(SI.Value)) {
1384
274
    OS << (isObjCPointer(SI.Dest) ? 
"nil object reference stored"21
1385
274
                                  : 
(253
HasSuffix253
?
"Null pointer value stored"219
1386
253
                                               : 
"Storing null pointer value"34
));
1387
1388
274
  } else 
if (178
SI.Value.isUndef()178
) {
1389
23
    OS << (HasSuffix ? 
"Uninitialized value stored"7
1390
23
                     : 
"Storing uninitialized value"16
);
1391
1392
155
  } else if (auto CV = SI.Value.getAs<nonloc::ConcreteInt>()) {
1393
60
    if (HasSuffix)
1394
48
      OS << "The value " << CV->getValue() << " is assigned";
1395
12
    else
1396
12
      OS << "Assigning " << CV->getValue();
1397
1398
95
  } else if (SI.Origin && 
SI.Origin->canPrintPretty()4
) {
1399
4
    if (HasSuffix) {
1400
4
      OS << "The value of ";
1401
4
      SI.Origin->printPretty(OS);
1402
4
      OS << " is assigned";
1403
4
    } else {
1404
0
      OS << "Assigning the value of ";
1405
0
      SI.Origin->printPretty(OS);
1406
0
    }
1407
1408
91
  } else {
1409
91
    OS << (HasSuffix ? 
"Value assigned"82
:
"Assigning value"9
);
1410
91
  }
1411
1412
452
  if (HasSuffix) {
1413
381
    OS << " to ";
1414
381
    SI.Dest->printPretty(OS);
1415
381
  }
1416
452
}
1417
1418
39
static bool isTrivialCopyOrMoveCtor(const CXXConstructExpr *CE) {
1419
39
  if (!CE)
1420
0
    return false;
1421
1422
39
  const auto *CtorDecl = CE->getConstructor();
1423
1424
39
  return CtorDecl->isCopyOrMoveConstructor() && 
CtorDecl->isTrivial()38
;
1425
39
}
1426
1427
static const Expr *tryExtractInitializerFromList(const InitListExpr *ILE,
1428
18
                                                 const MemRegion *R) {
1429
1430
18
  const auto *TVR = dyn_cast_or_null<TypedValueRegion>(R);
1431
1432
18
  if (!TVR)
1433
0
    return nullptr;
1434
1435
18
  const auto ITy = ILE->getType().getCanonicalType();
1436
1437
  // Push each sub-region onto the stack.
1438
18
  std::stack<const TypedValueRegion *> TVRStack;
1439
50
  while (isa<FieldRegion>(TVR) || 
isa<ElementRegion>(TVR)19
) {
1440
    // We found a region that matches the type of the init list,
1441
    // so we assume this is the outer-most region. This can happen
1442
    // if the initializer list is inside a class. If our assumption
1443
    // is wrong, we return a nullptr in the end.
1444
34
    if (ITy == TVR->getValueType().getCanonicalType())
1445
2
      break;
1446
1447
32
    TVRStack.push(TVR);
1448
32
    TVR = cast<TypedValueRegion>(TVR->getSuperRegion());
1449
32
  }
1450
1451
  // If the type of the outer most region doesn't match the type
1452
  // of the ILE, we can't match the ILE and the region.
1453
18
  if (ITy != TVR->getValueType().getCanonicalType())
1454
0
    return nullptr;
1455
1456
18
  const Expr *Init = ILE;
1457
50
  while (!TVRStack.empty()) {
1458
32
    TVR = TVRStack.top();
1459
32
    TVRStack.pop();
1460
1461
    // We hit something that's not an init list before
1462
    // running out of regions, so we most likely failed.
1463
32
    if (!isa<InitListExpr>(Init))
1464
0
      return nullptr;
1465
1466
32
    ILE = cast<InitListExpr>(Init);
1467
32
    auto NumInits = ILE->getNumInits();
1468
1469
32
    if (const auto *FR = dyn_cast<FieldRegion>(TVR)) {
1470
29
      const auto *FD = FR->getDecl();
1471
1472
29
      if (FD->getFieldIndex() >= NumInits)
1473
0
        return nullptr;
1474
1475
29
      Init = ILE->getInit(FD->getFieldIndex());
1476
29
    } else 
if (const auto *3
ER3
= dyn_cast<ElementRegion>(TVR)) {
1477
3
      const auto Ind = ER->getIndex();
1478
1479
      // If index is symbolic, we can't figure out which expression
1480
      // belongs to the region.
1481
3
      if (!Ind.isConstant())
1482
0
        return nullptr;
1483
1484
3
      const auto IndVal = Ind.getAsInteger()->getLimitedValue();
1485
3
      if (IndVal >= NumInits)
1486
0
        return nullptr;
1487
1488
3
      Init = ILE->getInit(IndVal);
1489
3
    }
1490
32
  }
1491
1492
18
  return Init;
1493
18
}
1494
1495
PathDiagnosticPieceRef StoreSiteFinder::VisitNode(const ExplodedNode *Succ,
1496
                                                  BugReporterContext &BRC,
1497
131k
                                                  PathSensitiveBugReport &BR) {
1498
131k
  if (Satisfied)
1499
59.7k
    return nullptr;
1500
1501
72.2k
  const ExplodedNode *StoreSite = nullptr;
1502
72.2k
  const ExplodedNode *Pred = Succ->getFirstPred();
1503
72.2k
  const Expr *InitE = nullptr;
1504
72.2k
  bool IsParam = false;
1505
1506
  // First see if we reached the declaration of the region.
1507
72.2k
  if (const auto *VR = dyn_cast<VarRegion>(R)) {
1508
58.6k
    if (isInitializationOfVar(Pred, VR)) {
1509
1.59k
      StoreSite = Pred;
1510
1.59k
      InitE = VR->getDecl()->getInit();
1511
1.59k
    }
1512
58.6k
  }
1513
1514
  // If this is a post initializer expression, initializing the region, we
1515
  // should track the initializer expression.
1516
72.2k
  if (std::optional<PostInitializer> PIP =
1517
72.2k
          Pred->getLocationAs<PostInitializer>()) {
1518
147
    const MemRegion *FieldReg = (const MemRegion *)PIP->getLocationValue();
1519
147
    if (FieldReg == R) {
1520
14
      StoreSite = Pred;
1521
14
      InitE = PIP->getInitializer()->getInit();
1522
14
    }
1523
147
  }
1524
1525
  // Otherwise, see if this is the store site:
1526
  // (1) Succ has this binding and Pred does not, i.e. this is
1527
  //     where the binding first occurred.
1528
  // (2) Succ has this binding and is a PostStore node for this region, i.e.
1529
  //     the same binding was re-assigned here.
1530
72.2k
  if (!StoreSite) {
1531
70.6k
    if (Succ->getState()->getSVal(R) != V)
1532
3.04k
      return nullptr;
1533
1534
67.6k
    if (hasVisibleUpdate(Pred, Pred->getState()->getSVal(R), Succ, V)) {
1535
66.9k
      std::optional<PostStore> PS = Succ->getLocationAs<PostStore>();
1536
66.9k
      if (!PS || 
PS->getLocationValue() != R1.12k
)
1537
66.9k
        return nullptr;
1538
66.9k
    }
1539
1540
683
    StoreSite = Succ;
1541
1542
683
    if (std::optional<PostStmt> P = Succ->getLocationAs<PostStmt>()) {
1543
      // If this is an assignment expression, we can track the value
1544
      // being assigned.
1545
491
      if (const BinaryOperator *BO = P->getStmtAs<BinaryOperator>()) {
1546
354
        if (BO->isAssignmentOp())
1547
354
          InitE = BO->getRHS();
1548
354
      }
1549
      // If we have a declaration like 'S s{1,2}' that needs special
1550
      // handling, we handle it here.
1551
137
      else if (const auto *DS = P->getStmtAs<DeclStmt>()) {
1552
16
        const auto *Decl = DS->getSingleDecl();
1553
16
        if (isa<VarDecl>(Decl)) {
1554
16
          const auto *VD = cast<VarDecl>(Decl);
1555
1556
          // FIXME: Here we only track the inner most region, so we lose
1557
          // information, but it's still better than a crash or no information
1558
          // at all.
1559
          //
1560
          // E.g.: The region we have is 's.s2.s3.s4.y' and we only track 'y',
1561
          // and throw away the rest.
1562
16
          if (const auto *ILE = dyn_cast<InitListExpr>(VD->getInit()))
1563
16
            InitE = tryExtractInitializerFromList(ILE, R);
1564
16
        }
1565
121
      } else if (const auto *CE = P->getStmtAs<CXXConstructExpr>()) {
1566
1567
39
        const auto State = Succ->getState();
1568
1569
39
        if (isTrivialCopyOrMoveCtor(CE) && 
isa<SubRegion>(R)38
) {
1570
          // Migrate the field regions from the current object to
1571
          // the parent object. If we track 'a.y.e' and encounter
1572
          // 'S a = b' then we need to track 'b.y.e'.
1573
1574
          // Push the regions to a stack, from last to first, so
1575
          // considering the example above the stack will look like
1576
          // (bottom) 'e' -> 'y' (top).
1577
1578
38
          std::stack<const SubRegion *> SRStack;
1579
38
          const SubRegion *SR = cast<SubRegion>(R);
1580
82
          while (isa<FieldRegion>(SR) || 
isa<ElementRegion>(SR)40
) {
1581
44
            SRStack.push(SR);
1582
44
            SR = cast<SubRegion>(SR->getSuperRegion());
1583
44
          }
1584
1585
          // Get the region for the object we copied/moved from.
1586
38
          const auto *OriginEx = CE->getArg(0);
1587
38
          const auto OriginVal =
1588
38
              State->getSVal(OriginEx, Succ->getLocationContext());
1589
1590
          // Pop the stored field regions and apply them to the origin
1591
          // object in the same order we had them on the copy.
1592
          // OriginField will evolve like 'b' -> 'b.y' -> 'b.y.e'.
1593
38
          SVal OriginField = OriginVal;
1594
82
          while (!SRStack.empty()) {
1595
44
            const auto *TopR = SRStack.top();
1596
44
            SRStack.pop();
1597
1598
44
            if (const auto *FR = dyn_cast<FieldRegion>(TopR)) {
1599
42
              OriginField = State->getLValue(FR->getDecl(), OriginField);
1600
42
            } else 
if (const auto *2
ER2
= dyn_cast<ElementRegion>(TopR)) {
1601
2
              OriginField = State->getLValue(ER->getElementType(),
1602
2
                                             ER->getIndex(), OriginField);
1603
2
            } else {
1604
              // FIXME: handle other region type
1605
0
            }
1606
44
          }
1607
1608
          // Track 'b.y.e'.
1609
38
          getParentTracker().track(V, OriginField.getAsRegion(), Options);
1610
38
          InitE = OriginEx;
1611
38
        }
1612
39
      }
1613
      // This branch can occur in cases like `Ctor() : field{ x, y } {}'.
1614
82
      else if (const auto *ILE = P->getStmtAs<InitListExpr>()) {
1615
        // FIXME: Here we only track the top level region, so we lose
1616
        // information, but it's still better than a crash or no information
1617
        // at all.
1618
        //
1619
        // E.g.: The region we have is 's.s2.s3.s4.y' and we only track 'y', and
1620
        // throw away the rest.
1621
2
        InitE = tryExtractInitializerFromList(ILE, R);
1622
2
      }
1623
491
    }
1624
1625
    // If this is a call entry, the variable should be a parameter.
1626
    // FIXME: Handle CXXThisRegion as well. (This is not a priority because
1627
    // 'this' should never be NULL, but this visitor isn't just for NULL and
1628
    // UndefinedVal.)
1629
683
    if (std::optional<CallEnter> CE = Succ->getLocationAs<CallEnter>()) {
1630
185
      if (const auto *VR = dyn_cast<VarRegion>(R)) {
1631
1632
185
        if (const auto *Param = dyn_cast<ParmVarDecl>(VR->getDecl())) {
1633
164
          ProgramStateManager &StateMgr = BRC.getStateManager();
1634
164
          CallEventManager &CallMgr = StateMgr.getCallEventManager();
1635
1636
164
          CallEventRef<> Call = CallMgr.getCaller(CE->getCalleeContext(),
1637
164
                                                  Succ->getState());
1638
164
          InitE = Call->getArgExpr(Param->getFunctionScopeIndex());
1639
164
        } else {
1640
          // Handle Objective-C 'self'.
1641
21
          assert(isa<ImplicitParamDecl>(VR->getDecl()));
1642
21
          InitE = cast<ObjCMessageExpr>(CE->getCalleeContext()->getCallSite())
1643
21
                      ->getInstanceReceiver()->IgnoreParenCasts();
1644
21
        }
1645
185
        IsParam = true;
1646
185
      }
1647
185
    }
1648
1649
    // If this is a CXXTempObjectRegion, the Expr responsible for its creation
1650
    // is wrapped inside of it.
1651
683
    if (const auto *TmpR = dyn_cast<CXXTempObjectRegion>(R))
1652
6
      InitE = TmpR->getExpr();
1653
683
  }
1654
1655
2.29k
  if (!StoreSite)
1656
0
    return nullptr;
1657
1658
2.29k
  Satisfied = true;
1659
1660
  // If we have an expression that provided the value, try to track where it
1661
  // came from.
1662
2.29k
  if (InitE) {
1663
1.70k
    if (!IsParam)
1664
1.51k
      InitE = InitE->IgnoreParenCasts();
1665
1666
1.70k
    getParentTracker().track(InitE, StoreSite, Options);
1667
1.70k
  }
1668
1669
  // Let's try to find the region where the value came from.
1670
2.29k
  const MemRegion *OldRegion = nullptr;
1671
1672
  // If we have init expression, it might be simply a reference
1673
  // to a variable, so we can use it.
1674
2.29k
  if (InitE) {
1675
    // That region might still be not exactly what we are looking for.
1676
    // In situations like `int &ref = val;`, we can't say that
1677
    // `ref` is initialized with `val`, rather refers to `val`.
1678
    //
1679
    // In order, to mitigate situations like this, we check if the last
1680
    // stored value in that region is the value that we track.
1681
    //
1682
    // TODO: support other situations better.
1683
1.70k
    if (const MemRegion *Candidate =
1684
1.70k
            getLocationRegionIfReference(InitE, Succ, false)) {
1685
174
      const StoreManager &SM = BRC.getStateManager().getStoreManager();
1686
1687
      // Here we traverse the graph up to find the last node where the
1688
      // candidate region is still in the store.
1689
1.44k
      for (const ExplodedNode *N = StoreSite; N; 
N = N->getFirstPred()1.26k
) {
1690
1.40k
        if (SM.includedInBindings(N->getState()->getStore(), Candidate)) {
1691
          // And if it was bound to the target value, we can use it.
1692
139
          if (N->getState()->getSVal(Candidate) == V) {
1693
68
            OldRegion = Candidate;
1694
68
          }
1695
139
          break;
1696
139
        }
1697
1.40k
      }
1698
174
    }
1699
1.70k
  }
1700
1701
  // Otherwise, if the current region does indeed contain the value
1702
  // we are looking for, we can look for a region where this value
1703
  // was before.
1704
  //
1705
  // It can be useful for situations like:
1706
  //     new = identity(old)
1707
  // where the analyzer knows that 'identity' returns the value of its
1708
  // first argument.
1709
  //
1710
  // NOTE: If the region R is not a simple var region, it can contain
1711
  //       V in one of its subregions.
1712
2.29k
  if (!OldRegion && 
StoreSite->getState()->getSVal(R) == V2.22k
) {
1713
    // Let's go up the graph to find the node where the region is
1714
    // bound to V.
1715
2.21k
    const ExplodedNode *NodeWithoutBinding = StoreSite->getFirstPred();
1716
2.21k
    for (;
1717
11.3k
         NodeWithoutBinding && 
NodeWithoutBinding->getState()->getSVal(R) == V10.8k
;
1718
9.10k
         NodeWithoutBinding = NodeWithoutBinding->getFirstPred()) {
1719
9.10k
    }
1720
1721
2.21k
    if (NodeWithoutBinding) {
1722
      // Let's try to find a unique binding for the value in that node.
1723
      // We want to use this to find unique bindings because of the following
1724
      // situations:
1725
      //     b = a;
1726
      //     c = identity(b);
1727
      //
1728
      // Telling the user that the value of 'a' is assigned to 'c', while
1729
      // correct, can be confusing.
1730
1.69k
      StoreManager::FindUniqueBinding FB(V.getAsLocSymbol());
1731
1.69k
      BRC.getStateManager().iterBindings(NodeWithoutBinding->getState(), FB);
1732
1.69k
      if (FB)
1733
6
        OldRegion = FB.getRegion();
1734
1.69k
    }
1735
2.21k
  }
1736
1737
2.29k
  if (Options.Kind == TrackingKind::Condition && 
OriginSFC184
&&
1738
2.29k
      
!OriginSFC->isParentOf(StoreSite->getStackFrame())184
)
1739
159
    return nullptr;
1740
1741
  // Okay, we've found the binding. Emit an appropriate message.
1742
2.13k
  SmallString<256> sbuf;
1743
2.13k
  llvm::raw_svector_ostream os(sbuf);
1744
1745
2.13k
  StoreInfo SI = {StoreInfo::Assignment, // default kind
1746
2.13k
                  StoreSite,
1747
2.13k
                  InitE,
1748
2.13k
                  V,
1749
2.13k
                  R,
1750
2.13k
                  OldRegion};
1751
1752
2.13k
  if (std::optional<PostStmt> PS = StoreSite->getLocationAs<PostStmt>()) {
1753
1.98k
    const Stmt *S = PS->getStmt();
1754
1.98k
    const auto *DS = dyn_cast<DeclStmt>(S);
1755
1.98k
    const auto *VR = dyn_cast<VarRegion>(R);
1756
1757
1.98k
    if (DS) {
1758
1.55k
      SI.StoreKind = StoreInfo::Initialization;
1759
1.55k
    } else 
if (435
isa<BlockExpr>(S)435
) {
1760
4
      SI.StoreKind = StoreInfo::BlockCapture;
1761
4
      if (VR) {
1762
        // See if we can get the BlockVarRegion.
1763
4
        ProgramStateRef State = StoreSite->getState();
1764
4
        SVal V = StoreSite->getSVal(S);
1765
4
        if (const auto *BDR =
1766
4
                dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
1767
4
          if (const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) {
1768
4
            getParentTracker().track(State->getSVal(OriginalR), OriginalR,
1769
4
                                     Options, OriginSFC);
1770
4
          }
1771
4
        }
1772
4
      }
1773
4
    }
1774
1.98k
  } else 
if (147
SI.StoreSite->getLocation().getAs<CallEnter>()147
&&
1775
147
             
isa<VarRegion>(SI.Dest)126
) {
1776
126
    SI.StoreKind = StoreInfo::CallArgument;
1777
126
  }
1778
1779
2.13k
  return getParentTracker().handle(SI, BRC, Options);
1780
2.29k
}
1781
1782
//===----------------------------------------------------------------------===//
1783
// Implementation of TrackConstraintBRVisitor.
1784
//===----------------------------------------------------------------------===//
1785
1786
410
void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
1787
410
  static int tag = 0;
1788
410
  ID.AddPointer(&tag);
1789
410
  ID.AddString(Message);
1790
410
  ID.AddBoolean(Assumption);
1791
410
  ID.Add(Constraint);
1792
410
}
1793
1794
/// Return the tag associated with this visitor.  This tag will be used
1795
/// to make all PathDiagnosticPieces created by this visitor.
1796
1.92k
const char *TrackConstraintBRVisitor::getTag() {
1797
1.92k
  return "TrackConstraintBRVisitor";
1798
1.92k
}
1799
1800
8.48k
bool TrackConstraintBRVisitor::isZeroCheck() const {
1801
8.48k
  return !Assumption && Constraint.getAs<Loc>();
1802
8.48k
}
1803
1804
8.48k
bool TrackConstraintBRVisitor::isUnderconstrained(const ExplodedNode *N) const {
1805
8.48k
  if (isZeroCheck())
1806
8.45k
    return N->getState()->isNull(Constraint).isUnderconstrained();
1807
24
  return (bool)N->getState()->assume(Constraint, !Assumption);
1808
8.48k
}
1809
1810
PathDiagnosticPieceRef TrackConstraintBRVisitor::VisitNode(
1811
11.0k
    const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &) {
1812
11.0k
  const ExplodedNode *PrevN = N->getFirstPred();
1813
11.0k
  if (IsSatisfied)
1814
3.34k
    return nullptr;
1815
1816
  // Start tracking after we see the first state in which the value is
1817
  // constrained.
1818
7.73k
  if (!IsTrackingTurnedOn)
1819
1.09k
    if (!isUnderconstrained(N))
1820
371
      IsTrackingTurnedOn = true;
1821
7.73k
  if (!IsTrackingTurnedOn)
1822
728
    return nullptr;
1823
1824
  // Check if in the previous state it was feasible for this constraint
1825
  // to *not* be true.
1826
7.01k
  if (isUnderconstrained(PrevN)) {
1827
371
    IsSatisfied = true;
1828
1829
    // At this point, the negation of the constraint should be infeasible. If it
1830
    // is feasible, make sure that the negation of the constrainti was
1831
    // infeasible in the current state.  If it is feasible, we somehow missed
1832
    // the transition point.
1833
371
    assert(!isUnderconstrained(N));
1834
1835
    // Construct a new PathDiagnosticPiece.
1836
371
    ProgramPoint P = N->getLocation();
1837
1838
    // If this node already have a specialized note, it's probably better
1839
    // than our generic note.
1840
    // FIXME: This only looks for note tags, not for other ways to add a note.
1841
371
    if (isa_and_nonnull<NoteTag>(P.getTag()))
1842
17
      return nullptr;
1843
1844
354
    PathDiagnosticLocation L =
1845
354
      PathDiagnosticLocation::create(P, BRC.getSourceManager());
1846
354
    if (!L.isValid())
1847
0
      return nullptr;
1848
1849
354
    auto X = std::make_shared<PathDiagnosticEventPiece>(L, Message);
1850
354
    X->setTag(getTag());
1851
354
    return std::move(X);
1852
354
  }
1853
1854
6.64k
  return nullptr;
1855
7.01k
}
1856
1857
//===----------------------------------------------------------------------===//
1858
// Implementation of SuppressInlineDefensiveChecksVisitor.
1859
//===----------------------------------------------------------------------===//
1860
1861
SuppressInlineDefensiveChecksVisitor::
1862
SuppressInlineDefensiveChecksVisitor(DefinedSVal Value, const ExplodedNode *N)
1863
762
    : V(Value) {
1864
  // Check if the visitor is disabled.
1865
762
  AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
1866
762
  if (!Options.ShouldSuppressInlinedDefensiveChecks)
1867
0
    IsSatisfied = true;
1868
762
}
1869
1870
void SuppressInlineDefensiveChecksVisitor::Profile(
1871
762
    llvm::FoldingSetNodeID &ID) const {
1872
762
  static int id = 0;
1873
762
  ID.AddPointer(&id);
1874
762
  ID.Add(V);
1875
762
}
1876
1877
0
const char *SuppressInlineDefensiveChecksVisitor::getTag() {
1878
0
  return "IDCVisitor";
1879
0
}
1880
1881
PathDiagnosticPieceRef
1882
SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ,
1883
                                                BugReporterContext &BRC,
1884
29.2k
                                                PathSensitiveBugReport &BR) {
1885
29.2k
  const ExplodedNode *Pred = Succ->getFirstPred();
1886
29.2k
  if (IsSatisfied)
1887
3.17k
    return nullptr;
1888
1889
  // Start tracking after we see the first state in which the value is null.
1890
26.1k
  if (!IsTrackingTurnedOn)
1891
19.6k
    if (Succ->getState()->isNull(V).isConstrainedTrue())
1892
371
      IsTrackingTurnedOn = true;
1893
26.1k
  if (!IsTrackingTurnedOn)
1894
19.2k
    return nullptr;
1895
1896
  // Check if in the previous state it was feasible for this value
1897
  // to *not* be null.
1898
6.85k
  if (!Pred->getState()->isNull(V).isConstrainedTrue() &&
1899
6.85k
      
Succ->getState()->isNull(V).isConstrainedTrue()371
) {
1900
371
    IsSatisfied = true;
1901
1902
    // Check if this is inlined defensive checks.
1903
371
    const LocationContext *CurLC = Succ->getLocationContext();
1904
371
    const LocationContext *ReportLC = BR.getErrorNode()->getLocationContext();
1905
371
    if (CurLC != ReportLC && 
!CurLC->isParentOf(ReportLC)56
) {
1906
51
      BR.markInvalid("Suppress IDC", CurLC);
1907
51
      return nullptr;
1908
51
    }
1909
1910
    // Treat defensive checks in function-like macros as if they were an inlined
1911
    // defensive check. If the bug location is not in a macro and the
1912
    // terminator for the current location is in a macro then suppress the
1913
    // warning.
1914
320
    auto BugPoint = BR.getErrorNode()->getLocation().getAs<StmtPoint>();
1915
1916
320
    if (!BugPoint)
1917
0
      return nullptr;
1918
1919
320
    ProgramPoint CurPoint = Succ->getLocation();
1920
320
    const Stmt *CurTerminatorStmt = nullptr;
1921
320
    if (auto BE = CurPoint.getAs<BlockEdge>()) {
1922
162
      CurTerminatorStmt = BE->getSrc()->getTerminator().getStmt();
1923
162
    } else 
if (auto 158
SP158
= CurPoint.getAs<StmtPoint>()) {
1924
158
      const Stmt *CurStmt = SP->getStmt();
1925
158
      if (!CurStmt->getBeginLoc().isMacroID())
1926
123
        return nullptr;
1927
1928
35
      CFGStmtMap *Map = CurLC->getAnalysisDeclContext()->getCFGStmtMap();
1929
35
      CurTerminatorStmt = Map->getBlock(CurStmt)->getTerminatorStmt();
1930
35
    } else {
1931
0
      return nullptr;
1932
0
    }
1933
1934
197
    if (!CurTerminatorStmt)
1935
2
      return nullptr;
1936
1937
195
    SourceLocation TerminatorLoc = CurTerminatorStmt->getBeginLoc();
1938
195
    if (TerminatorLoc.isMacroID()) {
1939
35
      SourceLocation BugLoc = BugPoint->getStmt()->getBeginLoc();
1940
1941
      // Suppress reports unless we are in that same macro.
1942
35
      if (!BugLoc.isMacroID() ||
1943
35
          
getMacroName(BugLoc, BRC) != getMacroName(TerminatorLoc, BRC)11
) {
1944
27
        BR.markInvalid("Suppress Macro IDC", CurLC);
1945
27
      }
1946
35
      return nullptr;
1947
35
    }
1948
195
  }
1949
6.64k
  return nullptr;
1950
6.85k
}
1951
1952
//===----------------------------------------------------------------------===//
1953
// TrackControlDependencyCondBRVisitor.
1954
//===----------------------------------------------------------------------===//
1955
1956
namespace {
1957
/// Tracks the expressions that are a control dependency of the node that was
1958
/// supplied to the constructor.
1959
/// For example:
1960
///
1961
///   cond = 1;
1962
///   if (cond)
1963
///     10 / 0;
1964
///
1965
/// An error is emitted at line 3. This visitor realizes that the branch
1966
/// on line 2 is a control dependency of line 3, and tracks it's condition via
1967
/// trackExpressionValue().
1968
class TrackControlDependencyCondBRVisitor final
1969
    : public TrackingBugReporterVisitor {
1970
  const ExplodedNode *Origin;
1971
  ControlDependencyCalculator ControlDeps;
1972
  llvm::SmallSet<const CFGBlock *, 32> VisitedBlocks;
1973
1974
public:
1975
  TrackControlDependencyCondBRVisitor(TrackerRef ParentTracker,
1976
                                      const ExplodedNode *O)
1977
      : TrackingBugReporterVisitor(ParentTracker), Origin(O),
1978
5.71k
        ControlDeps(&O->getCFG()) {}
1979
1980
5.71k
  void Profile(llvm::FoldingSetNodeID &ID) const override {
1981
5.71k
    static int x = 0;
1982
5.71k
    ID.AddPointer(&x);
1983
5.71k
  }
1984
1985
  PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
1986
                                   BugReporterContext &BRC,
1987
                                   PathSensitiveBugReport &BR) override;
1988
};
1989
} // end of anonymous namespace
1990
1991
static std::shared_ptr<PathDiagnosticEventPiece>
1992
constructDebugPieceForTrackedCondition(const Expr *Cond,
1993
                                       const ExplodedNode *N,
1994
831
                                       BugReporterContext &BRC) {
1995
1996
831
  if (BRC.getAnalyzerOptions().AnalysisDiagOpt == PD_NONE ||
1997
831
      !BRC.getAnalyzerOptions().ShouldTrackConditionsDebug)
1998
800
    return nullptr;
1999
2000
31
  std::string ConditionText = std::string(Lexer::getSourceText(
2001
31
      CharSourceRange::getTokenRange(Cond->getSourceRange()),
2002
31
      BRC.getSourceManager(), BRC.getASTContext().getLangOpts()));
2003
2004
31
  return std::make_shared<PathDiagnosticEventPiece>(
2005
31
      PathDiagnosticLocation::createBegin(
2006
31
          Cond, BRC.getSourceManager(), N->getLocationContext()),
2007
31
          (Twine() + "Tracking condition '" + ConditionText + "'").str());
2008
831
}
2009
2010
10.3k
static bool isAssertlikeBlock(const CFGBlock *B, ASTContext &Context) {
2011
10.3k
  if (B->succ_size() != 2)
2012
6.19k
    return false;
2013
2014
4.14k
  const CFGBlock *Then = B->succ_begin()->getReachableBlock();
2015
4.14k
  const CFGBlock *Else = (B->succ_begin() + 1)->getReachableBlock();
2016
2017
4.14k
  if (!Then || 
!Else4.09k
)
2018
604
    return false;
2019
2020
3.54k
  if (Then->isInevitablySinking() != Else->isInevitablySinking())
2021
50
    return true;
2022
2023
  // For the following condition the following CFG would be built:
2024
  //
2025
  //                          ------------->
2026
  //                         /              \
2027
  //                       [B1] -> [B2] -> [B3] -> [sink]
2028
  // assert(A && B || C);            \       \
2029
  //                                  -----------> [go on with the execution]
2030
  //
2031
  // It so happens that CFGBlock::getTerminatorCondition returns 'A' for block
2032
  // B1, 'A && B' for B2, and 'A && B || C' for B3. Let's check whether we
2033
  // reached the end of the condition!
2034
3.49k
  if (const Stmt *ElseCond = Else->getTerminatorCondition())
2035
786
    if (const auto *BinOp = dyn_cast<BinaryOperator>(ElseCond))
2036
255
      if (BinOp->isLogicalOp())
2037
109
        return isAssertlikeBlock(Else, Context);
2038
2039
3.38k
  return false;
2040
3.49k
}
2041
2042
PathDiagnosticPieceRef
2043
TrackControlDependencyCondBRVisitor::VisitNode(const ExplodedNode *N,
2044
                                               BugReporterContext &BRC,
2045
214k
                                               PathSensitiveBugReport &BR) {
2046
  // We can only reason about control dependencies within the same stack frame.
2047
214k
  if (Origin->getStackFrame() != N->getStackFrame())
2048
58.9k
    return nullptr;
2049
2050
155k
  CFGBlock *NB = const_cast<CFGBlock *>(N->getCFGBlock());
2051
2052
  // Skip if we already inspected this block.
2053
155k
  if (!VisitedBlocks.insert(NB).second)
2054
144k
    return nullptr;
2055
2056
11.7k
  CFGBlock *OriginB = const_cast<CFGBlock *>(Origin->getCFGBlock());
2057
2058
  // TODO: Cache CFGBlocks for each ExplodedNode.
2059
11.7k
  if (!OriginB || !NB)
2060
1.52k
    return nullptr;
2061
2062
10.2k
  if (isAssertlikeBlock(NB, BRC.getASTContext()))
2063
50
    return nullptr;
2064
2065
10.1k
  if (ControlDeps.isControlDependent(OriginB, NB)) {
2066
    // We don't really want to explain for range loops. Evidence suggests that
2067
    // the only thing that leads to is the addition of calls to operator!=.
2068
1.78k
    if (llvm::isa_and_nonnull<CXXForRangeStmt>(NB->getTerminatorStmt()))
2069
16
      return nullptr;
2070
2071
1.76k
    if (const Expr *Condition = NB->getLastCondition()) {
2072
2073
      // If we can't retrieve a sensible condition, just bail out.
2074
1.50k
      const Expr *InnerExpr = peelOffOuterExpr(Condition, N);
2075
1.50k
      if (!InnerExpr)
2076
0
        return nullptr;
2077
2078
      // If the condition was a function call, we likely won't gain much from
2079
      // tracking it either. Evidence suggests that it will mostly trigger in
2080
      // scenarios like this:
2081
      //
2082
      //   void f(int *x) {
2083
      //     x = nullptr;
2084
      //     if (alwaysTrue()) // We don't need a whole lot of explanation
2085
      //                       // here, the function name is good enough.
2086
      //       *x = 5;
2087
      //   }
2088
      //
2089
      // Its easy to create a counterexample where this heuristic would make us
2090
      // lose valuable information, but we've never really seen one in practice.
2091
1.50k
      if (isa<CallExpr>(InnerExpr))
2092
367
        return nullptr;
2093
2094
      // Keeping track of the already tracked conditions on a visitor level
2095
      // isn't sufficient, because a new visitor is created for each tracked
2096
      // expression, hence the BugReport level set.
2097
1.14k
      if (BR.addTrackedCondition(N)) {
2098
831
        getParentTracker().track(InnerExpr, N,
2099
831
                                 {bugreporter::TrackingKind::Condition,
2100
831
                                  /*EnableNullFPSuppression=*/false});
2101
831
        return constructDebugPieceForTrackedCondition(Condition, N, BRC);
2102
831
      }
2103
1.14k
    }
2104
1.76k
  }
2105
2106
8.97k
  return nullptr;
2107
10.1k
}
2108
2109
//===----------------------------------------------------------------------===//
2110
// Implementation of trackExpressionValue.
2111
//===----------------------------------------------------------------------===//
2112
2113
7.79k
static const Expr *peelOffOuterExpr(const Expr *Ex, const ExplodedNode *N) {
2114
2115
7.79k
  Ex = Ex->IgnoreParenCasts();
2116
7.79k
  if (const auto *FE = dyn_cast<FullExpr>(Ex))
2117
0
    return peelOffOuterExpr(FE->getSubExpr(), N);
2118
7.79k
  if (const auto *OVE = dyn_cast<OpaqueValueExpr>(Ex))
2119
33
    return peelOffOuterExpr(OVE->getSourceExpr(), N);
2120
7.75k
  if (const auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {
2121
57
    const auto *PropRef = dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
2122
57
    if (PropRef && PropRef->isMessagingGetter()) {
2123
57
      const Expr *GetterMessageSend =
2124
57
          POE->getSemanticExpr(POE->getNumSemanticExprs() - 1);
2125
57
      assert(isa<ObjCMessageExpr>(GetterMessageSend->IgnoreParenCasts()));
2126
57
      return peelOffOuterExpr(GetterMessageSend, N);
2127
57
    }
2128
57
  }
2129
2130
  // Peel off the ternary operator.
2131
7.70k
  if (const auto *CO = dyn_cast<ConditionalOperator>(Ex)) {
2132
    // Find a node where the branching occurred and find out which branch
2133
    // we took (true/false) by looking at the ExplodedGraph.
2134
48
    const ExplodedNode *NI = N;
2135
1.16k
    do {
2136
1.16k
      ProgramPoint ProgPoint = NI->getLocation();
2137
1.16k
      if (std::optional<BlockEdge> BE = ProgPoint.getAs<BlockEdge>()) {
2138
191
        const CFGBlock *srcBlk = BE->getSrc();
2139
191
        if (const Stmt *term = srcBlk->getTerminatorStmt()) {
2140
61
          if (term == CO) {
2141
47
            bool TookTrueBranch = (*(srcBlk->succ_begin()) == BE->getDst());
2142
47
            if (TookTrueBranch)
2143
25
              return peelOffOuterExpr(CO->getTrueExpr(), N);
2144
22
            else
2145
22
              return peelOffOuterExpr(CO->getFalseExpr(), N);
2146
47
          }
2147
61
        }
2148
191
      }
2149
1.11k
      NI = NI->getFirstPred();
2150
1.11k
    } while (NI);
2151
48
  }
2152
2153
7.65k
  if (auto *BO = dyn_cast<BinaryOperator>(Ex))
2154
1.05k
    if (const Expr *SubEx = peelOffPointerArithmetic(BO))
2155
19
      return peelOffOuterExpr(SubEx, N);
2156
2157
7.63k
  if (auto *UO = dyn_cast<UnaryOperator>(Ex)) {
2158
382
    if (UO->getOpcode() == UO_LNot)
2159
220
      return peelOffOuterExpr(UO->getSubExpr(), N);
2160
2161
    // FIXME: There's a hack in our Store implementation that always computes
2162
    // field offsets around null pointers as if they are always equal to 0.
2163
    // The idea here is to report accesses to fields as null dereferences
2164
    // even though the pointer value that's being dereferenced is actually
2165
    // the offset of the field rather than exactly 0.
2166
    // See the FIXME in StoreManager's getLValueFieldOrIvar() method.
2167
    // This code interacts heavily with this hack; otherwise the value
2168
    // would not be null at all for most fields, so we'd be unable to track it.
2169
162
    if (UO->getOpcode() == UO_AddrOf && 
UO->getSubExpr()->isLValue()49
)
2170
49
      if (const Expr *DerefEx = bugreporter::getDerefExpr(UO->getSubExpr()))
2171
49
        return peelOffOuterExpr(DerefEx, N);
2172
162
  }
2173
2174
7.36k
  return Ex;
2175
7.63k
}
2176
2177
/// Find the ExplodedNode where the lvalue (the value of 'Ex')
2178
/// was computed.
2179
static const ExplodedNode* findNodeForExpression(const ExplodedNode *N,
2180
8.46k
                                                 const Expr *Inner) {
2181
56.8k
  while (N) {
2182
56.8k
    if (N->getStmtForDiagnostics() == Inner)
2183
8.40k
      return N;
2184
48.4k
    N = N->getFirstPred();
2185
48.4k
  }
2186
62
  return N;
2187
8.46k
}
2188
2189
//===----------------------------------------------------------------------===//
2190
//                            Tracker implementation
2191
//===----------------------------------------------------------------------===//
2192
2193
PathDiagnosticPieceRef StoreHandler::constructNote(StoreInfo SI,
2194
                                                   BugReporterContext &BRC,
2195
2.13k
                                                   StringRef NodeText) {
2196
  // Construct a new PathDiagnosticPiece.
2197
2.13k
  ProgramPoint P = SI.StoreSite->getLocation();
2198
2.13k
  PathDiagnosticLocation L;
2199
2.13k
  if (P.getAs<CallEnter>() && 
SI.SourceOfTheValue126
)
2200
126
    L = PathDiagnosticLocation(SI.SourceOfTheValue, BRC.getSourceManager(),
2201
126
                               P.getLocationContext());
2202
2203
2.13k
  if (!L.isValid() || 
!L.asLocation().isValid()126
)
2204
2.01k
    L = PathDiagnosticLocation::create(P, BRC.getSourceManager());
2205
2206
2.13k
  if (!L.isValid() || !L.asLocation().isValid())
2207
1
    return nullptr;
2208
2209
2.13k
  return std::make_shared<PathDiagnosticEventPiece>(L, NodeText);
2210
2.13k
}
2211
2212
namespace {
2213
class DefaultStoreHandler final : public StoreHandler {
2214
public:
2215
  using StoreHandler::StoreHandler;
2216
2217
  PathDiagnosticPieceRef handle(StoreInfo SI, BugReporterContext &BRC,
2218
2.13k
                                TrackingOptions Opts) override {
2219
    // Okay, we've found the binding. Emit an appropriate message.
2220
2.13k
    SmallString<256> Buffer;
2221
2.13k
    llvm::raw_svector_ostream OS(Buffer);
2222
2223
2.13k
    switch (SI.StoreKind) {
2224
1.55k
    case StoreInfo::Initialization:
2225
1.55k
    case StoreInfo::BlockCapture:
2226
1.55k
      showBRDiagnostics(OS, SI);
2227
1.55k
      break;
2228
126
    case StoreInfo::CallArgument:
2229
126
      showBRParamDiagnostics(OS, SI);
2230
126
      break;
2231
452
    case StoreInfo::Assignment:
2232
452
      showBRDefaultDiagnostics(OS, SI);
2233
452
      break;
2234
2.13k
    }
2235
2236
2.13k
    if (Opts.Kind == bugreporter::TrackingKind::Condition)
2237
25
      OS << WillBeUsedForACondition;
2238
2239
2.13k
    return constructNote(SI, BRC, OS.str());
2240
2.13k
  }
2241
};
2242
2243
class ControlDependencyHandler final : public ExpressionHandler {
2244
public:
2245
  using ExpressionHandler::ExpressionHandler;
2246
2247
  Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
2248
                         const ExplodedNode *LVNode,
2249
5.79k
                         TrackingOptions Opts) override {
2250
5.79k
    PathSensitiveBugReport &Report = getParentTracker().getReport();
2251
2252
    // We only track expressions if we believe that they are important. Chances
2253
    // are good that control dependencies to the tracking point are also
2254
    // important because of this, let's explain why we believe control reached
2255
    // this point.
2256
    // TODO: Shouldn't we track control dependencies of every bug location,
2257
    // rather than only tracked expressions?
2258
5.79k
    if (LVNode->getState()
2259
5.79k
            ->getAnalysisManager()
2260
5.79k
            .getAnalyzerOptions()
2261
5.79k
            .ShouldTrackConditions) {
2262
5.71k
      Report.addVisitor<TrackControlDependencyCondBRVisitor>(
2263
5.71k
          &getParentTracker(), InputNode);
2264
5.71k
      return {/*FoundSomethingToTrack=*/true};
2265
5.71k
    }
2266
2267
84
    return {};
2268
5.79k
  }
2269
};
2270
2271
class NilReceiverHandler final : public ExpressionHandler {
2272
public:
2273
  using ExpressionHandler::ExpressionHandler;
2274
2275
  Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
2276
                         const ExplodedNode *LVNode,
2277
5.79k
                         TrackingOptions Opts) override {
2278
    // The message send could be nil due to the receiver being nil.
2279
    // At this point in the path, the receiver should be live since we are at
2280
    // the message send expr. If it is nil, start tracking it.
2281
5.79k
    if (const Expr *Receiver =
2282
5.79k
            NilReceiverBRVisitor::getNilReceiver(Inner, LVNode))
2283
41
      return getParentTracker().track(Receiver, LVNode, Opts);
2284
2285
5.75k
    return {};
2286
5.79k
  }
2287
};
2288
2289
class ArrayIndexHandler final : public ExpressionHandler {
2290
public:
2291
  using ExpressionHandler::ExpressionHandler;
2292
2293
  Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
2294
                         const ExplodedNode *LVNode,
2295
5.79k
                         TrackingOptions Opts) override {
2296
    // Track the index if this is an array subscript.
2297
5.79k
    if (const auto *Arr = dyn_cast<ArraySubscriptExpr>(Inner))
2298
53
      return getParentTracker().track(
2299
53
          Arr->getIdx(), LVNode,
2300
53
          {Opts.Kind, /*EnableNullFPSuppression*/ false});
2301
2302
5.74k
    return {};
2303
5.79k
  }
2304
};
2305
2306
// TODO: extract it into more handlers
2307
class InterestingLValueHandler final : public ExpressionHandler {
2308
public:
2309
  using ExpressionHandler::ExpressionHandler;
2310
2311
  Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
2312
                         const ExplodedNode *LVNode,
2313
5.79k
                         TrackingOptions Opts) override {
2314
5.79k
    ProgramStateRef LVState = LVNode->getState();
2315
5.79k
    const StackFrameContext *SFC = LVNode->getStackFrame();
2316
5.79k
    PathSensitiveBugReport &Report = getParentTracker().getReport();
2317
5.79k
    Tracker::Result Result;
2318
2319
    // See if the expression we're interested refers to a variable.
2320
    // If so, we can track both its contents and constraints on its value.
2321
5.79k
    if (ExplodedGraph::isInterestingLValueExpr(Inner)) {
2322
3.08k
      SVal LVal = LVNode->getSVal(Inner);
2323
2324
3.08k
      const MemRegion *RR = getLocationRegionIfReference(Inner, LVNode);
2325
3.08k
      bool LVIsNull = LVState->isNull(LVal).isConstrainedTrue();
2326
2327
      // If this is a C++ reference to a null pointer, we are tracking the
2328
      // pointer. In addition, we should find the store at which the reference
2329
      // got initialized.
2330
3.08k
      if (RR && 
!LVIsNull50
)
2331
43
        Result.combineWith(getParentTracker().track(LVal, RR, Opts, SFC));
2332
2333
      // In case of C++ references, we want to differentiate between a null
2334
      // reference and reference to null pointer.
2335
      // If the LVal is null, check if we are dealing with null reference.
2336
      // For those, we want to track the location of the reference.
2337
3.08k
      const MemRegion *R =
2338
3.08k
          (RR && 
LVIsNull50
) ?
RR7
:
LVNode->getSVal(Inner).getAsRegion()3.08k
;
2339
2340
3.08k
      if (R) {
2341
2342
        // Mark both the variable region and its contents as interesting.
2343
3.08k
        SVal V = LVState->getRawSVal(loc::MemRegionVal(R));
2344
3.08k
        Report.addVisitor<NoStoreFuncVisitor>(cast<SubRegion>(R), Opts.Kind);
2345
2346
        // When we got here, we do have something to track, and we will
2347
        // interrupt.
2348
3.08k
        Result.FoundSomethingToTrack = true;
2349
3.08k
        Result.WasInterrupted = true;
2350
2351
3.08k
        MacroNullReturnSuppressionVisitor::addMacroVisitorIfNecessary(
2352
3.08k
            LVNode, R, Opts.EnableNullFPSuppression, Report, V);
2353
2354
3.08k
        Report.markInteresting(V, Opts.Kind);
2355
3.08k
        Report.addVisitor<UndefOrNullArgVisitor>(R);
2356
2357
        // If the contents are symbolic and null, find out when they became
2358
        // null.
2359
3.08k
        if (V.getAsLocSymbol(/*IncludeBaseRegions=*/true))
2360
688
          if (LVState->isNull(V).isConstrainedTrue())
2361
389
            Report.addVisitor<TrackConstraintBRVisitor>(
2362
389
                V.castAs<DefinedSVal>(),
2363
389
                /*Assumption=*/false, "Assuming pointer value is null");
2364
2365
        // Add visitor, which will suppress inline defensive checks.
2366
3.08k
        if (auto DV = V.getAs<DefinedSVal>())
2367
2.47k
          if (!DV->isZeroConstant() && 
Opts.EnableNullFPSuppression1.26k
)
2368
            // Note that LVNode may be too late (i.e., too far from the
2369
            // InputNode) because the lvalue may have been computed before the
2370
            // inlined call was evaluated. InputNode may as well be too early
2371
            // here, because the symbol is already dead; this, however, is fine
2372
            // because we can still find the node in which it collapsed to null
2373
            // previously.
2374
762
            Report.addVisitor<SuppressInlineDefensiveChecksVisitor>(*DV,
2375
762
                                                                    InputNode);
2376
3.08k
        getParentTracker().track(V, R, Opts, SFC);
2377
3.08k
      }
2378
3.08k
    }
2379
2380
5.79k
    return Result;
2381
5.79k
  }
2382
};
2383
2384
/// Adds a ReturnVisitor if the given statement represents a call that was
2385
/// inlined.
2386
///
2387
/// This will search back through the ExplodedGraph, starting from the given
2388
/// node, looking for when the given statement was processed. If it turns out
2389
/// the statement is a call that was inlined, we add the visitor to the
2390
/// bug report, so it can print a note later.
2391
class InlinedFunctionCallHandler final : public ExpressionHandler {
2392
  using ExpressionHandler::ExpressionHandler;
2393
2394
  Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
2395
                         const ExplodedNode *ExprNode,
2396
2.71k
                         TrackingOptions Opts) override {
2397
2.71k
    if (!CallEvent::isCallStmt(E))
2398
2.01k
      return {};
2399
2400
    // First, find when we processed the statement.
2401
    // If we work with a 'CXXNewExpr' that is going to be purged away before
2402
    // its call take place. We would catch that purge in the last condition
2403
    // as a 'StmtPoint' so we have to bypass it.
2404
698
    const bool BypassCXXNewExprEval = isa<CXXNewExpr>(E);
2405
2406
    // This is moving forward when we enter into another context.
2407
698
    const StackFrameContext *CurrentSFC = ExprNode->getStackFrame();
2408
2409
1.19k
    do {
2410
      // If that is satisfied we found our statement as an inlined call.
2411
1.19k
      if (std::optional<CallExitEnd> CEE =
2412
1.19k
              ExprNode->getLocationAs<CallExitEnd>())
2413
357
        if (CEE->getCalleeContext()->getCallSite() == E)
2414
321
          break;
2415
2416
      // Try to move forward to the end of the call-chain.
2417
871
      ExprNode = ExprNode->getFirstPred();
2418
871
      if (!ExprNode)
2419
35
        break;
2420
2421
836
      const StackFrameContext *PredSFC = ExprNode->getStackFrame();
2422
2423
      // If that is satisfied we found our statement.
2424
      // FIXME: This code currently bypasses the call site for the
2425
      //        conservatively evaluated allocator.
2426
836
      if (!BypassCXXNewExprEval)
2427
342
        if (std::optional<StmtPoint> SP = ExprNode->getLocationAs<StmtPoint>())
2428
          // See if we do not enter into another context.
2429
342
          if (SP->getStmt() == E && CurrentSFC == PredSFC)
2430
342
            break;
2431
2432
494
      CurrentSFC = PredSFC;
2433
494
    } while (ExprNode->getStackFrame() == CurrentSFC);
2434
2435
    // Next, step over any post-statement checks.
2436
807
    while (ExprNode && 
ExprNode->getLocation().getAs<PostStmt>()772
)
2437
109
      ExprNode = ExprNode->getFirstPred();
2438
698
    if (!ExprNode)
2439
35
      return {};
2440
2441
    // Finally, see if we inlined the call.
2442
663
    std::optional<CallExitEnd> CEE = ExprNode->getLocationAs<CallExitEnd>();
2443
663
    if (!CEE)
2444
342
      return {};
2445
2446
321
    const StackFrameContext *CalleeContext = CEE->getCalleeContext();
2447
321
    if (CalleeContext->getCallSite() != E)
2448
0
      return {};
2449
2450
    // Check the return value.
2451
321
    ProgramStateRef State = ExprNode->getState();
2452
321
    SVal RetVal = ExprNode->getSVal(E);
2453
2454
    // Handle cases where a reference is returned and then immediately used.
2455
321
    if (cast<Expr>(E)->isGLValue())
2456
24
      if (std::optional<Loc> LValue = RetVal.getAs<Loc>())
2457
24
        RetVal = State->getSVal(*LValue);
2458
2459
    // See if the return value is NULL. If so, suppress the report.
2460
321
    AnalyzerOptions &Options = State->getAnalysisManager().options;
2461
2462
321
    bool EnableNullFPSuppression = false;
2463
321
    if (Opts.EnableNullFPSuppression && 
Options.ShouldSuppressNullReturnPaths260
)
2464
194
      if (std::optional<Loc> RetLoc = RetVal.getAs<Loc>())
2465
122
        EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
2466
2467
321
    PathSensitiveBugReport &Report = getParentTracker().getReport();
2468
321
    Report.addVisitor<ReturnVisitor>(&getParentTracker(), CalleeContext,
2469
321
                                     EnableNullFPSuppression, Options,
2470
321
                                     Opts.Kind);
2471
321
    return {true};
2472
321
  }
2473
};
2474
2475
class DefaultExpressionHandler final : public ExpressionHandler {
2476
public:
2477
  using ExpressionHandler::ExpressionHandler;
2478
2479
  Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
2480
                         const ExplodedNode *LVNode,
2481
2.71k
                         TrackingOptions Opts) override {
2482
2.71k
    ProgramStateRef LVState = LVNode->getState();
2483
2.71k
    const StackFrameContext *SFC = LVNode->getStackFrame();
2484
2.71k
    PathSensitiveBugReport &Report = getParentTracker().getReport();
2485
2.71k
    Tracker::Result Result;
2486
2487
    // If the expression is not an "lvalue expression", we can still
2488
    // track the constraints on its contents.
2489
2.71k
    SVal V = LVState->getSValAsScalarOrLoc(Inner, LVNode->getLocationContext());
2490
2491
    // Is it a symbolic value?
2492
2.71k
    if (auto L = V.getAs<loc::MemRegionVal>()) {
2493
      // FIXME: this is a hack for fixing a later crash when attempting to
2494
      // dereference a void* pointer.
2495
      // We should not try to dereference pointers at all when we don't care
2496
      // what is written inside the pointer.
2497
311
      bool CanDereference = true;
2498
311
      if (const auto *SR = L->getRegionAs<SymbolicRegion>()) {
2499
226
        if (SR->getPointeeStaticType()->isVoidType())
2500
9
          CanDereference = false;
2501
226
      } else 
if (85
L->getRegionAs<AllocaRegion>()85
)
2502
1
        CanDereference = false;
2503
2504
      // At this point we are dealing with the region's LValue.
2505
      // However, if the rvalue is a symbolic region, we should track it as
2506
      // well. Try to use the correct type when looking up the value.
2507
311
      SVal RVal;
2508
311
      if (ExplodedGraph::isInterestingLValueExpr(Inner))
2509
0
        RVal = LVState->getRawSVal(*L, Inner->getType());
2510
311
      else if (CanDereference)
2511
301
        RVal = LVState->getSVal(L->getRegion());
2512
2513
311
      if (CanDereference) {
2514
301
        Report.addVisitor<UndefOrNullArgVisitor>(L->getRegion());
2515
301
        Result.FoundSomethingToTrack = true;
2516
2517
301
        if (auto KV = RVal.getAs<KnownSVal>())
2518
157
          Result.combineWith(
2519
157
              getParentTracker().track(*KV, L->getRegion(), Opts, SFC));
2520
301
      }
2521
2522
311
      const MemRegion *RegionRVal = RVal.getAsRegion();
2523
311
      if (isa_and_nonnull<SymbolicRegion>(RegionRVal)) {
2524
21
        Report.markInteresting(RegionRVal, Opts.Kind);
2525
21
        Report.addVisitor<TrackConstraintBRVisitor>(
2526
21
            loc::MemRegionVal(RegionRVal),
2527
21
            /*Assumption=*/false, "Assuming pointer value is null");
2528
21
        Result.FoundSomethingToTrack = true;
2529
21
      }
2530
311
    }
2531
2532
2.71k
    return Result;
2533
2.71k
  }
2534
};
2535
2536
/// Attempts to add visitors to track an RValue expression back to its point of
2537
/// origin.
2538
class PRValueHandler final : public ExpressionHandler {
2539
public:
2540
  using ExpressionHandler::ExpressionHandler;
2541
2542
  Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
2543
                         const ExplodedNode *ExprNode,
2544
2.71k
                         TrackingOptions Opts) override {
2545
2.71k
    if (!E->isPRValue())
2546
103
      return {};
2547
2548
2.61k
    const ExplodedNode *RVNode = findNodeForExpression(ExprNode, E);
2549
2.61k
    if (!RVNode)
2550
0
      return {};
2551
2552
2.61k
    Tracker::Result CombinedResult;
2553
2.61k
    Tracker &Parent = getParentTracker();
2554
2555
2.61k
    const auto track = [&CombinedResult, &Parent, ExprNode,
2556
2.61k
                        Opts](const Expr *Inner) {
2557
28
      CombinedResult.combineWith(Parent.track(Inner, ExprNode, Opts));
2558
28
    };
2559
2560
    // FIXME: Initializer lists can appear in many different contexts
2561
    // and most of them needs a special handling. For now let's handle
2562
    // what we can. If the initializer list only has 1 element, we track
2563
    // that.
2564
    // This snippet even handles nesting, e.g.: int *x{{{{{y}}}}};
2565
2.61k
    if (const auto *ILE = dyn_cast<InitListExpr>(E)) {
2566
23
      if (ILE->getNumInits() == 1) {
2567
14
        track(ILE->getInit(0));
2568
2569
14
        return CombinedResult;
2570
14
      }
2571
2572
9
      return {};
2573
23
    }
2574
2575
2.58k
    ProgramStateRef RVState = RVNode->getState();
2576
2.58k
    SVal V = RVState->getSValAsScalarOrLoc(E, RVNode->getLocationContext());
2577
2.58k
    const auto *BO = dyn_cast<BinaryOperator>(E);
2578
2579
2.58k
    if (!BO || 
!BO->isMultiplicativeOp()463
||
!V.isZeroConstant()15
)
2580
2.57k
      return {};
2581
2582
13
    SVal RHSV = RVState->getSVal(BO->getRHS(), RVNode->getLocationContext());
2583
13
    SVal LHSV = RVState->getSVal(BO->getLHS(), RVNode->getLocationContext());
2584
2585
    // Track both LHS and RHS of a multiplication.
2586
13
    if (BO->getOpcode() == BO_Mul) {
2587
11
      if (LHSV.isZeroConstant())
2588
6
        track(BO->getLHS());
2589
11
      if (RHSV.isZeroConstant())
2590
6
        track(BO->getRHS());
2591
11
    } else { // Track only the LHS of a division or a modulo.
2592
2
      if (LHSV.isZeroConstant())
2593
2
        track(BO->getLHS());
2594
2
    }
2595
2596
13
    return CombinedResult;
2597
2.58k
  }
2598
};
2599
} // namespace
2600
2601
2.93k
Tracker::Tracker(PathSensitiveBugReport &Report) : Report(Report) {
2602
  // Default expression handlers.
2603
2.93k
  addLowPriorityHandler<ControlDependencyHandler>();
2604
2.93k
  addLowPriorityHandler<NilReceiverHandler>();
2605
2.93k
  addLowPriorityHandler<ArrayIndexHandler>();
2606
2.93k
  addLowPriorityHandler<InterestingLValueHandler>();
2607
2.93k
  addLowPriorityHandler<InlinedFunctionCallHandler>();
2608
2.93k
  addLowPriorityHandler<DefaultExpressionHandler>();
2609
2.93k
  addLowPriorityHandler<PRValueHandler>();
2610
  // Default store handlers.
2611
2.93k
  addHighPriorityHandler<DefaultStoreHandler>();
2612
2.93k
}
2613
2614
Tracker::Result Tracker::track(const Expr *E, const ExplodedNode *N,
2615
5.85k
                               TrackingOptions Opts) {
2616
5.85k
  if (!E || !N)
2617
0
    return {};
2618
2619
5.85k
  const Expr *Inner = peelOffOuterExpr(E, N);
2620
5.85k
  const ExplodedNode *LVNode = findNodeForExpression(N, Inner);
2621
5.85k
  if (!LVNode)
2622
62
    return {};
2623
2624
5.79k
  Result CombinedResult;
2625
  // Iterate through the handlers in the order according to their priorities.
2626
31.3k
  for (ExpressionHandlerPtr &Handler : ExpressionHandlers) {
2627
31.3k
    CombinedResult.combineWith(Handler->handle(Inner, N, LVNode, Opts));
2628
31.3k
    if (CombinedResult.WasInterrupted) {
2629
      // There is no need to confuse our users here.
2630
      // We got interrupted, but our users don't need to know about it.
2631
3.08k
      CombinedResult.WasInterrupted = false;
2632
3.08k
      break;
2633
3.08k
    }
2634
31.3k
  }
2635
2636
5.79k
  return CombinedResult;
2637
5.85k
}
2638
2639
Tracker::Result Tracker::track(SVal V, const MemRegion *R, TrackingOptions Opts,
2640
3.34k
                               const StackFrameContext *Origin) {
2641
3.34k
  if (auto KV = V.getAs<KnownSVal>()) {
2642
3.34k
    Report.addVisitor<StoreSiteFinder>(this, *KV, R, Opts, Origin);
2643
3.34k
    return {true};
2644
3.34k
  }
2645
1
  return {};
2646
3.34k
}
2647
2648
PathDiagnosticPieceRef Tracker::handle(StoreInfo SI, BugReporterContext &BRC,
2649
2.13k
                                       TrackingOptions Opts) {
2650
  // Iterate through the handlers in the order according to their priorities.
2651
2.13k
  for (StoreHandlerPtr &Handler : StoreHandlers) {
2652
2.13k
    if (PathDiagnosticPieceRef Result = Handler->handle(SI, BRC, Opts))
2653
      // If the handler produced a non-null piece, return it.
2654
      // There is no need in asking other handlers.
2655
2.13k
      return Result;
2656
2.13k
  }
2657
1
  return {};
2658
2.13k
}
2659
2660
bool bugreporter::trackExpressionValue(const ExplodedNode *InputNode,
2661
                                       const Expr *E,
2662
2663
                                       PathSensitiveBugReport &Report,
2664
2.90k
                                       TrackingOptions Opts) {
2665
2.90k
  return Tracker::create(Report)
2666
2.90k
      ->track(E, InputNode, Opts)
2667
2.90k
      .FoundSomethingToTrack;
2668
2.90k
}
2669
2670
void bugreporter::trackStoredValue(KnownSVal V, const MemRegion *R,
2671
                                   PathSensitiveBugReport &Report,
2672
                                   TrackingOptions Opts,
2673
25
                                   const StackFrameContext *Origin) {
2674
25
  Tracker::create(Report)->track(V, R, Opts, Origin);
2675
25
}
2676
2677
//===----------------------------------------------------------------------===//
2678
// Implementation of NulReceiverBRVisitor.
2679
//===----------------------------------------------------------------------===//
2680
2681
const Expr *NilReceiverBRVisitor::getNilReceiver(const Stmt *S,
2682
51.9k
                                                 const ExplodedNode *N) {
2683
51.9k
  const auto *ME = dyn_cast<ObjCMessageExpr>(S);
2684
51.9k
  if (!ME)
2685
51.6k
    return nullptr;
2686
285
  if (const Expr *Receiver = ME->getInstanceReceiver()) {
2687
210
    ProgramStateRef state = N->getState();
2688
210
    SVal V = N->getSVal(Receiver);
2689
210
    if (state->isNull(V).isConstrainedTrue())
2690
89
      return Receiver;
2691
210
  }
2692
196
  return nullptr;
2693
285
}
2694
2695
PathDiagnosticPieceRef
2696
NilReceiverBRVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
2697
3.37M
                                PathSensitiveBugReport &BR) {
2698
3.37M
  std::optional<PreStmt> P = N->getLocationAs<PreStmt>();
2699
3.37M
  if (!P)
2700
3.32M
    return nullptr;
2701
2702
46.1k
  const Stmt *S = P->getStmt();
2703
46.1k
  const Expr *Receiver = getNilReceiver(S, N);
2704
46.1k
  if (!Receiver)
2705
46.0k
    return nullptr;
2706
2707
48
  llvm::SmallString<256> Buf;
2708
48
  llvm::raw_svector_ostream OS(Buf);
2709
2710
48
  if (const auto *ME = dyn_cast<ObjCMessageExpr>(S)) {
2711
48
    OS << "'";
2712
48
    ME->getSelector().print(OS);
2713
48
    OS << "' not called";
2714
48
  }
2715
0
  else {
2716
0
    OS << "No method is called";
2717
0
  }
2718
48
  OS << " because the receiver is nil";
2719
2720
  // The receiver was nil, and hence the method was skipped.
2721
  // Register a BugReporterVisitor to issue a message telling us how
2722
  // the receiver was null.
2723
48
  bugreporter::trackExpressionValue(N, Receiver, BR,
2724
48
                                    {bugreporter::TrackingKind::Thorough,
2725
48
                                     /*EnableNullFPSuppression*/ false});
2726
  // Issue a message saying that the method was skipped.
2727
48
  PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
2728
48
                                     N->getLocationContext());
2729
48
  return std::make_shared<PathDiagnosticEventPiece>(L, OS.str());
2730
46.1k
}
2731
2732
//===----------------------------------------------------------------------===//
2733
// Visitor that tries to report interesting diagnostics from conditions.
2734
//===----------------------------------------------------------------------===//
2735
2736
/// Return the tag associated with this visitor.  This tag will be used
2737
/// to make all PathDiagnosticPieces created by this visitor.
2738
12.0k
const char *ConditionBRVisitor::getTag() { return "ConditionBRVisitor"; }
2739
2740
PathDiagnosticPieceRef
2741
ConditionBRVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
2742
3.37M
                              PathSensitiveBugReport &BR) {
2743
3.37M
  auto piece = VisitNodeImpl(N, BRC, BR);
2744
3.37M
  if (piece) {
2745
10.4k
    piece->setTag(getTag());
2746
10.4k
    if (auto *ev = dyn_cast<PathDiagnosticEventPiece>(piece.get()))
2747
8.22k
      ev->setPrunable(true, /* override */ false);
2748
10.4k
  }
2749
3.37M
  return piece;
2750
3.37M
}
2751
2752
PathDiagnosticPieceRef
2753
ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N,
2754
                                  BugReporterContext &BRC,
2755
3.37M
                                  PathSensitiveBugReport &BR) {
2756
3.37M
  ProgramPoint ProgPoint = N->getLocation();
2757
3.37M
  const std::pair<const ProgramPointTag *, const ProgramPointTag *> &Tags =
2758
3.37M
      ExprEngine::geteagerlyAssumeBinOpBifurcationTags();
2759
2760
  // If an assumption was made on a branch, it should be caught
2761
  // here by looking at the state transition.
2762
3.37M
  if (std::optional<BlockEdge> BE = ProgPoint.getAs<BlockEdge>()) {
2763
92.0k
    const CFGBlock *SrcBlock = BE->getSrc();
2764
92.0k
    if (const Stmt *Term = SrcBlock->getTerminatorStmt()) {
2765
      // If the tag of the previous node is 'Eagerly Assume...' the current
2766
      // 'BlockEdge' has the same constraint information. We do not want to
2767
      // report the value as it is just an assumption on the predecessor node
2768
      // which will be caught in the next VisitNode() iteration as a 'PostStmt'.
2769
12.4k
      const ProgramPointTag *PreviousNodeTag =
2770
12.4k
          N->getFirstPred()->getLocation().getTag();
2771
12.4k
      if (PreviousNodeTag == Tags.first || 
PreviousNodeTag == Tags.second11.8k
)
2772
1.30k
        return nullptr;
2773
2774
11.1k
      return VisitTerminator(Term, N, SrcBlock, BE->getDst(), BR, BRC);
2775
12.4k
    }
2776
79.5k
    return nullptr;
2777
92.0k
  }
2778
2779
3.28M
  if (std::optional<PostStmt> PS = ProgPoint.getAs<PostStmt>()) {
2780
2.52M
    const ProgramPointTag *CurrentNodeTag = PS->getTag();
2781
2.52M
    if (CurrentNodeTag != Tags.first && 
CurrentNodeTag != Tags.second2.51M
)
2782
2.51M
      return nullptr;
2783
2784
3.94k
    bool TookTrue = CurrentNodeTag == Tags.first;
2785
3.94k
    return VisitTrueTest(cast<Expr>(PS->getStmt()), BRC, BR, N, TookTrue);
2786
2.52M
  }
2787
2788
763k
  return nullptr;
2789
3.28M
}
2790
2791
PathDiagnosticPieceRef ConditionBRVisitor::VisitTerminator(
2792
    const Stmt *Term, const ExplodedNode *N, const CFGBlock *srcBlk,
2793
    const CFGBlock *dstBlk, PathSensitiveBugReport &R,
2794
11.1k
    BugReporterContext &BRC) {
2795
11.1k
  const Expr *Cond = nullptr;
2796
2797
  // In the code below, Term is a CFG terminator and Cond is a branch condition
2798
  // expression upon which the decision is made on this terminator.
2799
  //
2800
  // For example, in "if (x == 0)", the "if (x == 0)" statement is a terminator,
2801
  // and "x == 0" is the respective condition.
2802
  //
2803
  // Another example: in "if (x && y)", we've got two terminators and two
2804
  // conditions due to short-circuit nature of operator "&&":
2805
  // 1. The "if (x && y)" statement is a terminator,
2806
  //    and "y" is the respective condition.
2807
  // 2. Also "x && ..." is another terminator,
2808
  //    and "x" is its condition.
2809
2810
11.1k
  switch (Term->getStmtClass()) {
2811
  // FIXME: Stmt::SwitchStmtClass is worth handling, however it is a bit
2812
  // more tricky because there are more than two branches to account for.
2813
2.86k
  default:
2814
2.86k
    return nullptr;
2815
4.13k
  case Stmt::IfStmtClass:
2816
4.13k
    Cond = cast<IfStmt>(Term)->getCond();
2817
4.13k
    break;
2818
1.75k
  case Stmt::ConditionalOperatorClass:
2819
1.75k
    Cond = cast<ConditionalOperator>(Term)->getCond();
2820
1.75k
    break;
2821
2.37k
  case Stmt::BinaryOperatorClass:
2822
    // When we encounter a logical operator (&& or ||) as a CFG terminator,
2823
    // then the condition is actually its LHS; otherwise, we'd encounter
2824
    // the parent, such as if-statement, as a terminator.
2825
2.37k
    const auto *BO = cast<BinaryOperator>(Term);
2826
2.37k
    assert(BO->isLogicalOp() &&
2827
2.37k
           "CFG terminator is not a short-circuit operator!");
2828
2.37k
    Cond = BO->getLHS();
2829
2.37k
    break;
2830
11.1k
  }
2831
2832
8.26k
  Cond = Cond->IgnoreParens();
2833
2834
  // However, when we encounter a logical operator as a branch condition,
2835
  // then the condition is actually its RHS, because LHS would be
2836
  // the condition for the logical operator terminator.
2837
9.74k
  while (const auto *InnerBO = dyn_cast<BinaryOperator>(Cond)) {
2838
6.66k
    if (!InnerBO->isLogicalOp())
2839
5.19k
      break;
2840
1.47k
    Cond = InnerBO->getRHS()->IgnoreParens();
2841
1.47k
  }
2842
2843
8.26k
  assert(Cond);
2844
8.26k
  assert(srcBlk->succ_size() == 2);
2845
8.26k
  const bool TookTrue = *(srcBlk->succ_begin()) == dstBlk;
2846
8.26k
  return VisitTrueTest(Cond, BRC, R, N, TookTrue);
2847
8.26k
}
2848
2849
PathDiagnosticPieceRef
2850
ConditionBRVisitor::VisitTrueTest(const Expr *Cond, BugReporterContext &BRC,
2851
                                  PathSensitiveBugReport &R,
2852
12.2k
                                  const ExplodedNode *N, bool TookTrue) {
2853
12.2k
  ProgramStateRef CurrentState = N->getState();
2854
12.2k
  ProgramStateRef PrevState = N->getFirstPred()->getState();
2855
12.2k
  const LocationContext *LCtx = N->getLocationContext();
2856
2857
  // If the constraint information is changed between the current and the
2858
  // previous program state we assuming the newly seen constraint information.
2859
  // If we cannot evaluate the condition (and the constraints are the same)
2860
  // the analyzer has no information about the value and just assuming it.
2861
12.2k
  bool IsAssuming =
2862
12.2k
      !BRC.getStateManager().haveEqualConstraints(CurrentState, PrevState) ||
2863
12.2k
      
CurrentState->getSVal(Cond, LCtx).isUnknownOrUndef()4.04k
;
2864
2865
  // These will be modified in code below, but we need to preserve the original
2866
  //  values in case we want to throw the generic message.
2867
12.2k
  const Expr *CondTmp = Cond;
2868
12.2k
  bool TookTrueTmp = TookTrue;
2869
2870
12.8k
  while (true) {
2871
12.8k
    CondTmp = CondTmp->IgnoreParenCasts();
2872
12.8k
    switch (CondTmp->getStmtClass()) {
2873
1.21k
      default:
2874
1.21k
        break;
2875
9.07k
      case Stmt::BinaryOperatorClass:
2876
9.07k
        if (auto P = VisitTrueTest(Cond, cast<BinaryOperator>(CondTmp),
2877
9.07k
                                   BRC, R, N, TookTrueTmp, IsAssuming))
2878
4.61k
          return P;
2879
4.45k
        break;
2880
4.45k
      case Stmt::DeclRefExprClass:
2881
1.75k
        if (auto P = VisitTrueTest(Cond, cast<DeclRefExpr>(CondTmp),
2882
1.75k
                                   BRC, R, N, TookTrueTmp, IsAssuming))
2883
1.73k
          return P;
2884
12
        break;
2885
156
      case Stmt::MemberExprClass:
2886
156
        if (auto P = VisitTrueTest(Cond, cast<MemberExpr>(CondTmp),
2887
156
                                   BRC, R, N, TookTrueTmp, IsAssuming))
2888
113
          return P;
2889
43
        break;
2890
640
      case Stmt::UnaryOperatorClass: {
2891
640
        const auto *UO = cast<UnaryOperator>(CondTmp);
2892
640
        if (UO->getOpcode() == UO_LNot) {
2893
626
          TookTrueTmp = !TookTrueTmp;
2894
626
          CondTmp = UO->getSubExpr();
2895
626
          continue;
2896
626
        }
2897
14
        break;
2898
640
      }
2899
12.8k
    }
2900
5.74k
    break;
2901
12.8k
  }
2902
2903
  // Condition too complex to explain? Just say something so that the user
2904
  // knew we've made some path decision at this point.
2905
  // If it is too complex and we know the evaluation of the condition do not
2906
  // repeat the note from 'BugReporter.cpp'
2907
5.74k
  if (!IsAssuming)
2908
1.75k
    return nullptr;
2909
2910
3.98k
  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
2911
3.98k
  if (!Loc.isValid() || !Loc.asLocation().isValid())
2912
4
    return nullptr;
2913
2914
3.97k
  return std::make_shared<PathDiagnosticEventPiece>(
2915
3.97k
      Loc, TookTrue ? 
GenericTrueMessage3.17k
:
GenericFalseMessage809
);
2916
3.98k
}
2917
2918
bool ConditionBRVisitor::patternMatch(const Expr *Ex, const Expr *ParentEx,
2919
                                      raw_ostream &Out, BugReporterContext &BRC,
2920
                                      PathSensitiveBugReport &report,
2921
                                      const ExplodedNode *N,
2922
                                      std::optional<bool> &prunable,
2923
18.1k
                                      bool IsSameFieldName) {
2924
18.1k
  const Expr *OriginalExpr = Ex;
2925
18.1k
  Ex = Ex->IgnoreParenCasts();
2926
2927
18.1k
  if (isa<GNUNullExpr, ObjCBoolLiteralExpr, CXXBoolLiteralExpr, IntegerLiteral,
2928
18.1k
          FloatingLiteral>(Ex)) {
2929
    // Use heuristics to determine if the expression is a macro
2930
    // expanding to a literal and if so, use the macro's name.
2931
4.31k
    SourceLocation BeginLoc = OriginalExpr->getBeginLoc();
2932
4.31k
    SourceLocation EndLoc = OriginalExpr->getEndLoc();
2933
4.31k
    if (BeginLoc.isMacroID() && 
EndLoc.isMacroID()838
) {
2934
838
      const SourceManager &SM = BRC.getSourceManager();
2935
838
      const LangOptions &LO = BRC.getASTContext().getLangOpts();
2936
838
      if (Lexer::isAtStartOfMacroExpansion(BeginLoc, SM, LO) &&
2937
838
          
Lexer::isAtEndOfMacroExpansion(EndLoc, SM, LO)211
) {
2938
211
        CharSourceRange R = Lexer::getAsCharRange({BeginLoc, EndLoc}, SM, LO);
2939
211
        Out << Lexer::getSourceText(R, SM, LO);
2940
211
        return false;
2941
211
      }
2942
838
    }
2943
4.31k
  }
2944
2945
17.9k
  if (const auto *DR = dyn_cast<DeclRefExpr>(Ex)) {
2946
8.27k
    const bool quotes = isa<VarDecl>(DR->getDecl());
2947
8.27k
    if (quotes) {
2948
8.25k
      Out << '\'';
2949
8.25k
      const LocationContext *LCtx = N->getLocationContext();
2950
8.25k
      const ProgramState *state = N->getState().get();
2951
8.25k
      if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()),
2952
8.25k
                                                LCtx).getAsRegion()) {
2953
8.25k
        if (report.isInteresting(R))
2954
0
          prunable = false;
2955
8.25k
        else {
2956
8.25k
          const ProgramState *state = N->getState().get();
2957
8.25k
          SVal V = state->getSVal(R);
2958
8.25k
          if (report.isInteresting(V))
2959
248
            prunable = false;
2960
8.25k
        }
2961
8.25k
      }
2962
8.25k
    }
2963
8.27k
    Out << DR->getDecl()->getDeclName().getAsString();
2964
8.27k
    if (quotes)
2965
8.25k
      Out << '\'';
2966
8.27k
    return quotes;
2967
8.27k
  }
2968
2969
9.66k
  if (const auto *IL = dyn_cast<IntegerLiteral>(Ex)) {
2970
3.83k
    QualType OriginalTy = OriginalExpr->getType();
2971
3.83k
    if (OriginalTy->isPointerType()) {
2972
150
      if (IL->getValue() == 0) {
2973
149
        Out << "null";
2974
149
        return false;
2975
149
      }
2976
150
    }
2977
3.68k
    else if (OriginalTy->isObjCObjectPointerType()) {
2978
15
      if (IL->getValue() == 0) {
2979
15
        Out << "nil";
2980
15
        return false;
2981
15
      }
2982
15
    }
2983
2984
3.66k
    Out << IL->getValue();
2985
3.66k
    return false;
2986
3.83k
  }
2987
2988
5.83k
  if (const auto *ME = dyn_cast<MemberExpr>(Ex)) {
2989
321
    if (!IsSameFieldName)
2990
281
      Out << "field '" << ME->getMemberDecl()->getName() << '\'';
2991
40
    else
2992
40
      Out << '\''
2993
40
          << Lexer::getSourceText(
2994
40
                 CharSourceRange::getTokenRange(Ex->getSourceRange()),
2995
40
                 BRC.getSourceManager(), BRC.getASTContext().getLangOpts(),
2996
40
                 nullptr)
2997
40
          << '\'';
2998
321
  }
2999
3000
5.83k
  return false;
3001
9.66k
}
3002
3003
PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest(
3004
    const Expr *Cond, const BinaryOperator *BExpr, BugReporterContext &BRC,
3005
    PathSensitiveBugReport &R, const ExplodedNode *N, bool TookTrue,
3006
9.07k
    bool IsAssuming) {
3007
9.07k
  bool shouldInvert = false;
3008
9.07k
  std::optional<bool> shouldPrune;
3009
3010
  // Check if the field name of the MemberExprs is ambiguous. Example:
3011
  // " 'a.d' is equal to 'h.d' " in 'test/Analysis/null-deref-path-notes.cpp'.
3012
9.07k
  bool IsSameFieldName = false;
3013
9.07k
  const auto *LhsME = dyn_cast<MemberExpr>(BExpr->getLHS()->IgnoreParenCasts());
3014
9.07k
  const auto *RhsME = dyn_cast<MemberExpr>(BExpr->getRHS()->IgnoreParenCasts());
3015
3016
9.07k
  if (LhsME && 
RhsME301
)
3017
20
    IsSameFieldName =
3018
20
        LhsME->getMemberDecl()->getName() == RhsME->getMemberDecl()->getName();
3019
3020
9.07k
  SmallString<128> LhsString, RhsString;
3021
9.07k
  {
3022
9.07k
    llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
3023
9.07k
    const bool isVarLHS = patternMatch(BExpr->getLHS(), BExpr, OutLHS, BRC, R,
3024
9.07k
                                       N, shouldPrune, IsSameFieldName);
3025
9.07k
    const bool isVarRHS = patternMatch(BExpr->getRHS(), BExpr, OutRHS, BRC, R,
3026
9.07k
                                       N, shouldPrune, IsSameFieldName);
3027
3028
9.07k
    shouldInvert = !isVarLHS && 
isVarRHS3.18k
;
3029
9.07k
  }
3030
3031
9.07k
  BinaryOperator::Opcode Op = BExpr->getOpcode();
3032
3033
9.07k
  if (BinaryOperator::isAssignmentOp(Op)) {
3034
    // For assignment operators, all that we care about is that the LHS
3035
    // evaluates to "true" or "false".
3036
13
    return VisitConditionVariable(LhsString, BExpr->getLHS(), BRC, R, N,
3037
13
                                  TookTrue);
3038
13
  }
3039
3040
  // For non-assignment operations, we require that we can understand
3041
  // both the LHS and RHS.
3042
9.06k
  if (LhsString.empty() || 
RhsString.empty()6.42k
||
3043
9.06k
      
!BinaryOperator::isComparisonOp(Op)4.61k
||
Op == BO_Cmp4.60k
)
3044
4.45k
    return nullptr;
3045
3046
  // Should we invert the strings if the LHS is not a variable name?
3047
4.60k
  SmallString<256> buf;
3048
4.60k
  llvm::raw_svector_ostream Out(buf);
3049
4.60k
  Out << (IsAssuming ? 
"Assuming "3.23k
:
""1.36k
)
3050
4.60k
      << (shouldInvert ? 
RhsString39
:
LhsString4.56k
) << " is ";
3051
3052
  // Do we need to invert the opcode?
3053
4.60k
  if (shouldInvert)
3054
39
    switch (Op) {
3055
9
      default: break;
3056
9
      
case BO_LT: Op = BO_GT; break6
;
3057
0
      case BO_GT: Op = BO_LT; break;
3058
24
      case BO_LE: Op = BO_GE; break;
3059
0
      case BO_GE: Op = BO_LE; break;
3060
39
    }
3061
3062
4.60k
  if (!TookTrue)
3063
2.34k
    switch (Op) {
3064
698
      case BO_EQ: Op = BO_NE; break;
3065
444
      case BO_NE: Op = BO_EQ; break;
3066
420
      case BO_LT: Op = BO_GE; break;
3067
431
      case BO_GT: Op = BO_LE; break;
3068
142
      case BO_LE: Op = BO_GT; break;
3069
207
      case BO_GE: Op = BO_LT; break;
3070
0
      default:
3071
0
        return nullptr;
3072
2.34k
    }
3073
3074
4.60k
  switch (Op) {
3075
1.13k
    case BO_EQ:
3076
1.13k
      Out << "equal to ";
3077
1.13k
      break;
3078
1.08k
    case BO_NE:
3079
1.08k
      Out << "not equal to ";
3080
1.08k
      break;
3081
2.38k
    default:
3082
2.38k
      Out << BinaryOperator::getOpcodeStr(Op) << ' ';
3083
2.38k
      break;
3084
4.60k
  }
3085
3086
4.60k
  Out << (shouldInvert ? 
LhsString39
:
RhsString4.56k
);
3087
4.60k
  const LocationContext *LCtx = N->getLocationContext();
3088
4.60k
  const SourceManager &SM = BRC.getSourceManager();
3089
3090
4.60k
  if (isVarAnInterestingCondition(BExpr->getLHS(), N, &R) ||
3091
4.60k
      
isVarAnInterestingCondition(BExpr->getRHS(), N, &R)4.59k
)
3092
4
    Out << WillBeUsedForACondition;
3093
3094
  // Convert 'field ...' to 'Field ...' if it is a MemberExpr.
3095
4.60k
  std::string Message = std::string(Out.str());
3096
4.60k
  Message[0] = toupper(Message[0]);
3097
3098
  // If we know the value create a pop-up note to the value part of 'BExpr'.
3099
4.60k
  if (!IsAssuming) {
3100
1.36k
    PathDiagnosticLocation Loc;
3101
1.36k
    if (!shouldInvert) {
3102
1.33k
      if (LhsME && 
LhsME->getMemberLoc().isValid()87
)
3103
87
        Loc = PathDiagnosticLocation(LhsME->getMemberLoc(), SM);
3104
1.24k
      else
3105
1.24k
        Loc = PathDiagnosticLocation(BExpr->getLHS(), SM, LCtx);
3106
1.33k
    } else {
3107
30
      if (RhsME && 
RhsME->getMemberLoc().isValid()0
)
3108
0
        Loc = PathDiagnosticLocation(RhsME->getMemberLoc(), SM);
3109
30
      else
3110
30
        Loc = PathDiagnosticLocation(BExpr->getRHS(), SM, LCtx);
3111
30
    }
3112
3113
1.36k
    return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Message);
3114
1.36k
  }
3115
3116
3.23k
  PathDiagnosticLocation Loc(Cond, SM, LCtx);
3117
3.23k
  auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Message);
3118
3.23k
  if (shouldPrune)
3119
134
    event->setPrunable(*shouldPrune);
3120
3.23k
  return event;
3121
4.60k
}
3122
3123
PathDiagnosticPieceRef ConditionBRVisitor::VisitConditionVariable(
3124
    StringRef LhsString, const Expr *CondVarExpr, BugReporterContext &BRC,
3125
13
    PathSensitiveBugReport &report, const ExplodedNode *N, bool TookTrue) {
3126
  // FIXME: If there's already a constraint tracker for this variable,
3127
  // we shouldn't emit anything here (c.f. the double note in
3128
  // test/Analysis/inlining/path-notes.c)
3129
13
  SmallString<256> buf;
3130
13
  llvm::raw_svector_ostream Out(buf);
3131
13
  Out << "Assuming " << LhsString << " is ";
3132
3133
13
  if (!printValue(CondVarExpr, Out, N, TookTrue, /*IsAssuming=*/true))
3134
0
    return nullptr;
3135
3136
13
  const LocationContext *LCtx = N->getLocationContext();
3137
13
  PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
3138
3139
13
  if (isVarAnInterestingCondition(CondVarExpr, N, &report))
3140
2
    Out << WillBeUsedForACondition;
3141
3142
13
  auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
3143
3144
13
  if (isInterestingExpr(CondVarExpr, N, &report))
3145
4
    event->setPrunable(false);
3146
3147
13
  return event;
3148
13
}
3149
3150
PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest(
3151
    const Expr *Cond, const DeclRefExpr *DRE, BugReporterContext &BRC,
3152
    PathSensitiveBugReport &report, const ExplodedNode *N, bool TookTrue,
3153
1.75k
    bool IsAssuming) {
3154
1.75k
  const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
3155
1.75k
  if (!VD)
3156
4
    return nullptr;
3157
3158
1.74k
  SmallString<256> Buf;
3159
1.74k
  llvm::raw_svector_ostream Out(Buf);
3160
3161
1.74k
  Out << (IsAssuming ? 
"Assuming '"960
:
"'"787
) << VD->getDeclName() << "' is ";
3162
3163
1.74k
  if (!printValue(DRE, Out, N, TookTrue, IsAssuming))
3164
8
    return nullptr;
3165
3166
1.73k
  const LocationContext *LCtx = N->getLocationContext();
3167
3168
1.73k
  if (isVarAnInterestingCondition(DRE, N, &report))
3169
15
    Out << WillBeUsedForACondition;
3170
3171
  // If we know the value create a pop-up note to the 'DRE'.
3172
1.73k
  if (!IsAssuming) {
3173
785
    PathDiagnosticLocation Loc(DRE, BRC.getSourceManager(), LCtx);
3174
785
    return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Out.str());
3175
785
  }
3176
3177
954
  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
3178
954
  auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
3179
3180
954
  if (isInterestingExpr(DRE, N, &report))
3181
377
    event->setPrunable(false);
3182
3183
954
  return std::move(event);
3184
1.73k
}
3185
3186
PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest(
3187
    const Expr *Cond, const MemberExpr *ME, BugReporterContext &BRC,
3188
    PathSensitiveBugReport &report, const ExplodedNode *N, bool TookTrue,
3189
156
    bool IsAssuming) {
3190
156
  SmallString<256> Buf;
3191
156
  llvm::raw_svector_ostream Out(Buf);
3192
3193
156
  Out << (IsAssuming ? 
"Assuming field '"43
:
"Field '"113
)
3194
156
      << ME->getMemberDecl()->getName() << "' is ";
3195
3196
156
  if (!printValue(ME, Out, N, TookTrue, IsAssuming))
3197
0
    return nullptr;
3198
3199
156
  const LocationContext *LCtx = N->getLocationContext();
3200
156
  PathDiagnosticLocation Loc;
3201
3202
  // If we know the value create a pop-up note to the member of the MemberExpr.
3203
156
  if (!IsAssuming && 
ME->getMemberLoc().isValid()113
)
3204
70
    Loc = PathDiagnosticLocation(ME->getMemberLoc(), BRC.getSourceManager());
3205
86
  else
3206
86
    Loc = PathDiagnosticLocation(Cond, BRC.getSourceManager(), LCtx);
3207
3208
156
  if (!Loc.isValid() || !Loc.asLocation().isValid())
3209
43
    return nullptr;
3210
3211
113
  if (isVarAnInterestingCondition(ME, N, &report))
3212
2
    Out << WillBeUsedForACondition;
3213
3214
  // If we know the value create a pop-up note.
3215
113
  if (!IsAssuming)
3216
70
    return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Out.str());
3217
3218
43
  auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
3219
43
  if (isInterestingExpr(ME, N, &report))
3220
8
    event->setPrunable(false);
3221
43
  return event;
3222
113
}
3223
3224
bool ConditionBRVisitor::printValue(const Expr *CondVarExpr, raw_ostream &Out,
3225
                                    const ExplodedNode *N, bool TookTrue,
3226
1.91k
                                    bool IsAssuming) {
3227
1.91k
  QualType Ty = CondVarExpr->getType();
3228
3229
1.91k
  if (Ty->isPointerType()) {
3230
746
    Out << (TookTrue ? 
"non-null"352
:
"null"394
);
3231
746
    return true;
3232
746
  }
3233
3234
1.17k
  if (Ty->isObjCObjectPointerType()) {
3235
94
    Out << (TookTrue ? 
"non-nil"48
:
"nil"46
);
3236
94
    return true;
3237
94
  }
3238
3239
1.07k
  if (!Ty->isIntegralOrEnumerationType())
3240
8
    return false;
3241
3242
1.06k
  std::optional<const llvm::APSInt *> IntValue;
3243
1.06k
  if (!IsAssuming)
3244
528
    IntValue = getConcreteIntegerValue(CondVarExpr, N);
3245
3246
1.06k
  if (IsAssuming || 
!IntValue528
) {
3247
894
    if (Ty->isBooleanType())
3248
184
      Out << (TookTrue ? 
"true"101
:
"false"83
);
3249
710
    else
3250
710
      Out << (TookTrue ? 
"not equal to 0"405
:
"0"305
);
3251
894
  } else {
3252
174
    if (Ty->isBooleanType())
3253
28
      Out << ((*IntValue)->getBoolValue() ? 
"true"13
:
"false"15
);
3254
146
    else
3255
146
      Out << **IntValue;
3256
174
  }
3257
3258
1.06k
  return true;
3259
1.07k
}
3260
3261
constexpr llvm::StringLiteral ConditionBRVisitor::GenericTrueMessage;
3262
constexpr llvm::StringLiteral ConditionBRVisitor::GenericFalseMessage;
3263
3264
bool ConditionBRVisitor::isPieceMessageGeneric(
3265
112
    const PathDiagnosticPiece *Piece) {
3266
112
  return Piece->getString() == GenericTrueMessage ||
3267
112
         
Piece->getString() == GenericFalseMessage109
;
3268
112
}
3269
3270
//===----------------------------------------------------------------------===//
3271
// Implementation of LikelyFalsePositiveSuppressionBRVisitor.
3272
//===----------------------------------------------------------------------===//
3273
3274
void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor(
3275
    BugReporterContext &BRC, const ExplodedNode *N,
3276
20.7k
    PathSensitiveBugReport &BR) {
3277
  // Here we suppress false positives coming from system headers. This list is
3278
  // based on known issues.
3279
20.7k
  const AnalyzerOptions &Options = BRC.getAnalyzerOptions();
3280
20.7k
  const Decl *D = N->getLocationContext()->getDecl();
3281
3282
20.7k
  if (AnalysisDeclContext::isInStdNamespace(D)) {
3283
    // Skip reports within the 'std' namespace. Although these can sometimes be
3284
    // the user's fault, we currently don't report them very well, and
3285
    // Note that this will not help for any other data structure libraries, like
3286
    // TR1, Boost, or llvm/ADT.
3287
15
    if (Options.ShouldSuppressFromCXXStandardLibrary) {
3288
14
      BR.markInvalid(getTag(), nullptr);
3289
14
      return;
3290
14
    } else {
3291
      // If the complete 'std' suppression is not enabled, suppress reports
3292
      // from the 'std' namespace that are known to produce false positives.
3293
3294
      // The analyzer issues a false use-after-free when std::list::pop_front
3295
      // or std::list::pop_back are called multiple times because we cannot
3296
      // reason about the internal invariants of the data structure.
3297
1
      if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
3298
0
        const CXXRecordDecl *CD = MD->getParent();
3299
0
        if (CD->getName() == "list") {
3300
0
          BR.markInvalid(getTag(), nullptr);
3301
0
          return;
3302
0
        }
3303
0
      }
3304
3305
      // The analyzer issues a false positive when the constructor of
3306
      // std::__independent_bits_engine from algorithms is used.
3307
1
      if (const auto *MD = dyn_cast<CXXConstructorDecl>(D)) {
3308
0
        const CXXRecordDecl *CD = MD->getParent();
3309
0
        if (CD->getName() == "__independent_bits_engine") {
3310
0
          BR.markInvalid(getTag(), nullptr);
3311
0
          return;
3312
0
        }
3313
0
      }
3314
3315
4
      
for (const LocationContext *LCtx = N->getLocationContext(); 1
LCtx;
3316
3
           LCtx = LCtx->getParent()) {
3317
3
        const auto *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
3318
3
        if (!MD)
3319
3
          continue;
3320
3321
0
        const CXXRecordDecl *CD = MD->getParent();
3322
        // The analyzer issues a false positive on
3323
        //   std::basic_string<uint8_t> v; v.push_back(1);
3324
        // and
3325
        //   std::u16string s; s += u'a';
3326
        // because we cannot reason about the internal invariants of the
3327
        // data structure.
3328
0
        if (CD->getName() == "basic_string") {
3329
0
          BR.markInvalid(getTag(), nullptr);
3330
0
          return;
3331
0
        }
3332
3333
        // The analyzer issues a false positive on
3334
        //    std::shared_ptr<int> p(new int(1)); p = nullptr;
3335
        // because it does not reason properly about temporary destructors.
3336
0
        if (CD->getName() == "shared_ptr") {
3337
0
          BR.markInvalid(getTag(), nullptr);
3338
0
          return;
3339
0
        }
3340
0
      }
3341
1
    }
3342
15
  }
3343
3344
  // Skip reports within the sys/queue.h macros as we do not have the ability to
3345
  // reason about data structure shapes.
3346
20.7k
  const SourceManager &SM = BRC.getSourceManager();
3347
20.7k
  FullSourceLoc Loc = BR.getLocation().asLocation();
3348
21.2k
  while (Loc.isMacroID()) {
3349
523
    Loc = Loc.getSpellingLoc();
3350
523
    if (SM.getFilename(Loc).endswith("sys/queue.h")) {
3351
2
      BR.markInvalid(getTag(), nullptr);
3352
2
      return;
3353
2
    }
3354
523
  }
3355
20.7k
}
3356
3357
//===----------------------------------------------------------------------===//
3358
// Implementation of UndefOrNullArgVisitor.
3359
//===----------------------------------------------------------------------===//
3360
3361
PathDiagnosticPieceRef
3362
UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
3363
129k
                                 PathSensitiveBugReport &BR) {
3364
129k
  ProgramStateRef State = N->getState();
3365
129k
  ProgramPoint ProgLoc = N->getLocation();
3366
3367
  // We are only interested in visiting CallEnter nodes.
3368
129k
  std::optional<CallEnter> CEnter = ProgLoc.getAs<CallEnter>();
3369
129k
  if (!CEnter)
3370
127k
    return nullptr;
3371
3372
  // Check if one of the arguments is the region the visitor is tracking.
3373
1.76k
  CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager();
3374
1.76k
  CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State);
3375
1.76k
  unsigned Idx = 0;
3376
1.76k
  ArrayRef<ParmVarDecl *> parms = Call->parameters();
3377
3378
1.76k
  for (const auto ParamDecl : parms) {
3379
1.11k
    const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion();
3380
1.11k
    ++Idx;
3381
3382
    // Are we tracking the argument or its subregion?
3383
1.11k
    if ( !ArgReg || 
!R->isSubRegionOf(ArgReg->StripCasts())468
)
3384
946
      continue;
3385
3386
    // Check the function parameter type.
3387
165
    assert(ParamDecl && "Formal parameter has no decl?");
3388
165
    QualType T = ParamDecl->getType();
3389
3390
165
    if (!(T->isAnyPointerType() || 
T->isReferenceType()86
)) {
3391
      // Function can only change the value passed in by address.
3392
8
      continue;
3393
8
    }
3394
3395
    // If it is a const pointer value, the function does not intend to
3396
    // change the value.
3397
157
    if (T->getPointeeType().isConstQualified())
3398
21
      continue;
3399
3400
    // Mark the call site (LocationContext) as interesting if the value of the
3401
    // argument is undefined or '0'/'NULL'.
3402
136
    SVal BoundVal = State->getSVal(R);
3403
136
    if (BoundVal.isUndef() || 
BoundVal.isZeroConstant()38
) {
3404
107
      BR.markInteresting(CEnter->getCalleeContext());
3405
107
      return nullptr;
3406
107
    }
3407
136
  }
3408
1.66k
  return nullptr;
3409
1.76k
}
3410
3411
//===----------------------------------------------------------------------===//
3412
// Implementation of FalsePositiveRefutationBRVisitor.
3413
//===----------------------------------------------------------------------===//
3414
3415
FalsePositiveRefutationBRVisitor::FalsePositiveRefutationBRVisitor()
3416
0
    : Constraints(ConstraintMap::Factory().getEmptyMap()) {}
3417
3418
void FalsePositiveRefutationBRVisitor::finalizeVisitor(
3419
    BugReporterContext &BRC, const ExplodedNode *EndPathNode,
3420
0
    PathSensitiveBugReport &BR) {
3421
  // Collect new constraints
3422
0
  addConstraints(EndPathNode, /*OverwriteConstraintsOnExistingSyms=*/true);
3423
3424
  // Create a refutation manager
3425
0
  llvm::SMTSolverRef RefutationSolver = llvm::CreateZ3Solver();
3426
0
  ASTContext &Ctx = BRC.getASTContext();
3427
3428
  // Add constraints to the solver
3429
0
  for (const auto &I : Constraints) {
3430
0
    const SymbolRef Sym = I.first;
3431
0
    auto RangeIt = I.second.begin();
3432
3433
0
    llvm::SMTExprRef SMTConstraints = SMTConv::getRangeExpr(
3434
0
        RefutationSolver, Ctx, Sym, RangeIt->From(), RangeIt->To(),
3435
0
        /*InRange=*/true);
3436
0
    while ((++RangeIt) != I.second.end()) {
3437
0
      SMTConstraints = RefutationSolver->mkOr(
3438
0
          SMTConstraints, SMTConv::getRangeExpr(RefutationSolver, Ctx, Sym,
3439
0
                                                RangeIt->From(), RangeIt->To(),
3440
0
                                                /*InRange=*/true));
3441
0
    }
3442
3443
0
    RefutationSolver->addConstraint(SMTConstraints);
3444
0
  }
3445
3446
  // And check for satisfiability
3447
0
  std::optional<bool> IsSAT = RefutationSolver->check();
3448
0
  if (!IsSAT)
3449
0
    return;
3450
3451
0
  if (!*IsSAT)
3452
0
    BR.markInvalid("Infeasible constraints", EndPathNode->getLocationContext());
3453
0
}
3454
3455
void FalsePositiveRefutationBRVisitor::addConstraints(
3456
0
    const ExplodedNode *N, bool OverwriteConstraintsOnExistingSyms) {
3457
  // Collect new constraints
3458
0
  ConstraintMap NewCs = getConstraintMap(N->getState());
3459
0
  ConstraintMap::Factory &CF = N->getState()->get_context<ConstraintMap>();
3460
3461
  // Add constraints if we don't have them yet
3462
0
  for (auto const &C : NewCs) {
3463
0
    const SymbolRef &Sym = C.first;
3464
0
    if (!Constraints.contains(Sym)) {
3465
      // This symbol is new, just add the constraint.
3466
0
      Constraints = CF.add(Constraints, Sym, C.second);
3467
0
    } else if (OverwriteConstraintsOnExistingSyms) {
3468
      // Overwrite the associated constraint of the Symbol.
3469
0
      Constraints = CF.remove(Constraints, Sym);
3470
0
      Constraints = CF.add(Constraints, Sym, C.second);
3471
0
    }
3472
0
  }
3473
0
}
3474
3475
PathDiagnosticPieceRef FalsePositiveRefutationBRVisitor::VisitNode(
3476
0
    const ExplodedNode *N, BugReporterContext &, PathSensitiveBugReport &) {
3477
0
  addConstraints(N, /*OverwriteConstraintsOnExistingSyms=*/false);
3478
0
  return nullptr;
3479
0
}
3480
3481
void FalsePositiveRefutationBRVisitor::Profile(
3482
0
    llvm::FoldingSetNodeID &ID) const {
3483
0
  static int Tag = 0;
3484
0
  ID.AddPointer(&Tag);
3485
0
}
3486
3487
//===----------------------------------------------------------------------===//
3488
// Implementation of TagVisitor.
3489
//===----------------------------------------------------------------------===//
3490
3491
int NoteTag::Kind = 0;
3492
3493
20.8k
void TagVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
3494
20.8k
  static int Tag = 0;
3495
20.8k
  ID.AddPointer(&Tag);
3496
20.8k
}
3497
3498
PathDiagnosticPieceRef TagVisitor::VisitNode(const ExplodedNode *N,
3499
                                             BugReporterContext &BRC,
3500
3.37M
                                             PathSensitiveBugReport &R) {
3501
3.37M
  ProgramPoint PP = N->getLocation();
3502
3.37M
  const NoteTag *T = dyn_cast_or_null<NoteTag>(PP.getTag());
3503
3.37M
  if (!T)
3504
3.36M
    return nullptr;
3505
3506
10.4k
  if (std::optional<std::string> Msg = T->generateMessage(BRC, R)) {
3507
1.39k
    PathDiagnosticLocation Loc =
3508
1.39k
        PathDiagnosticLocation::create(PP, BRC.getSourceManager());
3509
1.39k
    auto Piece = std::make_shared<PathDiagnosticEventPiece>(Loc, *Msg);
3510
1.39k
    Piece->setPrunable(T->isPrunable());
3511
1.39k
    return Piece;
3512
1.39k
  }
3513
3514
9.06k
  return nullptr;
3515
10.4k
}