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