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