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