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>(R) || isa<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  // As a sanity check, make sure that the negation of the constraint
1674  // was infeasible in the current state. If it is feasible, we somehow
1675  // missed the transition point.
1676  assert(!isUnderconstrained(N));
1677 
1678  // We found the transition point for the constraint. We now need to
1679  // pretty-print the constraint. (work-in-progress)
1680  SmallString<64> sbuf;
1681  llvm::raw_svector_ostream os(sbuf);
1682 
1683  if (Constraint.getAs<Loc>()) {
1684  os << "Assuming pointer value is ";
1685  os << (Assumption ? "non-null" : "null");
1686  }
1687 
1688  if (os.str().empty())
1689  return nullptr;
1690 
1691  // Construct a new PathDiagnosticPiece.
1692  ProgramPoint P = N->getLocation();
1695  if (!L.isValid())
1696  return nullptr;
1697 
1698  auto X = std::make_shared<PathDiagnosticEventPiece>(L, os.str());
1699  X->setTag(getTag());
1700  return std::move(X);
1701  }
1702 
1703  return nullptr;
1704 }
1705 
1706 //===----------------------------------------------------------------------===//
1707 // Implementation of SuppressInlineDefensiveChecksVisitor.
1708 //===----------------------------------------------------------------------===//
1709 
1712  : V(Value) {
1713  // Check if the visitor is disabled.
1714  AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
1715  if (!Options.ShouldSuppressInlinedDefensiveChecks)
1716  IsSatisfied = true;
1717 }
1718 
1720  llvm::FoldingSetNodeID &ID) const {
1721  static int id = 0;
1722  ID.AddPointer(&id);
1723  ID.Add(V);
1724 }
1725 
1727  return "IDCVisitor";
1728 }
1729 
1732  BugReporterContext &BRC,
1733  PathSensitiveBugReport &BR) {
1734  const ExplodedNode *Pred = Succ->getFirstPred();
1735  if (IsSatisfied)
1736  return nullptr;
1737 
1738  // Start tracking after we see the first state in which the value is null.
1739  if (!IsTrackingTurnedOn)
1740  if (Succ->getState()->isNull(V).isConstrainedTrue())
1741  IsTrackingTurnedOn = true;
1742  if (!IsTrackingTurnedOn)
1743  return nullptr;
1744 
1745  // Check if in the previous state it was feasible for this value
1746  // to *not* be null.
1747  if (!Pred->getState()->isNull(V).isConstrainedTrue() &&
1748  Succ->getState()->isNull(V).isConstrainedTrue()) {
1749  IsSatisfied = true;
1750 
1751  // Check if this is inlined defensive checks.
1752  const LocationContext *CurLC = Succ->getLocationContext();
1753  const LocationContext *ReportLC = BR.getErrorNode()->getLocationContext();
1754  if (CurLC != ReportLC && !CurLC->isParentOf(ReportLC)) {
1755  BR.markInvalid("Suppress IDC", CurLC);
1756  return nullptr;
1757  }
1758 
1759  // Treat defensive checks in function-like macros as if they were an inlined
1760  // defensive check. If the bug location is not in a macro and the
1761  // terminator for the current location is in a macro then suppress the
1762  // warning.
1763  auto BugPoint = BR.getErrorNode()->getLocation().getAs<StmtPoint>();
1764 
1765  if (!BugPoint)
1766  return nullptr;
1767 
1768  ProgramPoint CurPoint = Succ->getLocation();
1769  const Stmt *CurTerminatorStmt = nullptr;
1770  if (auto BE = CurPoint.getAs<BlockEdge>()) {
1771  CurTerminatorStmt = BE->getSrc()->getTerminator().getStmt();
1772  } else if (auto SP = CurPoint.getAs<StmtPoint>()) {
1773  const Stmt *CurStmt = SP->getStmt();
1774  if (!CurStmt->getBeginLoc().isMacroID())
1775  return nullptr;
1776 
1777  CFGStmtMap *Map = CurLC->getAnalysisDeclContext()->getCFGStmtMap();
1778  CurTerminatorStmt = Map->getBlock(CurStmt)->getTerminatorStmt();
1779  } else {
1780  return nullptr;
1781  }
1782 
1783  if (!CurTerminatorStmt)
1784  return nullptr;
1785 
1786  SourceLocation TerminatorLoc = CurTerminatorStmt->getBeginLoc();
1787  if (TerminatorLoc.isMacroID()) {
1788  SourceLocation BugLoc = BugPoint->getStmt()->getBeginLoc();
1789 
1790  // Suppress reports unless we are in that same macro.
1791  if (!BugLoc.isMacroID() ||
1792  getMacroName(BugLoc, BRC) != getMacroName(TerminatorLoc, BRC)) {
1793  BR.markInvalid("Suppress Macro IDC", CurLC);
1794  }
1795  return nullptr;
1796  }
1797  }
1798  return nullptr;
1799 }
1800 
1801 //===----------------------------------------------------------------------===//
1802 // TrackControlDependencyCondBRVisitor.
1803 //===----------------------------------------------------------------------===//
1804 
1805 namespace {
1806 /// Tracks the expressions that are a control dependency of the node that was
1807 /// supplied to the constructor.
1808 /// For example:
1809 ///
1810 /// cond = 1;
1811 /// if (cond)
1812 /// 10 / 0;
1813 ///
1814 /// An error is emitted at line 3. This visitor realizes that the branch
1815 /// on line 2 is a control dependency of line 3, and tracks it's condition via
1816 /// trackExpressionValue().
1817 class TrackControlDependencyCondBRVisitor final
1818  : public TrackingBugReporterVisitor {
1819  const ExplodedNode *Origin;
1820  ControlDependencyCalculator ControlDeps;
1821  llvm::SmallSet<const CFGBlock *, 32> VisitedBlocks;
1822 
1823 public:
1824  TrackControlDependencyCondBRVisitor(TrackerRef ParentTracker,
1825  const ExplodedNode *O)
1826  : TrackingBugReporterVisitor(ParentTracker), Origin(O),
1827  ControlDeps(&O->getCFG()) {}
1828 
1829  void Profile(llvm::FoldingSetNodeID &ID) const override {
1830  static int x = 0;
1831  ID.AddPointer(&x);
1832  }
1833 
1834  PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
1835  BugReporterContext &BRC,
1836  PathSensitiveBugReport &BR) override;
1837 };
1838 } // end of anonymous namespace
1839 
1840 static std::shared_ptr<PathDiagnosticEventPiece>
1842  const ExplodedNode *N,
1843  BugReporterContext &BRC) {
1844 
1845  if (BRC.getAnalyzerOptions().AnalysisDiagOpt == PD_NONE ||
1846  !BRC.getAnalyzerOptions().ShouldTrackConditionsDebug)
1847  return nullptr;
1848 
1851  BRC.getSourceManager(), BRC.getASTContext().getLangOpts()));
1852 
1853  return std::make_shared<PathDiagnosticEventPiece>(
1855  Cond, BRC.getSourceManager(), N->getLocationContext()),
1856  (Twine() + "Tracking condition '" + ConditionText + "'").str());
1857 }
1858 
1859 static bool isAssertlikeBlock(const CFGBlock *B, ASTContext &Context) {
1860  if (B->succ_size() != 2)
1861  return false;
1862 
1863  const CFGBlock *Then = B->succ_begin()->getReachableBlock();
1864  const CFGBlock *Else = (B->succ_begin() + 1)->getReachableBlock();
1865 
1866  if (!Then || !Else)
1867  return false;
1868 
1869  if (Then->isInevitablySinking() != Else->isInevitablySinking())
1870  return true;
1871 
1872  // For the following condition the following CFG would be built:
1873  //
1874  // ------------->
1875  // / \
1876  // [B1] -> [B2] -> [B3] -> [sink]
1877  // assert(A && B || C); \ \
1878  // -----------> [go on with the execution]
1879  //
1880  // It so happens that CFGBlock::getTerminatorCondition returns 'A' for block
1881  // B1, 'A && B' for B2, and 'A && B || C' for B3. Let's check whether we
1882  // reached the end of the condition!
1883  if (const Stmt *ElseCond = Else->getTerminatorCondition())
1884  if (const auto *BinOp = dyn_cast<BinaryOperator>(ElseCond))
1885  if (BinOp->isLogicalOp())
1886  return isAssertlikeBlock(Else, Context);
1887 
1888  return false;
1889 }
1890 
1892 TrackControlDependencyCondBRVisitor::VisitNode(const ExplodedNode *N,
1893  BugReporterContext &BRC,
1894  PathSensitiveBugReport &BR) {
1895  // We can only reason about control dependencies within the same stack frame.
1896  if (Origin->getStackFrame() != N->getStackFrame())
1897  return nullptr;
1898 
1899  CFGBlock *NB = const_cast<CFGBlock *>(N->getCFGBlock());
1900 
1901  // Skip if we already inspected this block.
1902  if (!VisitedBlocks.insert(NB).second)
1903  return nullptr;
1904 
1905  CFGBlock *OriginB = const_cast<CFGBlock *>(Origin->getCFGBlock());
1906 
1907  // TODO: Cache CFGBlocks for each ExplodedNode.
1908  if (!OriginB || !NB)
1909  return nullptr;
1910 
1911  if (isAssertlikeBlock(NB, BRC.getASTContext()))
1912  return nullptr;
1913 
1914  if (ControlDeps.isControlDependent(OriginB, NB)) {
1915  // We don't really want to explain for range loops. Evidence suggests that
1916  // the only thing that leads to is the addition of calls to operator!=.
1917  if (llvm::isa_and_nonnull<CXXForRangeStmt>(NB->getTerminatorStmt()))
1918  return nullptr;
1919 
1920  if (const Expr *Condition = NB->getLastCondition()) {
1921  // Keeping track of the already tracked conditions on a visitor level
1922  // isn't sufficient, because a new visitor is created for each tracked
1923  // expression, hence the BugReport level set.
1924  if (BR.addTrackedCondition(N)) {
1925  getParentTracker().track(Condition, N,
1927  /*EnableNullFPSuppression=*/false});
1928  return constructDebugPieceForTrackedCondition(Condition, N, BRC);
1929  }
1930  }
1931  }
1932 
1933  return nullptr;
1934 }
1935 
1936 //===----------------------------------------------------------------------===//
1937 // Implementation of trackExpressionValue.
1938 //===----------------------------------------------------------------------===//
1939 
1940 /// \return A subexpression of @c Ex which represents the
1941 /// expression-of-interest.
1942 static const Expr *peelOffOuterExpr(const Expr *Ex,
1943  const ExplodedNode *N) {
1944  Ex = Ex->IgnoreParenCasts();
1945  if (const auto *FE = dyn_cast<FullExpr>(Ex))
1946  return peelOffOuterExpr(FE->getSubExpr(), N);
1947  if (const auto *OVE = dyn_cast<OpaqueValueExpr>(Ex))
1948  return peelOffOuterExpr(OVE->getSourceExpr(), N);
1949  if (const auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {
1950  const auto *PropRef = dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
1951  if (PropRef && PropRef->isMessagingGetter()) {
1952  const Expr *GetterMessageSend =
1953  POE->getSemanticExpr(POE->getNumSemanticExprs() - 1);
1954  assert(isa<ObjCMessageExpr>(GetterMessageSend->IgnoreParenCasts()));
1955  return peelOffOuterExpr(GetterMessageSend, N);
1956  }
1957  }
1958 
1959  // Peel off the ternary operator.
1960  if (const auto *CO = dyn_cast<ConditionalOperator>(Ex)) {
1961  // Find a node where the branching occurred and find out which branch
1962  // we took (true/false) by looking at the ExplodedGraph.
1963  const ExplodedNode *NI = N;
1964  do {
1965  ProgramPoint ProgPoint = NI->getLocation();
1966  if (Optional<BlockEdge> BE = ProgPoint.getAs<BlockEdge>()) {
1967  const CFGBlock *srcBlk = BE->getSrc();
1968  if (const Stmt *term = srcBlk->getTerminatorStmt()) {
1969  if (term == CO) {
1970  bool TookTrueBranch = (*(srcBlk->succ_begin()) == BE->getDst());
1971  if (TookTrueBranch)
1972  return peelOffOuterExpr(CO->getTrueExpr(), N);
1973  else
1974  return peelOffOuterExpr(CO->getFalseExpr(), N);
1975  }
1976  }
1977  }
1978  NI = NI->getFirstPred();
1979  } while (NI);
1980  }
1981 
1982  if (auto *BO = dyn_cast<BinaryOperator>(Ex))
1983  if (const Expr *SubEx = peelOffPointerArithmetic(BO))
1984  return peelOffOuterExpr(SubEx, N);
1985 
1986  if (auto *UO = dyn_cast<UnaryOperator>(Ex)) {
1987  if (UO->getOpcode() == UO_LNot)
1988  return peelOffOuterExpr(UO->getSubExpr(), N);
1989 
1990  // FIXME: There's a hack in our Store implementation that always computes
1991  // field offsets around null pointers as if they are always equal to 0.
1992  // The idea here is to report accesses to fields as null dereferences
1993  // even though the pointer value that's being dereferenced is actually
1994  // the offset of the field rather than exactly 0.
1995  // See the FIXME in StoreManager's getLValueFieldOrIvar() method.
1996  // This code interacts heavily with this hack; otherwise the value
1997  // would not be null at all for most fields, so we'd be unable to track it.
1998  if (UO->getOpcode() == UO_AddrOf && UO->getSubExpr()->isLValue())
1999  if (const Expr *DerefEx = bugreporter::getDerefExpr(UO->getSubExpr()))
2000  return peelOffOuterExpr(DerefEx, N);
2001  }
2002 
2003  return Ex;
2004 }
2005 
2006 /// Find the ExplodedNode where the lvalue (the value of 'Ex')
2007 /// was computed.
2008 static const ExplodedNode* findNodeForExpression(const ExplodedNode *N,
2009  const Expr *Inner) {
2010  while (N) {
2011  if (N->getStmtForDiagnostics() == Inner)
2012  return N;
2013  N = N->getFirstPred();
2014  }
2015  return N;
2016 }
2017 
2018 //===----------------------------------------------------------------------===//
2019 // Tracker implementation
2020 //===----------------------------------------------------------------------===//
2021 
2022 PathDiagnosticPieceRef StoreHandler::constructNote(StoreInfo SI,
2023  BugReporterContext &BRC,
2024  StringRef NodeText) {
2025  // Construct a new PathDiagnosticPiece.
2028  if (P.getAs<CallEnter>() && SI.SourceOfTheValue)
2030  P.getLocationContext());
2031 
2032  if (!L.isValid() || !L.asLocation().isValid())
2034 
2035  if (!L.isValid() || !L.asLocation().isValid())
2036  return nullptr;
2037 
2038  return std::make_shared<PathDiagnosticEventPiece>(L, NodeText);
2039 }
2040 
2041 class DefaultStoreHandler final : public StoreHandler {
2042 public:
2043  using StoreHandler::StoreHandler;
2044 
2045  PathDiagnosticPieceRef handle(StoreInfo SI, BugReporterContext &BRC,
2046  TrackingOptions Opts) override {
2047  // Okay, we've found the binding. Emit an appropriate message.
2048  SmallString<256> Buffer;
2049  llvm::raw_svector_ostream OS(Buffer);
2050 
2051  switch (SI.StoreKind) {
2052  case StoreInfo::Initialization:
2053  case StoreInfo::BlockCapture:
2054  showBRDiagnostics(OS, SI);
2055  break;
2056  case StoreInfo::CallArgument:
2057  showBRParamDiagnostics(OS, SI);
2058  break;
2059  case StoreInfo::Assignment:
2060  showBRDefaultDiagnostics(OS, SI);
2061  break;
2062  }
2063 
2064  if (Opts.Kind == bugreporter::TrackingKind::Condition)
2066 
2067  return constructNote(SI, BRC, OS.str());
2068  }
2069 };
2070 
2072 public:
2073  using ExpressionHandler::ExpressionHandler;
2074 
2075  Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
2076  const ExplodedNode *LVNode,
2077  TrackingOptions Opts) override {
2078  PathSensitiveBugReport &Report = getParentTracker().getReport();
2079 
2080  // We only track expressions if we believe that they are important. Chances
2081  // are good that control dependencies to the tracking point are also
2082  // important because of this, let's explain why we believe control reached
2083  // this point.
2084  // TODO: Shouldn't we track control dependencies of every bug location,
2085  // rather than only tracked expressions?
2086  if (LVNode->getState()
2087  ->getAnalysisManager()
2088  .getAnalyzerOptions()
2089  .ShouldTrackConditions) {
2090  Report.addVisitor<TrackControlDependencyCondBRVisitor>(
2091  &getParentTracker(), InputNode);
2092  return {/*FoundSomethingToTrack=*/true};
2093  }
2094 
2095  return {};
2096  }
2097 };
2098 
2100 public:
2101  using ExpressionHandler::ExpressionHandler;
2102 
2103  Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
2104  const ExplodedNode *LVNode,
2105  TrackingOptions Opts) override {
2106  // The message send could be nil due to the receiver being nil.
2107  // At this point in the path, the receiver should be live since we are at
2108  // the message send expr. If it is nil, start tracking it.
2109  if (const Expr *Receiver =
2110  NilReceiverBRVisitor::getNilReceiver(Inner, LVNode))
2111  return getParentTracker().track(Receiver, LVNode, Opts);
2112 
2113  return {};
2114  }
2115 };
2116 
2117 class ArrayIndexHandler final : public ExpressionHandler {
2118 public:
2119  using ExpressionHandler::ExpressionHandler;
2120 
2121  Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
2122  const ExplodedNode *LVNode,
2123  TrackingOptions Opts) override {
2124  // Track the index if this is an array subscript.
2125  if (const auto *Arr = dyn_cast<ArraySubscriptExpr>(Inner))
2126  return getParentTracker().track(
2127  Arr->getIdx(), LVNode,
2128  {Opts.Kind, /*EnableNullFPSuppression*/ false});
2129 
2130  return {};
2131  }
2132 };
2133 
2134 // TODO: extract it into more handlers
2136 public:
2137  using ExpressionHandler::ExpressionHandler;
2138 
2139  Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
2140  const ExplodedNode *LVNode,
2141  TrackingOptions Opts) override {
2142  ProgramStateRef LVState = LVNode->getState();
2143  const StackFrameContext *SFC = LVNode->getStackFrame();
2144  PathSensitiveBugReport &Report = getParentTracker().getReport();
2145  Tracker::Result Result;
2146 
2147  // See if the expression we're interested refers to a variable.
2148  // If so, we can track both its contents and constraints on its value.
2150  SVal LVal = LVNode->getSVal(Inner);
2151 
2152  const MemRegion *RR = getLocationRegionIfReference(Inner, LVNode);
2153  bool LVIsNull = LVState->isNull(LVal).isConstrainedTrue();
2154 
2155  // If this is a C++ reference to a null pointer, we are tracking the
2156  // pointer. In addition, we should find the store at which the reference
2157  // got initialized.
2158  if (RR && !LVIsNull)
2159  Result.combineWith(getParentTracker().track(LVal, RR, Opts, SFC));
2160 
2161  // In case of C++ references, we want to differentiate between a null
2162  // reference and reference to null pointer.
2163  // If the LVal is null, check if we are dealing with null reference.
2164  // For those, we want to track the location of the reference.
2165  const MemRegion *R =
2166  (RR && LVIsNull) ? RR : LVNode->getSVal(Inner).getAsRegion();
2167 
2168  if (R) {
2169 
2170  // Mark both the variable region and its contents as interesting.
2171  SVal V = LVState->getRawSVal(loc::MemRegionVal(R));
2172  Report.addVisitor<NoStoreFuncVisitor>(cast<SubRegion>(R), Opts.Kind);
2173 
2174  // When we got here, we do have something to track, and we will
2175  // interrupt.
2176  Result.FoundSomethingToTrack = true;
2177  Result.WasInterrupted = true;
2178 
2179  MacroNullReturnSuppressionVisitor::addMacroVisitorIfNecessary(
2180  LVNode, R, Opts.EnableNullFPSuppression, Report, V);
2181 
2182  Report.markInteresting(V, Opts.Kind);
2183  Report.addVisitor<UndefOrNullArgVisitor>(R);
2184 
2185  // If the contents are symbolic and null, find out when they became
2186  // null.
2187  if (V.getAsLocSymbol(/*IncludeBaseRegions=*/true))
2188  if (LVState->isNull(V).isConstrainedTrue())
2189  Report.addVisitor<TrackConstraintBRVisitor>(V.castAs<DefinedSVal>(),
2190  false);
2191 
2192  // Add visitor, which will suppress inline defensive checks.
2193  if (auto DV = V.getAs<DefinedSVal>())
2194  if (!DV->isZeroConstant() && Opts.EnableNullFPSuppression)
2195  // Note that LVNode may be too late (i.e., too far from the
2196  // InputNode) because the lvalue may have been computed before the
2197  // inlined call was evaluated. InputNode may as well be too early
2198  // here, because the symbol is already dead; this, however, is fine
2199  // because we can still find the node in which it collapsed to null
2200  // previously.
2201  Report.addVisitor<SuppressInlineDefensiveChecksVisitor>(*DV,
2202  InputNode);
2203  getParentTracker().track(V, R, Opts, SFC);
2204  }
2205  }
2206 
2207  return Result;
2208  }
2209 };
2210 
2211 /// Adds a ReturnVisitor if the given statement represents a call that was
2212 /// inlined.
2213 ///
2214 /// This will search back through the ExplodedGraph, starting from the given
2215 /// node, looking for when the given statement was processed. If it turns out
2216 /// the statement is a call that was inlined, we add the visitor to the
2217 /// bug report, so it can print a note later.
2219  using ExpressionHandler::ExpressionHandler;
2220 
2221  Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
2222  const ExplodedNode *ExprNode,
2223  TrackingOptions Opts) override {
2224  if (!CallEvent::isCallStmt(E))
2225  return {};
2226 
2227  // First, find when we processed the statement.
2228  // If we work with a 'CXXNewExpr' that is going to be purged away before
2229  // its call take place. We would catch that purge in the last condition
2230  // as a 'StmtPoint' so we have to bypass it.
2231  const bool BypassCXXNewExprEval = isa<CXXNewExpr>(E);
2232 
2233  // This is moving forward when we enter into another context.
2234  const StackFrameContext *CurrentSFC = ExprNode->getStackFrame();
2235 
2236  do {
2237  // If that is satisfied we found our statement as an inlined call.
2238  if (Optional<CallExitEnd> CEE = ExprNode->getLocationAs<CallExitEnd>())
2239  if (CEE->getCalleeContext()->getCallSite() == E)
2240  break;
2241 
2242  // Try to move forward to the end of the call-chain.
2243  ExprNode = ExprNode->getFirstPred();
2244  if (!ExprNode)
2245  break;
2246 
2247  const StackFrameContext *PredSFC = ExprNode->getStackFrame();
2248 
2249  // If that is satisfied we found our statement.
2250  // FIXME: This code currently bypasses the call site for the
2251  // conservatively evaluated allocator.
2252  if (!BypassCXXNewExprEval)
2253  if (Optional<StmtPoint> SP = ExprNode->getLocationAs<StmtPoint>())
2254  // See if we do not enter into another context.
2255  if (SP->getStmt() == E && CurrentSFC == PredSFC)
2256  break;
2257 
2258  CurrentSFC = PredSFC;
2259  } while (ExprNode->getStackFrame() == CurrentSFC);
2260 
2261  // Next, step over any post-statement checks.
2262  while (ExprNode && ExprNode->getLocation().getAs<PostStmt>())
2263  ExprNode = ExprNode->getFirstPred();
2264  if (!ExprNode)
2265  return {};
2266 
2267  // Finally, see if we inlined the call.
2268  Optional<CallExitEnd> CEE = ExprNode->getLocationAs<CallExitEnd>();
2269  if (!CEE)
2270  return {};
2271 
2272  const StackFrameContext *CalleeContext = CEE->getCalleeContext();
2273  if (CalleeContext->getCallSite() != E)
2274  return {};
2275 
2276  // Check the return value.
2277  ProgramStateRef State = ExprNode->getState();
2278  SVal RetVal = ExprNode->getSVal(E);
2279 
2280  // Handle cases where a reference is returned and then immediately used.
2281  if (cast<Expr>(E)->isGLValue())
2282  if (Optional<Loc> LValue = RetVal.getAs<Loc>())
2283  RetVal = State->getSVal(*LValue);
2284 
2285  // See if the return value is NULL. If so, suppress the report.
2286  AnalyzerOptions &Options = State->getAnalysisManager().options;
2287 
2288  bool EnableNullFPSuppression = false;
2289  if (Opts.EnableNullFPSuppression && Options.ShouldSuppressNullReturnPaths)
2290  if (Optional<Loc> RetLoc = RetVal.getAs<Loc>())
2291  EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
2292 
2293  PathSensitiveBugReport &Report = getParentTracker().getReport();
2294  Report.addVisitor<ReturnVisitor>(&getParentTracker(), CalleeContext,
2295  EnableNullFPSuppression, Options,
2296  Opts.Kind);
2297  return {true};
2298  }
2299 };
2300 
2302 public:
2303  using ExpressionHandler::ExpressionHandler;
2304 
2305  Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
2306  const ExplodedNode *LVNode,
2307  TrackingOptions Opts) override {
2308  ProgramStateRef LVState = LVNode->getState();
2309  const StackFrameContext *SFC = LVNode->getStackFrame();
2310  PathSensitiveBugReport &Report = getParentTracker().getReport();
2311  Tracker::Result Result;
2312 
2313  // If the expression is not an "lvalue expression", we can still
2314  // track the constraints on its contents.
2315  SVal V = LVState->getSValAsScalarOrLoc(Inner, LVNode->getLocationContext());
2316 
2317  // Is it a symbolic value?
2318  if (auto L = V.getAs<loc::MemRegionVal>()) {
2319  // FIXME: this is a hack for fixing a later crash when attempting to
2320  // dereference a void* pointer.
2321  // We should not try to dereference pointers at all when we don't care
2322  // what is written inside the pointer.
2323  bool CanDereference = true;
2324  if (const auto *SR = L->getRegionAs<SymbolicRegion>()) {
2325  if (SR->getSymbol()->getType()->getPointeeType()->isVoidType())
2326  CanDereference = false;
2327  } else if (L->getRegionAs<AllocaRegion>())
2328  CanDereference = false;
2329 
2330  // At this point we are dealing with the region's LValue.
2331  // However, if the rvalue is a symbolic region, we should track it as
2332  // well. Try to use the correct type when looking up the value.
2333  SVal RVal;
2335  RVal = LVState->getRawSVal(L.getValue(), Inner->getType());
2336  else if (CanDereference)
2337  RVal = LVState->getSVal(L->getRegion());
2338 
2339  if (CanDereference) {
2340  Report.addVisitor<UndefOrNullArgVisitor>(L->getRegion());
2341  Result.FoundSomethingToTrack = true;
2342 
2343  if (auto KV = RVal.getAs<KnownSVal>())
2344  Result.combineWith(
2345  getParentTracker().track(*KV, L->getRegion(), Opts, SFC));
2346  }
2347 
2348  const MemRegion *RegionRVal = RVal.getAsRegion();
2349  if (isa_and_nonnull<SymbolicRegion>(RegionRVal)) {
2350  Report.markInteresting(RegionRVal, Opts.Kind);
2351  Report.addVisitor<TrackConstraintBRVisitor>(
2352  loc::MemRegionVal(RegionRVal),
2353  /*assumption=*/false);
2354  Result.FoundSomethingToTrack = true;
2355  }
2356  }
2357 
2358  return Result;
2359  }
2360 };
2361 
2362 /// Attempts to add visitors to track an RValue expression back to its point of
2363 /// origin.
2364 class PRValueHandler final : public ExpressionHandler {
2365 public:
2366  using ExpressionHandler::ExpressionHandler;
2367 
2368  Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
2369  const ExplodedNode *ExprNode,
2370  TrackingOptions Opts) override {
2371  if (!E->isPRValue())
2372  return {};
2373 
2374  const ExplodedNode *RVNode = findNodeForExpression(ExprNode, E);
2375  if (!RVNode)
2376  return {};
2377 
2378  ProgramStateRef RVState = RVNode->getState();
2379  SVal V = RVState->getSValAsScalarOrLoc(E, RVNode->getLocationContext());
2380  const auto *BO = dyn_cast<BinaryOperator>(E);
2381 
2382  if (!BO || !BO->isMultiplicativeOp() || !V.isZeroConstant())
2383  return {};
2384 
2385  SVal RHSV = RVState->getSVal(BO->getRHS(), RVNode->getLocationContext());
2386  SVal LHSV = RVState->getSVal(BO->getLHS(), RVNode->getLocationContext());
2387 
2388  // Track both LHS and RHS of a multiplication.
2389  Tracker::Result CombinedResult;
2390  Tracker &Parent = getParentTracker();
2391 
2392  const auto track = [&CombinedResult, &Parent, ExprNode, Opts](Expr *Inner) {
2393  CombinedResult.combineWith(Parent.track(Inner, ExprNode, Opts));
2394  };
2395 
2396  if (BO->getOpcode() == BO_Mul) {
2397  if (LHSV.isZeroConstant())
2398  track(BO->getLHS());
2399  if (RHSV.isZeroConstant())
2400  track(BO->getRHS());
2401  } else { // Track only the LHS of a division or a modulo.
2402  if (LHSV.isZeroConstant())
2403  track(BO->getLHS());
2404  }
2405 
2406  return CombinedResult;
2407  }
2408 };
2409 
2410 Tracker::Tracker(PathSensitiveBugReport &Report) : Report(Report) {
2411  // Default expression handlers.
2412  addLowPriorityHandler<ControlDependencyHandler>();
2413  addLowPriorityHandler<NilReceiverHandler>();
2414  addLowPriorityHandler<ArrayIndexHandler>();
2415  addLowPriorityHandler<InterestingLValueHandler>();
2416  addLowPriorityHandler<InlinedFunctionCallHandler>();
2417  addLowPriorityHandler<DefaultExpressionHandler>();
2418  addLowPriorityHandler<PRValueHandler>();
2419  // Default store handlers.
2420  addHighPriorityHandler<DefaultStoreHandler>();
2421 }
2422 
2423 Tracker::Result Tracker::track(const Expr *E, const ExplodedNode *N,
2424  TrackingOptions Opts) {
2425  if (!E || !N)
2426  return {};
2427 
2428  const Expr *Inner = peelOffOuterExpr(E, N);
2429  const ExplodedNode *LVNode = findNodeForExpression(N, Inner);
2430  if (!LVNode)
2431  return {};
2432 
2433  Result CombinedResult;
2434  // Iterate through the handlers in the order according to their priorities.
2435  for (ExpressionHandlerPtr &Handler : ExpressionHandlers) {
2436  CombinedResult.combineWith(Handler->handle(Inner, N, LVNode, Opts));
2437  if (CombinedResult.WasInterrupted) {
2438  // There is no need to confuse our users here.
2439  // We got interrupted, but our users don't need to know about it.
2440  CombinedResult.WasInterrupted = false;
2441  break;
2442  }
2443  }
2444 
2445  return CombinedResult;
2446 }
2447 
2448 Tracker::Result Tracker::track(SVal V, const MemRegion *R, TrackingOptions Opts,
2449  const StackFrameContext *Origin) {
2450  if (auto KV = V.getAs<KnownSVal>()) {
2451  Report.addVisitor<StoreSiteFinder>(this, *KV, R, Opts, Origin);
2452  return {true};
2453  }
2454  return {};
2455 }
2456 
2458  TrackingOptions Opts) {
2459  // Iterate through the handlers in the order according to their priorities.
2460  for (StoreHandlerPtr &Handler : StoreHandlers) {
2461  if (PathDiagnosticPieceRef Result = Handler->handle(SI, BRC, Opts))
2462  // If the handler produced a non-null piece, return it.
2463  // There is no need in asking other handlers.
2464  return Result;
2465  }
2466  return {};
2467 }
2468 
2469 bool bugreporter::trackExpressionValue(const ExplodedNode *InputNode,
2470  const Expr *E,
2471 
2472  PathSensitiveBugReport &Report,
2473  TrackingOptions Opts) {
2474  return Tracker::create(Report)
2475  ->track(E, InputNode, Opts)
2476  .FoundSomethingToTrack;
2477 }
2478 
2480  PathSensitiveBugReport &Report,
2481  TrackingOptions Opts,
2482  const StackFrameContext *Origin) {
2483  Tracker::create(Report)->track(V, R, Opts, Origin);
2484 }
2485 
2486 //===----------------------------------------------------------------------===//
2487 // Implementation of NulReceiverBRVisitor.
2488 //===----------------------------------------------------------------------===//
2489 
2491  const ExplodedNode *N) {
2492  const auto *ME = dyn_cast<ObjCMessageExpr>(S);
2493  if (!ME)
2494  return nullptr;
2495  if (const Expr *Receiver = ME->getInstanceReceiver()) {
2497  SVal V = N->getSVal(Receiver);
2498  if (state->isNull(V).isConstrainedTrue())
2499  return Receiver;
2500  }
2501  return nullptr;
2502 }
2503 
2506  PathSensitiveBugReport &BR) {
2508  if (!P)
2509  return nullptr;
2510 
2511  const Stmt *S = P->getStmt();
2512  const Expr *Receiver = getNilReceiver(S, N);
2513  if (!Receiver)
2514  return nullptr;
2515 
2517  llvm::raw_svector_ostream OS(Buf);
2518 
2519  if (const auto *ME = dyn_cast<ObjCMessageExpr>(S)) {
2520  OS << "'";
2521  ME->getSelector().print(OS);
2522  OS << "' not called";
2523  }
2524  else {
2525  OS << "No method is called";
2526  }
2527  OS << " because the receiver is nil";
2528 
2529  // The receiver was nil, and hence the method was skipped.
2530  // Register a BugReporterVisitor to issue a message telling us how
2531  // the receiver was null.
2532  bugreporter::trackExpressionValue(N, Receiver, BR,
2534  /*EnableNullFPSuppression*/ false});
2535  // Issue a message saying that the method was skipped.
2536  PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
2537  N->getLocationContext());
2538  return std::make_shared<PathDiagnosticEventPiece>(L, OS.str());
2539 }
2540 
2541 //===----------------------------------------------------------------------===//
2542 // Visitor that tries to report interesting diagnostics from conditions.
2543 //===----------------------------------------------------------------------===//
2544 
2545 /// Return the tag associated with this visitor. This tag will be used
2546 /// to make all PathDiagnosticPieces created by this visitor.
2547 const char *ConditionBRVisitor::getTag() { return "ConditionBRVisitor"; }
2548 
2551  PathSensitiveBugReport &BR) {
2552  auto piece = VisitNodeImpl(N, BRC, BR);
2553  if (piece) {
2554  piece->setTag(getTag());
2555  if (auto *ev = dyn_cast<PathDiagnosticEventPiece>(piece.get()))
2556  ev->setPrunable(true, /* override */ false);
2557  }
2558  return piece;
2559 }
2560 
2563  BugReporterContext &BRC,
2564  PathSensitiveBugReport &BR) {
2565  ProgramPoint ProgPoint = N->getLocation();
2566  const std::pair<const ProgramPointTag *, const ProgramPointTag *> &Tags =
2568 
2569  // If an assumption was made on a branch, it should be caught
2570  // here by looking at the state transition.
2571  if (Optional<BlockEdge> BE = ProgPoint.getAs<BlockEdge>()) {
2572  const CFGBlock *SrcBlock = BE->getSrc();
2573  if (const Stmt *Term = SrcBlock->getTerminatorStmt()) {
2574  // If the tag of the previous node is 'Eagerly Assume...' the current
2575  // 'BlockEdge' has the same constraint information. We do not want to
2576  // report the value as it is just an assumption on the predecessor node
2577  // which will be caught in the next VisitNode() iteration as a 'PostStmt'.
2578  const ProgramPointTag *PreviousNodeTag =
2579  N->getFirstPred()->getLocation().getTag();
2580  if (PreviousNodeTag == Tags.first || PreviousNodeTag == Tags.second)
2581  return nullptr;
2582 
2583  return VisitTerminator(Term, N, SrcBlock, BE->getDst(), BR, BRC);
2584  }
2585  return nullptr;
2586  }
2587 
2588  if (Optional<PostStmt> PS = ProgPoint.getAs<PostStmt>()) {
2589  const ProgramPointTag *CurrentNodeTag = PS->getTag();
2590  if (CurrentNodeTag != Tags.first && CurrentNodeTag != Tags.second)
2591  return nullptr;
2592 
2593  bool TookTrue = CurrentNodeTag == Tags.first;
2594  return VisitTrueTest(cast<Expr>(PS->getStmt()), BRC, BR, N, TookTrue);
2595  }
2596 
2597  return nullptr;
2598 }
2599 
2601  const Stmt *Term, const ExplodedNode *N, const CFGBlock *srcBlk,
2602  const CFGBlock *dstBlk, PathSensitiveBugReport &R,
2603  BugReporterContext &BRC) {
2604  const Expr *Cond = nullptr;
2605 
2606  // In the code below, Term is a CFG terminator and Cond is a branch condition
2607  // expression upon which the decision is made on this terminator.
2608  //
2609  // For example, in "if (x == 0)", the "if (x == 0)" statement is a terminator,
2610  // and "x == 0" is the respective condition.
2611  //
2612  // Another example: in "if (x && y)", we've got two terminators and two
2613  // conditions due to short-circuit nature of operator "&&":
2614  // 1. The "if (x && y)" statement is a terminator,
2615  // and "y" is the respective condition.
2616  // 2. Also "x && ..." is another terminator,
2617  // and "x" is its condition.
2618 
2619  switch (Term->getStmtClass()) {
2620  // FIXME: Stmt::SwitchStmtClass is worth handling, however it is a bit
2621  // more tricky because there are more than two branches to account for.
2622  default:
2623  return nullptr;
2624  case Stmt::IfStmtClass:
2625  Cond = cast<IfStmt>(Term)->getCond();
2626  break;
2627  case Stmt::ConditionalOperatorClass:
2628  Cond = cast<ConditionalOperator>(Term)->getCond();
2629  break;
2630  case Stmt::BinaryOperatorClass:
2631  // When we encounter a logical operator (&& or ||) as a CFG terminator,
2632  // then the condition is actually its LHS; otherwise, we'd encounter
2633  // the parent, such as if-statement, as a terminator.
2634  const auto *BO = cast<BinaryOperator>(Term);
2635  assert(BO->isLogicalOp() &&
2636  "CFG terminator is not a short-circuit operator!");
2637  Cond = BO->getLHS();
2638  break;
2639  }
2640 
2641  Cond = Cond->IgnoreParens();
2642 
2643  // However, when we encounter a logical operator as a branch condition,
2644  // then the condition is actually its RHS, because LHS would be
2645  // the condition for the logical operator terminator.
2646  while (const auto *InnerBO = dyn_cast<BinaryOperator>(Cond)) {
2647  if (!InnerBO->isLogicalOp())
2648  break;
2649  Cond = InnerBO->getRHS()->IgnoreParens();
2650  }
2651 
2652  assert(Cond);
2653  assert(srcBlk->succ_size() == 2);
2654  const bool TookTrue = *(srcBlk->succ_begin()) == dstBlk;
2655  return VisitTrueTest(Cond, BRC, R, N, TookTrue);
2656 }
2657 
2661  const ExplodedNode *N, bool TookTrue) {
2662  ProgramStateRef CurrentState = N->getState();
2663  ProgramStateRef PrevState = N->getFirstPred()->getState();
2664  const LocationContext *LCtx = N->getLocationContext();
2665 
2666  // If the constraint information is changed between the current and the
2667  // previous program state we assuming the newly seen constraint information.
2668  // If we cannot evaluate the condition (and the constraints are the same)
2669  // the analyzer has no information about the value and just assuming it.
2670  bool IsAssuming =
2671  !BRC.getStateManager().haveEqualConstraints(CurrentState, PrevState) ||
2672  CurrentState->getSVal(Cond, LCtx).isUnknownOrUndef();
2673 
2674  // These will be modified in code below, but we need to preserve the original
2675  // values in case we want to throw the generic message.
2676  const Expr *CondTmp = Cond;
2677  bool TookTrueTmp = TookTrue;
2678 
2679  while (true) {
2680  CondTmp = CondTmp->IgnoreParenCasts();
2681  switch (CondTmp->getStmtClass()) {
2682  default:
2683  break;
2684  case Stmt::BinaryOperatorClass:
2685  if (auto P = VisitTrueTest(Cond, cast<BinaryOperator>(CondTmp),
2686  BRC, R, N, TookTrueTmp, IsAssuming))
2687  return P;
2688  break;
2689  case Stmt::DeclRefExprClass:
2690  if (auto P = VisitTrueTest(Cond, cast<DeclRefExpr>(CondTmp),
2691  BRC, R, N, TookTrueTmp, IsAssuming))
2692  return P;
2693  break;
2694  case Stmt::MemberExprClass:
2695  if (auto P = VisitTrueTest(Cond, cast<MemberExpr>(CondTmp),
2696  BRC, R, N, TookTrueTmp, IsAssuming))
2697  return P;
2698  break;
2699  case Stmt::UnaryOperatorClass: {
2700  const auto *UO = cast<UnaryOperator>(CondTmp);
2701  if (UO->getOpcode() == UO_LNot) {
2702  TookTrueTmp = !TookTrueTmp;
2703  CondTmp = UO->getSubExpr();
2704  continue;
2705  }
2706  break;
2707  }
2708  }
2709  break;
2710  }
2711 
2712  // Condition too complex to explain? Just say something so that the user
2713  // knew we've made some path decision at this point.
2714  // If it is too complex and we know the evaluation of the condition do not
2715  // repeat the note from 'BugReporter.cpp'
2716  if (!IsAssuming)
2717  return nullptr;
2718 
2719  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
2720  if (!Loc.isValid() || !Loc.asLocation().isValid())
2721  return nullptr;
2722 
2723  return std::make_shared<PathDiagnosticEventPiece>(
2724  Loc, TookTrue ? GenericTrueMessage : GenericFalseMessage);
2725 }
2726 
2728  const Expr *ParentEx,
2729  raw_ostream &Out,
2730  BugReporterContext &BRC,
2731  PathSensitiveBugReport &report,
2732  const ExplodedNode *N,
2733  Optional<bool> &prunable,
2734  bool IsSameFieldName) {
2735  const Expr *OriginalExpr = Ex;
2736  Ex = Ex->IgnoreParenCasts();
2737 
2738  if (isa<GNUNullExpr>(Ex) || isa<ObjCBoolLiteralExpr>(Ex) ||
2739  isa<CXXBoolLiteralExpr>(Ex) || isa<IntegerLiteral>(Ex) ||
2740  isa<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 << '\''
2807  BRC.getSourceManager(), BRC.getASTContext().getLangOpts(), 0)
2808  << '\'';
2809  }
2810 
2811  return false;
2812 }
2813 
2815  const Expr *Cond, const BinaryOperator *BExpr, BugReporterContext &BRC,
2816  PathSensitiveBugReport &R, const ExplodedNode *N, bool TookTrue,
2817  bool IsAssuming) {
2818  bool shouldInvert = false;
2819  Optional<bool> shouldPrune;
2820 
2821  // Check if the field name of the MemberExprs is ambiguous. Example:
2822  // " 'a.d' is equal to 'h.d' " in 'test/Analysis/null-deref-path-notes.cpp'.
2823  bool IsSameFieldName = false;
2824  const auto *LhsME = dyn_cast<MemberExpr>(BExpr->getLHS()->IgnoreParenCasts());
2825  const auto *RhsME = dyn_cast<MemberExpr>(BExpr->getRHS()->IgnoreParenCasts());
2826 
2827  if (LhsME && RhsME)
2828  IsSameFieldName =
2829  LhsME->getMemberDecl()->getName() == RhsME->getMemberDecl()->getName();
2830 
2831  SmallString<128> LhsString, RhsString;
2832  {
2833  llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
2834  const bool isVarLHS = patternMatch(BExpr->getLHS(), BExpr, OutLHS, BRC, R,
2835  N, shouldPrune, IsSameFieldName);
2836  const bool isVarRHS = patternMatch(BExpr->getRHS(), BExpr, OutRHS, BRC, R,
2837  N, shouldPrune, IsSameFieldName);
2838 
2839  shouldInvert = !isVarLHS && isVarRHS;
2840  }
2841 
2842  BinaryOperator::Opcode Op = BExpr->getOpcode();
2843 
2845  // For assignment operators, all that we care about is that the LHS
2846  // evaluates to "true" or "false".
2847  return VisitConditionVariable(LhsString, BExpr->getLHS(), BRC, R, N,
2848  TookTrue);
2849  }
2850 
2851  // For non-assignment operations, we require that we can understand
2852  // both the LHS and RHS.
2853  if (LhsString.empty() || RhsString.empty() ||
2854  !BinaryOperator::isComparisonOp(Op) || Op == BO_Cmp)
2855  return nullptr;
2856 
2857  // Should we invert the strings if the LHS is not a variable name?
2858  SmallString<256> buf;
2859  llvm::raw_svector_ostream Out(buf);
2860  Out << (IsAssuming ? "Assuming " : "")
2861  << (shouldInvert ? RhsString : LhsString) << " is ";
2862 
2863  // Do we need to invert the opcode?
2864  if (shouldInvert)
2865  switch (Op) {
2866  default: break;
2867  case BO_LT: Op = BO_GT; break;
2868  case BO_GT: Op = BO_LT; break;
2869  case BO_LE: Op = BO_GE; break;
2870  case BO_GE: Op = BO_LE; break;
2871  }
2872 
2873  if (!TookTrue)
2874  switch (Op) {
2875  case BO_EQ: Op = BO_NE; break;
2876  case BO_NE: Op = BO_EQ; break;
2877  case BO_LT: Op = BO_GE; break;
2878  case BO_GT: Op = BO_LE; break;
2879  case BO_LE: Op = BO_GT; break;
2880  case BO_GE: Op = BO_LT; break;
2881  default:
2882  return nullptr;
2883  }
2884 
2885  switch (Op) {
2886  case BO_EQ:
2887  Out << "equal to ";
2888  break;
2889  case BO_NE:
2890  Out << "not equal to ";
2891  break;
2892  default:
2893  Out << BinaryOperator::getOpcodeStr(Op) << ' ';
2894  break;
2895  }
2896 
2897  Out << (shouldInvert ? LhsString : RhsString);
2898  const LocationContext *LCtx = N->getLocationContext();
2899  const SourceManager &SM = BRC.getSourceManager();
2900 
2901  if (isVarAnInterestingCondition(BExpr->getLHS(), N, &R) ||
2902  isVarAnInterestingCondition(BExpr->getRHS(), N, &R))
2903  Out << WillBeUsedForACondition;
2904 
2905  // Convert 'field ...' to 'Field ...' if it is a MemberExpr.
2906  std::string Message = std::string(Out.str());
2907  Message[0] = toupper(Message[0]);
2908 
2909  // If we know the value create a pop-up note to the value part of 'BExpr'.
2910  if (!IsAssuming) {
2912  if (!shouldInvert) {
2913  if (LhsME && LhsME->getMemberLoc().isValid())
2914  Loc = PathDiagnosticLocation(LhsME->getMemberLoc(), SM);
2915  else
2916  Loc = PathDiagnosticLocation(BExpr->getLHS(), SM, LCtx);
2917  } else {
2918  if (RhsME && RhsME->getMemberLoc().isValid())
2919  Loc = PathDiagnosticLocation(RhsME->getMemberLoc(), SM);
2920  else
2921  Loc = PathDiagnosticLocation(BExpr->getRHS(), SM, LCtx);
2922  }
2923 
2924  return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Message);
2925  }
2926 
2927  PathDiagnosticLocation Loc(Cond, SM, LCtx);
2928  auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Message);
2929  if (shouldPrune.hasValue())
2930  event->setPrunable(shouldPrune.getValue());
2931  return event;
2932 }
2933 
2935  StringRef LhsString, const Expr *CondVarExpr, BugReporterContext &BRC,
2936  PathSensitiveBugReport &report, const ExplodedNode *N, bool TookTrue) {
2937  // FIXME: If there's already a constraint tracker for this variable,
2938  // we shouldn't emit anything here (c.f. the double note in
2939  // test/Analysis/inlining/path-notes.c)
2940  SmallString<256> buf;
2941  llvm::raw_svector_ostream Out(buf);
2942  Out << "Assuming " << LhsString << " is ";
2943 
2944  if (!printValue(CondVarExpr, Out, N, TookTrue, /*IsAssuming=*/true))
2945  return nullptr;
2946 
2947  const LocationContext *LCtx = N->getLocationContext();
2948  PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
2949 
2950  if (isVarAnInterestingCondition(CondVarExpr, N, &report))
2951  Out << WillBeUsedForACondition;
2952 
2953  auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2954 
2955  if (isInterestingExpr(CondVarExpr, N, &report))
2956  event->setPrunable(false);
2957 
2958  return event;
2959 }
2960 
2962  const Expr *Cond, const DeclRefExpr *DRE, BugReporterContext &BRC,
2963  PathSensitiveBugReport &report, const ExplodedNode *N, bool TookTrue,
2964  bool IsAssuming) {
2965  const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
2966  if (!VD)
2967  return nullptr;
2968 
2969  SmallString<256> Buf;
2970  llvm::raw_svector_ostream Out(Buf);
2971 
2972  Out << (IsAssuming ? "Assuming '" : "'") << VD->getDeclName() << "' is ";
2973 
2974  if (!printValue(DRE, Out, N, TookTrue, IsAssuming))
2975  return nullptr;
2976 
2977  const LocationContext *LCtx = N->getLocationContext();
2978 
2979  if (isVarAnInterestingCondition(DRE, N, &report))
2980  Out << WillBeUsedForACondition;
2981 
2982  // If we know the value create a pop-up note to the 'DRE'.
2983  if (!IsAssuming) {
2984  PathDiagnosticLocation Loc(DRE, BRC.getSourceManager(), LCtx);
2985  return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Out.str());
2986  }
2987 
2988  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
2989  auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2990 
2991  if (isInterestingExpr(DRE, N, &report))
2992  event->setPrunable(false);
2993 
2994  return std::move(event);
2995 }
2996 
2998  const Expr *Cond, const MemberExpr *ME, BugReporterContext &BRC,
2999  PathSensitiveBugReport &report, const ExplodedNode *N, bool TookTrue,
3000  bool IsAssuming) {
3001  SmallString<256> Buf;
3002  llvm::raw_svector_ostream Out(Buf);
3003 
3004  Out << (IsAssuming ? "Assuming field '" : "Field '")
3005  << ME->getMemberDecl()->getName() << "' is ";
3006 
3007  if (!printValue(ME, Out, N, TookTrue, IsAssuming))
3008  return nullptr;
3009 
3010  const LocationContext *LCtx = N->getLocationContext();
3011  PathDiagnosticLocation Loc;
3012 
3013  // If we know the value create a pop-up note to the member of the MemberExpr.
3014  if (!IsAssuming && ME->getMemberLoc().isValid())
3015  Loc = PathDiagnosticLocation(ME->getMemberLoc(), BRC.getSourceManager());
3016  else
3017  Loc = PathDiagnosticLocation(Cond, BRC.getSourceManager(), LCtx);
3018 
3019  if (!Loc.isValid() || !Loc.asLocation().isValid())
3020  return nullptr;
3021 
3022  if (isVarAnInterestingCondition(ME, N, &report))
3023  Out << WillBeUsedForACondition;
3024 
3025  // If we know the value create a pop-up note.
3026  if (!IsAssuming)
3027  return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Out.str());
3028 
3029  auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
3030  if (isInterestingExpr(ME, N, &report))
3031  event->setPrunable(false);
3032  return event;
3033 }
3034 
3035 bool ConditionBRVisitor::printValue(const Expr *CondVarExpr, raw_ostream &Out,
3036  const ExplodedNode *N, bool TookTrue,
3037  bool IsAssuming) {
3038  QualType Ty = CondVarExpr->getType();
3039 
3040  if (Ty->isPointerType()) {
3041  Out << (TookTrue ? "non-null" : "null");
3042  return true;
3043  }
3044 
3045  if (Ty->isObjCObjectPointerType()) {
3046  Out << (TookTrue ? "non-nil" : "nil");
3047  return true;
3048  }
3049 
3050  if (!Ty->isIntegralOrEnumerationType())
3051  return false;
3052 
3054  if (!IsAssuming)
3055  IntValue = getConcreteIntegerValue(CondVarExpr, N);
3056 
3057  if (IsAssuming || !IntValue.hasValue()) {
3058  if (Ty->isBooleanType())
3059  Out << (TookTrue ? "true" : "false");
3060  else
3061  Out << (TookTrue ? "not equal to 0" : "0");
3062  } else {
3063  if (Ty->isBooleanType())
3064  Out << (IntValue.getValue()->getBoolValue() ? "true" : "false");
3065  else
3066  Out << *IntValue.getValue();
3067  }
3068 
3069  return true;
3070 }
3071 
3072 constexpr llvm::StringLiteral ConditionBRVisitor::GenericTrueMessage;
3073 constexpr llvm::StringLiteral ConditionBRVisitor::GenericFalseMessage;
3074 
3076  const PathDiagnosticPiece *Piece) {
3077  return Piece->getString() == GenericTrueMessage ||
3078  Piece->getString() == GenericFalseMessage;
3079 }
3080 
3081 //===----------------------------------------------------------------------===//
3082 // Implementation of LikelyFalsePositiveSuppressionBRVisitor.
3083 //===----------------------------------------------------------------------===//
3084 
3086  BugReporterContext &BRC, const ExplodedNode *N,
3087  PathSensitiveBugReport &BR) {
3088  // Here we suppress false positives coming from system headers. This list is
3089  // based on known issues.
3090  const AnalyzerOptions &Options = BRC.getAnalyzerOptions();
3091  const Decl *D = N->getLocationContext()->getDecl();
3092 
3094  // Skip reports within the 'std' namespace. Although these can sometimes be
3095  // the user's fault, we currently don't report them very well, and
3096  // Note that this will not help for any other data structure libraries, like
3097  // TR1, Boost, or llvm/ADT.
3098  if (Options.ShouldSuppressFromCXXStandardLibrary) {
3099  BR.markInvalid(getTag(), nullptr);
3100  return;
3101  } else {
3102  // If the complete 'std' suppression is not enabled, suppress reports
3103  // from the 'std' namespace that are known to produce false positives.
3104 
3105  // The analyzer issues a false use-after-free when std::list::pop_front
3106  // or std::list::pop_back are called multiple times because we cannot
3107  // reason about the internal invariants of the data structure.
3108  if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
3109  const CXXRecordDecl *CD = MD->getParent();
3110  if (CD->getName() == "list") {
3111  BR.markInvalid(getTag(), nullptr);
3112  return;
3113  }
3114  }
3115 
3116  // The analyzer issues a false positive when the constructor of
3117  // std::__independent_bits_engine from algorithms is used.
3118  if (const auto *MD = dyn_cast<CXXConstructorDecl>(D)) {
3119  const CXXRecordDecl *CD = MD->getParent();
3120  if (CD->getName() == "__independent_bits_engine") {
3121  BR.markInvalid(getTag(), nullptr);
3122  return;
3123  }
3124  }
3125 
3126  for (const LocationContext *LCtx = N->getLocationContext(); LCtx;
3127  LCtx = LCtx->getParent()) {
3128  const auto *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
3129  if (!MD)
3130  continue;
3131 
3132  const CXXRecordDecl *CD = MD->getParent();
3133  // The analyzer issues a false positive on
3134  // std::basic_string<uint8_t> v; v.push_back(1);
3135  // and
3136  // std::u16string s; s += u'a';
3137  // because we cannot reason about the internal invariants of the
3138  // data structure.
3139  if (CD->getName() == "basic_string") {
3140  BR.markInvalid(getTag(), nullptr);
3141  return;
3142  }
3143 
3144  // The analyzer issues a false positive on
3145  // std::shared_ptr<int> p(new int(1)); p = nullptr;
3146  // because it does not reason properly about temporary destructors.
3147  if (CD->getName() == "shared_ptr") {
3148  BR.markInvalid(getTag(), nullptr);
3149  return;
3150  }
3151  }
3152  }
3153  }
3154 
3155  // Skip reports within the sys/queue.h macros as we do not have the ability to
3156  // reason about data structure shapes.
3157  const SourceManager &SM = BRC.getSourceManager();
3159  while (Loc.isMacroID()) {
3160  Loc = Loc.getSpellingLoc();
3161  if (SM.getFilename(Loc).endswith("sys/queue.h")) {
3162  BR.markInvalid(getTag(), nullptr);
3163  return;
3164  }
3165  }
3166 }
3167 
3168 //===----------------------------------------------------------------------===//
3169 // Implementation of UndefOrNullArgVisitor.
3170 //===----------------------------------------------------------------------===//
3171 
3174  PathSensitiveBugReport &BR) {
3176  ProgramPoint ProgLoc = N->getLocation();
3177 
3178  // We are only interested in visiting CallEnter nodes.
3179  Optional<CallEnter> CEnter = ProgLoc.getAs<CallEnter>();
3180  if (!CEnter)
3181  return nullptr;
3182 
3183  // Check if one of the arguments is the region the visitor is tracking.
3185  CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State);
3186  unsigned Idx = 0;
3187  ArrayRef<ParmVarDecl *> parms = Call->parameters();
3188 
3189  for (const auto ParamDecl : parms) {
3190  const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion();
3191  ++Idx;
3192 
3193  // Are we tracking the argument or its subregion?
3194  if ( !ArgReg || !R->isSubRegionOf(ArgReg->StripCasts()))
3195  continue;
3196 
3197  // Check the function parameter type.
3198  assert(ParamDecl && "Formal parameter has no decl?");
3199  QualType T = ParamDecl->getType();
3200 
3201  if (!(T->isAnyPointerType() || T->isReferenceType())) {
3202  // Function can only change the value passed in by address.
3203  continue;
3204  }
3205 
3206  // If it is a const pointer value, the function does not intend to
3207  // change the value.
3208  if (T->getPointeeType().isConstQualified())
3209  continue;
3210 
3211  // Mark the call site (LocationContext) as interesting if the value of the
3212  // argument is undefined or '0'/'NULL'.
3213  SVal BoundVal = State->getSVal(R);
3214  if (BoundVal.isUndef() || BoundVal.isZeroConstant()) {
3215  BR.markInteresting(CEnter->getCalleeContext());
3216  return nullptr;
3217  }
3218  }
3219  return nullptr;
3220 }
3221 
3222 //===----------------------------------------------------------------------===//
3223 // Implementation of FalsePositiveRefutationBRVisitor.
3224 //===----------------------------------------------------------------------===//
3225 
3227  : Constraints(ConstraintMap::Factory().getEmptyMap()) {}
3228 
3230  BugReporterContext &BRC, const ExplodedNode *EndPathNode,
3231  PathSensitiveBugReport &BR) {
3232  // Collect new constraints
3233  addConstraints(EndPathNode, /*OverwriteConstraintsOnExistingSyms=*/true);
3234 
3235  // Create a refutation manager
3236  llvm::SMTSolverRef RefutationSolver = llvm::CreateZ3Solver();
3237  ASTContext &Ctx = BRC.getASTContext();
3238 
3239  // Add constraints to the solver
3240  for (const auto &I : Constraints) {
3241  const SymbolRef Sym = I.first;
3242  auto RangeIt = I.second.begin();
3243 
3244  llvm::SMTExprRef SMTConstraints = SMTConv::getRangeExpr(
3245  RefutationSolver, Ctx, Sym, RangeIt->From(), RangeIt->To(),
3246  /*InRange=*/true);
3247  while ((++RangeIt) != I.second.end()) {
3248  SMTConstraints = RefutationSolver->mkOr(
3249  SMTConstraints, SMTConv::getRangeExpr(RefutationSolver, Ctx, Sym,
3250  RangeIt->From(), RangeIt->To(),
3251  /*InRange=*/true));
3252  }
3253 
3254  RefutationSolver->addConstraint(SMTConstraints);
3255  }
3256 
3257  // And check for satisfiability
3258  Optional<bool> IsSAT = RefutationSolver->check();
3259  if (!IsSAT.hasValue())
3260  return;
3261 
3262  if (!IsSAT.getValue())
3263  BR.markInvalid("Infeasible constraints", EndPathNode->getLocationContext());
3264 }
3265 
3267  const ExplodedNode *N, bool OverwriteConstraintsOnExistingSyms) {
3268  // Collect new constraints
3269  ConstraintMap NewCs = getConstraintMap(N->getState());
3270  ConstraintMap::Factory &CF = N->getState()->get_context<ConstraintMap>();
3271 
3272  // Add constraints if we don't have them yet
3273  for (auto const &C : NewCs) {
3274  const SymbolRef &Sym = C.first;
3275  if (!Constraints.contains(Sym)) {
3276  // This symbol is new, just add the constraint.
3277  Constraints = CF.add(Constraints, Sym, C.second);
3278  } else if (OverwriteConstraintsOnExistingSyms) {
3279  // Overwrite the associated constraint of the Symbol.
3280  Constraints = CF.remove(Constraints, Sym);
3281  Constraints = CF.add(Constraints, Sym, C.second);
3282  }
3283  }
3284 }
3285 
3288  addConstraints(N, /*OverwriteConstraintsOnExistingSyms=*/false);
3289  return nullptr;
3290 }
3291 
3293  llvm::FoldingSetNodeID &ID) const {
3294  static int Tag = 0;
3295  ID.AddPointer(&Tag);
3296 }
3297 
3298 //===----------------------------------------------------------------------===//
3299 // Implementation of TagVisitor.
3300 //===----------------------------------------------------------------------===//
3301 
3302 int NoteTag::Kind = 0;
3303 
3304 void TagVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
3305  static int Tag = 0;
3306  ID.AddPointer(&Tag);
3307 }
3308 
3310  BugReporterContext &BRC,
3312  ProgramPoint PP = N->getLocation();
3313  const NoteTag *T = dyn_cast_or_null<NoteTag>(PP.getTag());
3314  if (!T)
3315  return nullptr;
3316 
3317  if (Optional<std::string> Msg = T->generateMessage(BRC, R)) {
3320  auto Piece = std::make_shared<PathDiagnosticEventPiece>(Loc, *Msg);
3321  Piece->setPrunable(T->isPrunable());
3322  return Piece;
3323  }
3324 
3325  return nullptr;
3326 }
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:668
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:827
clang::ento::ProgramStateManager::haveEqualConstraints
bool haveEqualConstraints(ProgramStateRef S1, ProgramStateRef S2) const
Definition: ProgramState.h:568
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:2161
InterestingLValueHandler
Definition: BugReporterVisitors.cpp:2135
clang::ast_matchers::StatementMatcher
internal::Matcher< Stmt > StatementMatcher
Definition: ASTMatchers.h:142
clang::ento::PathDiagnosticLocation
Definition: PathDiagnostic.h:197
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:82
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:370
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:212
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:800
clang::ast_matchers::stmt
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
Definition: ASTMatchersInternal.cpp:809
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:3309
clang::ento::PathDiagnosticPieceRef
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
Definition: PathDiagnostic.h:494
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:140
clang::QualType::isConstQualified
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition: Type.h:6484
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:39
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:2490
AnalysisDeclContext.h
llvm::SmallVector
Definition: LLVM.h:38
clang::ento::MemRegion::StripCasts
const MemRegion * StripCasts(bool StripBaseAndDerivedCasts=true) const
Definition: MemRegion.cpp:1329
clang::SourceLocation
Encodes a location in the source.
Definition: SourceLocation.h:88
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:673
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:6464
clang::FieldDecl
Represents a member of a struct/union/class.
Definition: Decl.h:2835
clang::ento::ExplodedNode
Definition: ExplodedGraph.h:65
DefaultStoreHandler
Definition: BugReporterVisitors.cpp:2041
clang::ParmVarDecl
Represents a parameter to a function.
Definition: Decl.h:1665
ControlDependencyHandler
Definition: BugReporterVisitors.cpp:2071
DeclCXX.h
ProgramState_Fwd.h
clang::BinaryOperator::isAssignmentOp
bool isAssignmentOp() const
Definition: Expr.h:3941
clang::BinaryOperator::getOpcodeStr
StringRef getOpcodeStr() const
Definition: Expr.h:3868
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:2547
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:2550
llvm::Optional
Definition: LLVM.h:40
clang::CFG::isLinear
bool isLinear() const
Returns true if the CFG has no branches.
Definition: CFG.cpp:4996
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:957
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:6956
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:3035
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:59
peelOffOuterExpr
static const Expr * peelOffOuterExpr(const Expr *Ex, const ExplodedNode *N)
Definition: BugReporterVisitors.cpp:1942
clang::ento::FalsePositiveRefutationBRVisitor::FalsePositiveRefutationBRVisitor
FalsePositiveRefutationBRVisitor()
Definition: BugReporterVisitors.cpp:3226
clang::index::SymbolRole::Call
@ Call
clang::BinaryOperator::getOpcode
Opcode getOpcode() const
Definition: Expr.h:3847
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:2364
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:403
clang::ento::ProgramState
Definition: ProgramState.h:72
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:2899
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:483
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:784
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:2457
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:1165
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:6685
clang::syntax::NodeRole::Parameters
@ Parameters
V
#define V(N, I)
Definition: ASTContext.h:3121
clang::ento::ExplodedNode::getState
const ProgramStateRef & getState() const
Definition: ExplodedGraph.h:169
clang::ento::DefinedSVal
Definition: SVals.h:269
ProgramPoint.h
clang::ento::TrackConstraintBRVisitor::Profile
void Profile(llvm::FoldingSetNodeID &ID) const override
Definition: BugReporterVisitors.cpp:1635
TrackingBugReporterVisitor
clang::ast_matchers::objcIvarRefExpr
const internal::VariadicDynCastAllOfMatcher< Stmt, ObjCIvarRefExpr > objcIvarRefExpr
Matches a reference to an ObjCIvar.
Definition: ASTMatchersInternal.cpp:891
InlinedFunctionCallHandler
Adds a ReturnVisitor if the given statement represents a call that was inlined.
Definition: BugReporterVisitors.cpp:2218
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:315
isVarAnInterestingCondition
static bool isVarAnInterestingCondition(const Expr *CondVarExpr, const ExplodedNode *N, const PathSensitiveBugReport *B)
Definition: BugReporterVisitors.cpp:238
clang::StmtPoint
Definition: ProgramPoint.h:271
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:3803
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:250
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:1711
clang::ento::BugReporterContext::getSourceManager
const SourceManager & getSourceManager() const
Definition: BugReporter.h:723
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:212
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:151
clang::ento::SymExpr
Symbolic value.
Definition: SymExpr.h:29
clang::ProgramPoint::getTag
const ProgramPointTag * getTag() const
Definition: ProgramPoint.h:177
clang::ento::PathDiagnosticLocation::isValid
bool isValid() const
Definition: PathDiagnostic.h:337
clang::CallExitEnd
Represents a point when we finish the call exit sequence (for inlined call).
Definition: ProgramPoint.h:688
clang::ento::PathSensitiveBugReport::getErrorNode
const ExplodedNode * getErrorNode() const
Definition: BugReporter.h:404
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:3229
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:2600
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:727
getMatchingCallExitEnd
static const ExplodedNode * getMatchingCallExitEnd(const ExplodedNode *N)
Definition: BugReporterVisitors.cpp:369
clang::CFGBlock::getLastCondition
const Expr * getLastCondition() const
Definition: CFG.cpp:5964
clang::PostStore
Represents a program point after a store evaluation.
Definition: ProgramPoint.h:431
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:1321
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
IdentifierTable.h
clang::ento::TagVisitor::Profile
void Profile(llvm::FoldingSetNodeID &ID) const override
Definition: BugReporterVisitors.cpp:3304
clang::DeclRefExpr::getDecl
ValueDecl * getDecl()
Definition: Expr.h:1289
clang::ento::SuppressInlineDefensiveChecksVisitor::Profile
void Profile(llvm::FoldingSetNodeID &ID) const override
Definition: BugReporterVisitors.cpp:1719
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:279
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:527
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:3351
clang::ento::ExplodedNode::getLocationAs
Optional< T > getLocationAs() const LLVM_LVALUE_FUNCTION
Definition: ExplodedGraph.h:172
clang::ento::BugReporterContext
Definition: BugReporter.h:703
clang::ast_matchers::binaryOperator
const internal::VariadicDynCastAllOfMatcher< Stmt, BinaryOperator > binaryOperator
Matches binary operator expressions.
Definition: ASTMatchersInternal.cpp:946
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:3292
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:993
ExprCXX.h
Base
clang::ento::SuppressInlineDefensiveChecksVisitor::getTag
static const char * getTag()
Return the tag associated with this visitor.
Definition: BugReporterVisitors.cpp:1726
clang::CFGBlock::getTerminatorCondition
Stmt * getTerminatorCondition(bool StripParens=true)
Definition: CFG.cpp:5992
clang::ento::PathDiagnosticPiece::getString
StringRef getString() const
Definition: PathDiagnostic.h:438
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:1411
clang::ento::KnownSVal
Represents an SVal that is guaranteed to not be UnknownVal.
Definition: SVals.h:291
x
IRgen optimization opportunities The common pattern of short x
Definition: README.txt:7
ExpressionHandler
ExplodedGraph.h
DefaultExpressionHandler
Definition: BugReporterVisitors.cpp:2301
clang::MemberExpr::getMemberDecl
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition: Expr.h:3245
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:327
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:3034
NilReceiverHandler
Definition: BugReporterVisitors.cpp:2099
clang::Type::isObjCObjectPointerType
bool isObjCObjectPointerType() const
Definition: Type.h:6795
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:2505
constructDebugPieceForTrackedCondition
static std::shared_ptr< PathDiagnosticEventPiece > constructDebugPieceForTrackedCondition(const Expr *Cond, const ExplodedNode *N, BugReporterContext &BRC)
Definition: BugReporterVisitors.cpp:1841
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:2924
clang::CXXRecordDecl
Represents a C++ struct/union/class.
Definition: DeclCXX.h:255
clang::PostStmt
Definition: ProgramPoint.h:311
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:1307
P
StringRef P
Definition: ASTMatchersInternal.cpp:563
clang::PreStmt
Definition: ProgramPoint.h:295
clang::ento::CallEventManager
Manages the lifetime of CallEvent objects.
Definition: CallEvent.h:1328
clang::Stmt::getStmtClass
StmtClass getStmtClass() const
Definition: Stmt.h:1163
clang::Type::isPointerType
bool isPointerType() const
Definition: Type.h:6673
clang::ento::PathSensitiveBugReport::getRanges
ArrayRef< SourceRange > getRanges() const override
Get the SourceRanges associated with the report.
Definition: BugReporter.cpp:2406
clang::ento::FalsePositiveRefutationBRVisitor::addConstraints
void addConstraints(const ExplodedNode *N, bool OverwriteConstraintsOnExistingSyms)
Definition: BugReporterVisitors.cpp:3266
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:676
clang::ento::ProgramStateManager::getCallEventManager
CallEventManager & getCallEventManager()
Definition: ProgramState.h:537
isPointerToConst
static bool isPointerToConst(QualType Ty)
Definition: BugReporterVisitors.cpp:709
clang::BinaryOperator::getLHS
Expr * getLHS() const
Definition: Expr.h:3852
clang::ento::ConditionBRVisitor::isPieceMessageGeneric
static bool isPieceMessageGeneric(const PathDiagnosticPiece *Piece)
Definition: BugReporterVisitors.cpp:3075
clang::CharSourceRange::getTokenRange
static CharSourceRange getTokenRange(SourceRange R)
Definition: SourceLocation.h:263
clang::DeclContext::getParent
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:1860
clang::RecordDecl::fields
field_range fields() const
Definition: Decl.h:4079
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:738
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:89
clang::BinaryOperator::isComparisonOp
bool isComparisonOp() const
Definition: Expr.h:3903
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:5926
clang::StackFrameContext::getCallSite
const Stmt * getCallSite() const
Definition: AnalysisDeclContext.h:321
clang::CharSourceRange
Represents a character-granular source range.
Definition: SourceLocation.h:255
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:341
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:1757
State
LineState State
Definition: UnwrappedLineFormatter.cpp:986
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:2727
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:1009
clang::ImplicitParamDecl::ObjCSelf
@ ObjCSelf
Parameter for Objective-C 'self' argument.
Definition: Decl.h:1610
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:2659
clang::SourceLocation::isMacroID
bool isMacroID() const
Definition: SourceLocation.h:105
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:292
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:7072
isAssertlikeBlock
static bool isAssertlikeBlock(const CFGBlock *B, ASTContext &Context)
Definition: BugReporterVisitors.cpp:1859
clang::DeclStmt
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1292
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:159
clang::ento::MemRegionManager
Definition: MemRegion.h:1302
ArrayIndexHandler
Definition: BugReporterVisitors.cpp:2117
clang::ento::PathSensitiveBugReport
Definition: BugReporter.h:291
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:3173
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:2008
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:2045
clang::Expr::IgnoreParens
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:2915
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:6677
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:805
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:1924
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:3854
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:405
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:2934
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:112
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:630
Dominators.h
clang::MemberExpr
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3162
clang::BlockEdge
Definition: ProgramPoint.h:503
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:2373
clang::ento::SVal
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition: SVals.h:75
clang::ento::ConditionBRVisitor::VisitNodeImpl
PathDiagnosticPieceRef VisitNodeImpl(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR)
Definition: BugReporterVisitors.cpp:2562
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::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:3888
clang::ValueDecl::getType
QualType getType() const
Definition: Decl.h:687
clang::Expr
This represents one expression.
Definition: Expr.h:109
SM
#define SM(sm)
Definition: Cuda.cpp:78
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:1731
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:719
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:3563
AnalysisManager.h
clang::ento::NoteTag
The tag upon which the TagVisitor reacts.
Definition: BugReporter.h:765
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:2416
clang::ento::BugReporterContext::getStateManager
ProgramStateManager & getStateManager() const
Definition: BugReporter.h:715
clang::DeclRefExpr
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1217
clang::LocationContext::getDecl
const Decl * getDecl() const
Definition: AnalysisDeclContext.h:247
clang::RecordDecl
Represents a struct/union/class.
Definition: Decl.h:3859
clang::ProgramPoint
Definition: ProgramPoint.h:59
clang::ObjCIvarRefExpr
ObjCIvarRefExpr - A reference to an ObjC instance variable.
Definition: ExprObjC.h:548
clang::ento::getConstraintMap
ConstraintMap getConstraintMap(ProgramStateRef State)
Definition: RangeConstraintManager.cpp:1767
clang::ASTContext::getLangOpts
const LangOptions & getLangOpts() const
Definition: ASTContext.h:765
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:7059
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:3085
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:3286
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:398
clang::NamedDecl::getName
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:276