clang  3.9.0
BugReporterVisitors.cpp
Go to the documentation of this file.
1 // BugReporterVisitors.cpp - Helpers for reporting bugs -----------*- C++ -*--//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines a set of BugReporter "visitors" which can be used to
11 // enhance the diagnostics reported for a bug.
12 //
13 //===----------------------------------------------------------------------===//
15 #include "clang/AST/Expr.h"
16 #include "clang/AST/ExprObjC.h"
24 #include "llvm/ADT/SmallString.h"
25 #include "llvm/ADT/StringExtras.h"
26 #include "llvm/Support/raw_ostream.h"
27 
28 using namespace clang;
29 using namespace ento;
30 
31 using llvm::FoldingSetNodeID;
32 
33 //===----------------------------------------------------------------------===//
34 // Utility functions.
35 //===----------------------------------------------------------------------===//
36 
38  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
39  return DRE->getDecl()->getType()->isReferenceType();
40  }
41  return false;
42 }
43 
45  // Pattern match for a few useful cases:
46  // a[0], p->f, *p
47  const Expr *E = dyn_cast<Expr>(S);
48  if (!E)
49  return nullptr;
50  E = E->IgnoreParenCasts();
51 
52  while (true) {
53  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) {
54  assert(B->isAssignmentOp());
55  E = B->getLHS()->IgnoreParenCasts();
56  continue;
57  }
58  else if (const UnaryOperator *U = dyn_cast<UnaryOperator>(E)) {
59  if (U->getOpcode() == UO_Deref)
60  return U->getSubExpr()->IgnoreParenCasts();
61  }
62  else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
63  if (ME->isArrow() || isDeclRefExprToReference(ME->getBase())) {
64  return ME->getBase()->IgnoreParenCasts();
65  } else {
66  // If we have a member expr with a dot, the base must have been
67  // dereferenced.
68  return getDerefExpr(ME->getBase());
69  }
70  }
71  else if (const ObjCIvarRefExpr *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) {
72  return IvarRef->getBase()->IgnoreParenCasts();
73  }
74  else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(E)) {
75  return AE->getBase();
76  }
77  else if (isDeclRefExprToReference(E)) {
78  return E;
79  }
80  break;
81  }
82 
83  return nullptr;
84 }
85 
87  const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
88  if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S))
89  return BE->getRHS();
90  return nullptr;
91 }
92 
94  const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
95  if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S))
96  return RS->getRetValue();
97  return nullptr;
98 }
99 
100 //===----------------------------------------------------------------------===//
101 // Definitions for bug reporter visitors.
102 //===----------------------------------------------------------------------===//
103 
104 std::unique_ptr<PathDiagnosticPiece>
106  const ExplodedNode *EndPathNode, BugReport &BR) {
107  return nullptr;
108 }
109 
110 std::unique_ptr<PathDiagnosticPiece> BugReporterVisitor::getDefaultEndPath(
111  BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) {
114 
115  const auto &Ranges = BR.getRanges();
116 
117  // Only add the statement itself as a range if we didn't specify any
118  // special ranges for this report.
119  auto P = llvm::make_unique<PathDiagnosticEventPiece>(
120  L, BR.getDescription(), Ranges.begin() == Ranges.end());
121  for (SourceRange Range : Ranges)
122  P->addRange(Range);
123 
124  return std::move(P);
125 }
126 
127 
128 namespace {
129 /// Emits an extra note at the return statement of an interesting stack frame.
130 ///
131 /// The returned value is marked as an interesting value, and if it's null,
132 /// adds a visitor to track where it became null.
133 ///
134 /// This visitor is intended to be used when another visitor discovers that an
135 /// interesting value comes from an inlined function call.
136 class ReturnVisitor : public BugReporterVisitorImpl<ReturnVisitor> {
137  const StackFrameContext *StackFrame;
138  enum {
139  Initial,
140  MaybeUnsuppress,
141  Satisfied
142  } Mode;
143 
144  bool EnableNullFPSuppression;
145 
146 public:
147  ReturnVisitor(const StackFrameContext *Frame, bool Suppressed)
148  : StackFrame(Frame), Mode(Initial), EnableNullFPSuppression(Suppressed) {}
149 
150  static void *getTag() {
151  static int Tag = 0;
152  return static_cast<void *>(&Tag);
153  }
154 
155  void Profile(llvm::FoldingSetNodeID &ID) const override {
156  ID.AddPointer(ReturnVisitor::getTag());
157  ID.AddPointer(StackFrame);
158  ID.AddBoolean(EnableNullFPSuppression);
159  }
160 
161  /// Adds a ReturnVisitor if the given statement represents a call that was
162  /// inlined.
163  ///
164  /// This will search back through the ExplodedGraph, starting from the given
165  /// node, looking for when the given statement was processed. If it turns out
166  /// the statement is a call that was inlined, we add the visitor to the
167  /// bug report, so it can print a note later.
168  static void addVisitorIfNecessary(const ExplodedNode *Node, const Stmt *S,
169  BugReport &BR,
170  bool InEnableNullFPSuppression) {
171  if (!CallEvent::isCallStmt(S))
172  return;
173 
174  // First, find when we processed the statement.
175  do {
177  if (CEE->getCalleeContext()->getCallSite() == S)
178  break;
179  if (Optional<StmtPoint> SP = Node->getLocationAs<StmtPoint>())
180  if (SP->getStmt() == S)
181  break;
182 
183  Node = Node->getFirstPred();
184  } while (Node);
185 
186  // Next, step over any post-statement checks.
187  while (Node && Node->getLocation().getAs<PostStmt>())
188  Node = Node->getFirstPred();
189  if (!Node)
190  return;
191 
192  // Finally, see if we inlined the call.
194  if (!CEE)
195  return;
196 
197  const StackFrameContext *CalleeContext = CEE->getCalleeContext();
198  if (CalleeContext->getCallSite() != S)
199  return;
200 
201  // Check the return value.
202  ProgramStateRef State = Node->getState();
203  SVal RetVal = State->getSVal(S, Node->getLocationContext());
204 
205  // Handle cases where a reference is returned and then immediately used.
206  if (cast<Expr>(S)->isGLValue())
207  if (Optional<Loc> LValue = RetVal.getAs<Loc>())
208  RetVal = State->getSVal(*LValue);
209 
210  // See if the return value is NULL. If so, suppress the report.
211  SubEngine *Eng = State->getStateManager().getOwningEngine();
212  assert(Eng && "Cannot file a bug report without an owning engine");
214 
215  bool EnableNullFPSuppression = false;
216  if (InEnableNullFPSuppression && Options.shouldSuppressNullReturnPaths())
217  if (Optional<Loc> RetLoc = RetVal.getAs<Loc>())
218  EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
219 
220  BR.markInteresting(CalleeContext);
221  BR.addVisitor(llvm::make_unique<ReturnVisitor>(CalleeContext,
222  EnableNullFPSuppression));
223  }
224 
225  /// Returns true if any counter-suppression heuristics are enabled for
226  /// ReturnVisitor.
227  static bool hasCounterSuppression(AnalyzerOptions &Options) {
229  }
230 
231  PathDiagnosticPiece *visitNodeInitial(const ExplodedNode *N,
232  const ExplodedNode *PrevN,
233  BugReporterContext &BRC,
234  BugReport &BR) {
235  // Only print a message at the interesting return statement.
236  if (N->getLocationContext() != StackFrame)
237  return nullptr;
238 
240  if (!SP)
241  return nullptr;
242 
243  const ReturnStmt *Ret = dyn_cast<ReturnStmt>(SP->getStmt());
244  if (!Ret)
245  return nullptr;
246 
247  // Okay, we're at the right return statement, but do we have the return
248  // value available?
249  ProgramStateRef State = N->getState();
250  SVal V = State->getSVal(Ret, StackFrame);
251  if (V.isUnknownOrUndef())
252  return nullptr;
253 
254  // Don't print any more notes after this one.
255  Mode = Satisfied;
256 
257  const Expr *RetE = Ret->getRetValue();
258  assert(RetE && "Tracking a return value for a void function");
259 
260  // Handle cases where a reference is returned and then immediately used.
261  Optional<Loc> LValue;
262  if (RetE->isGLValue()) {
263  if ((LValue = V.getAs<Loc>())) {
264  SVal RValue = State->getRawSVal(*LValue, RetE->getType());
265  if (RValue.getAs<DefinedSVal>())
266  V = RValue;
267  }
268  }
269 
270  // Ignore aggregate rvalues.
271  if (V.getAs<nonloc::LazyCompoundVal>() ||
273  return nullptr;
274 
275  RetE = RetE->IgnoreParenCasts();
276 
277  // If we can't prove the return value is 0, just mark it interesting, and
278  // make sure to track it into any further inner functions.
279  if (!State->isNull(V).isConstrainedTrue()) {
280  BR.markInteresting(V);
281  ReturnVisitor::addVisitorIfNecessary(N, RetE, BR,
282  EnableNullFPSuppression);
283  return nullptr;
284  }
285 
286  // If we're returning 0, we should track where that 0 came from.
287  bugreporter::trackNullOrUndefValue(N, RetE, BR, /*IsArg*/ false,
288  EnableNullFPSuppression);
289 
290  // Build an appropriate message based on the return value.
291  SmallString<64> Msg;
292  llvm::raw_svector_ostream Out(Msg);
293 
294  if (V.getAs<Loc>()) {
295  // If we have counter-suppression enabled, make sure we keep visiting
296  // future nodes. We want to emit a path note as well, in case
297  // the report is resurrected as valid later on.
298  ExprEngine &Eng = BRC.getBugReporter().getEngine();
299  AnalyzerOptions &Options = Eng.getAnalysisManager().options;
300  if (EnableNullFPSuppression && hasCounterSuppression(Options))
301  Mode = MaybeUnsuppress;
302 
303  if (RetE->getType()->isObjCObjectPointerType())
304  Out << "Returning nil";
305  else
306  Out << "Returning null pointer";
307  } else {
308  Out << "Returning zero";
309  }
310 
311  if (LValue) {
312  if (const MemRegion *MR = LValue->getAsRegion()) {
313  if (MR->canPrintPretty()) {
314  Out << " (reference to ";
315  MR->printPretty(Out);
316  Out << ")";
317  }
318  }
319  } else {
320  // FIXME: We should have a more generalized location printing mechanism.
321  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(RetE))
322  if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(DR->getDecl()))
323  Out << " (loaded from '" << *DD << "')";
324  }
325 
326  PathDiagnosticLocation L(Ret, BRC.getSourceManager(), StackFrame);
327  if (!L.isValid() || !L.asLocation().isValid())
328  return nullptr;
329 
330  return new PathDiagnosticEventPiece(L, Out.str());
331  }
332 
333  PathDiagnosticPiece *visitNodeMaybeUnsuppress(const ExplodedNode *N,
334  const ExplodedNode *PrevN,
335  BugReporterContext &BRC,
336  BugReport &BR) {
337 #ifndef NDEBUG
338  ExprEngine &Eng = BRC.getBugReporter().getEngine();
339  AnalyzerOptions &Options = Eng.getAnalysisManager().options;
340  assert(hasCounterSuppression(Options));
341 #endif
342 
343  // Are we at the entry node for this call?
345  if (!CE)
346  return nullptr;
347 
348  if (CE->getCalleeContext() != StackFrame)
349  return nullptr;
350 
351  Mode = Satisfied;
352 
353  // Don't automatically suppress a report if one of the arguments is
354  // known to be a null pointer. Instead, start tracking /that/ null
355  // value back to its origin.
356  ProgramStateManager &StateMgr = BRC.getStateManager();
357  CallEventManager &CallMgr = StateMgr.getCallEventManager();
358 
359  ProgramStateRef State = N->getState();
360  CallEventRef<> Call = CallMgr.getCaller(StackFrame, State);
361  for (unsigned I = 0, E = Call->getNumArgs(); I != E; ++I) {
362  Optional<Loc> ArgV = Call->getArgSVal(I).getAs<Loc>();
363  if (!ArgV)
364  continue;
365 
366  const Expr *ArgE = Call->getArgExpr(I);
367  if (!ArgE)
368  continue;
369 
370  // Is it possible for this argument to be non-null?
371  if (!State->isNull(*ArgV).isConstrainedTrue())
372  continue;
373 
374  if (bugreporter::trackNullOrUndefValue(N, ArgE, BR, /*IsArg=*/true,
375  EnableNullFPSuppression))
376  BR.removeInvalidation(ReturnVisitor::getTag(), StackFrame);
377 
378  // If we /can't/ track the null pointer, we should err on the side of
379  // false negatives, and continue towards marking this report invalid.
380  // (We will still look at the other arguments, though.)
381  }
382 
383  return nullptr;
384  }
385 
386  PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
387  const ExplodedNode *PrevN,
388  BugReporterContext &BRC,
389  BugReport &BR) override {
390  switch (Mode) {
391  case Initial:
392  return visitNodeInitial(N, PrevN, BRC, BR);
393  case MaybeUnsuppress:
394  return visitNodeMaybeUnsuppress(N, PrevN, BRC, BR);
395  case Satisfied:
396  return nullptr;
397  }
398 
399  llvm_unreachable("Invalid visit mode!");
400  }
401 
402  std::unique_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
403  const ExplodedNode *N,
404  BugReport &BR) override {
405  if (EnableNullFPSuppression)
406  BR.markInvalid(ReturnVisitor::getTag(), StackFrame);
407  return nullptr;
408  }
409 };
410 } // end anonymous namespace
411 
412 
413 void FindLastStoreBRVisitor ::Profile(llvm::FoldingSetNodeID &ID) const {
414  static int tag = 0;
415  ID.AddPointer(&tag);
416  ID.AddPointer(R);
417  ID.Add(V);
418  ID.AddBoolean(EnableNullFPSuppression);
419 }
420 
421 /// Returns true if \p N represents the DeclStmt declaring and initializing
422 /// \p VR.
423 static bool isInitializationOfVar(const ExplodedNode *N, const VarRegion *VR) {
425  if (!P)
426  return false;
427 
428  const DeclStmt *DS = P->getStmtAs<DeclStmt>();
429  if (!DS)
430  return false;
431 
432  if (DS->getSingleDecl() != VR->getDecl())
433  return false;
434 
435  const MemSpaceRegion *VarSpace = VR->getMemorySpace();
436  const StackSpaceRegion *FrameSpace = dyn_cast<StackSpaceRegion>(VarSpace);
437  if (!FrameSpace) {
438  // If we ever directly evaluate global DeclStmts, this assertion will be
439  // invalid, but this still seems preferable to silently accepting an
440  // initialization that may be for a path-sensitive variable.
441  assert(VR->getDecl()->isStaticLocal() && "non-static stackless VarRegion");
442  return true;
443  }
444 
445  assert(VR->getDecl()->hasLocalStorage());
446  const LocationContext *LCtx = N->getLocationContext();
447  return FrameSpace->getStackFrame() == LCtx->getCurrentStackFrame();
448 }
449 
451  const ExplodedNode *Pred,
452  BugReporterContext &BRC,
453  BugReport &BR) {
454 
455  if (Satisfied)
456  return nullptr;
457 
458  const ExplodedNode *StoreSite = nullptr;
459  const Expr *InitE = nullptr;
460  bool IsParam = false;
461 
462  // First see if we reached the declaration of the region.
463  if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
464  if (isInitializationOfVar(Pred, VR)) {
465  StoreSite = Pred;
466  InitE = VR->getDecl()->getInit();
467  }
468  }
469 
470  // If this is a post initializer expression, initializing the region, we
471  // should track the initializer expression.
473  const MemRegion *FieldReg = (const MemRegion *)PIP->getLocationValue();
474  if (FieldReg && FieldReg == R) {
475  StoreSite = Pred;
476  InitE = PIP->getInitializer()->getInit();
477  }
478  }
479 
480  // Otherwise, see if this is the store site:
481  // (1) Succ has this binding and Pred does not, i.e. this is
482  // where the binding first occurred.
483  // (2) Succ has this binding and is a PostStore node for this region, i.e.
484  // the same binding was re-assigned here.
485  if (!StoreSite) {
486  if (Succ->getState()->getSVal(R) != V)
487  return nullptr;
488 
489  if (Pred->getState()->getSVal(R) == V) {
491  if (!PS || PS->getLocationValue() != R)
492  return nullptr;
493  }
494 
495  StoreSite = Succ;
496 
497  // If this is an assignment expression, we can track the value
498  // being assigned.
500  if (const BinaryOperator *BO = P->getStmtAs<BinaryOperator>())
501  if (BO->isAssignmentOp())
502  InitE = BO->getRHS();
503 
504  // If this is a call entry, the variable should be a parameter.
505  // FIXME: Handle CXXThisRegion as well. (This is not a priority because
506  // 'this' should never be NULL, but this visitor isn't just for NULL and
507  // UndefinedVal.)
508  if (Optional<CallEnter> CE = Succ->getLocationAs<CallEnter>()) {
509  if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
510  const ParmVarDecl *Param = cast<ParmVarDecl>(VR->getDecl());
511 
512  ProgramStateManager &StateMgr = BRC.getStateManager();
513  CallEventManager &CallMgr = StateMgr.getCallEventManager();
514 
515  CallEventRef<> Call = CallMgr.getCaller(CE->getCalleeContext(),
516  Succ->getState());
517  InitE = Call->getArgExpr(Param->getFunctionScopeIndex());
518  IsParam = true;
519  }
520  }
521 
522  // If this is a CXXTempObjectRegion, the Expr responsible for its creation
523  // is wrapped inside of it.
524  if (const CXXTempObjectRegion *TmpR = dyn_cast<CXXTempObjectRegion>(R))
525  InitE = TmpR->getExpr();
526  }
527 
528  if (!StoreSite)
529  return nullptr;
530  Satisfied = true;
531 
532  // If we have an expression that provided the value, try to track where it
533  // came from.
534  if (InitE) {
535  if (V.isUndef() ||
537  if (!IsParam)
538  InitE = InitE->IgnoreParenCasts();
539  bugreporter::trackNullOrUndefValue(StoreSite, InitE, BR, IsParam,
540  EnableNullFPSuppression);
541  } else {
542  ReturnVisitor::addVisitorIfNecessary(StoreSite, InitE->IgnoreParenCasts(),
543  BR, EnableNullFPSuppression);
544  }
545  }
546 
547  // Okay, we've found the binding. Emit an appropriate message.
548  SmallString<256> sbuf;
549  llvm::raw_svector_ostream os(sbuf);
550 
551  if (Optional<PostStmt> PS = StoreSite->getLocationAs<PostStmt>()) {
552  const Stmt *S = PS->getStmt();
553  const char *action = nullptr;
554  const DeclStmt *DS = dyn_cast<DeclStmt>(S);
555  const VarRegion *VR = dyn_cast<VarRegion>(R);
556 
557  if (DS) {
558  action = R->canPrintPretty() ? "initialized to " :
559  "Initializing to ";
560  } else if (isa<BlockExpr>(S)) {
561  action = R->canPrintPretty() ? "captured by block as " :
562  "Captured by block as ";
563  if (VR) {
564  // See if we can get the BlockVarRegion.
565  ProgramStateRef State = StoreSite->getState();
566  SVal V = State->getSVal(S, PS->getLocationContext());
567  if (const BlockDataRegion *BDR =
568  dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
569  if (const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) {
570  if (Optional<KnownSVal> KV =
571  State->getSVal(OriginalR).getAs<KnownSVal>())
572  BR.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
573  *KV, OriginalR, EnableNullFPSuppression));
574  }
575  }
576  }
577  }
578 
579  if (action) {
580  if (R->canPrintPretty()) {
581  R->printPretty(os);
582  os << " ";
583  }
584 
585  if (V.getAs<loc::ConcreteInt>()) {
586  bool b = false;
587  if (R->isBoundable()) {
588  if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
589  if (TR->getValueType()->isObjCObjectPointerType()) {
590  os << action << "nil";
591  b = true;
592  }
593  }
594  }
595 
596  if (!b)
597  os << action << "a null pointer value";
598  } else if (Optional<nonloc::ConcreteInt> CVal =
599  V.getAs<nonloc::ConcreteInt>()) {
600  os << action << CVal->getValue();
601  }
602  else if (DS) {
603  if (V.isUndef()) {
604  if (isa<VarRegion>(R)) {
605  const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
606  if (VD->getInit()) {
607  os << (R->canPrintPretty() ? "initialized" : "Initializing")
608  << " to a garbage value";
609  } else {
610  os << (R->canPrintPretty() ? "declared" : "Declaring")
611  << " without an initial value";
612  }
613  }
614  }
615  else {
616  os << (R->canPrintPretty() ? "initialized" : "Initialized")
617  << " here";
618  }
619  }
620  }
621  } else if (StoreSite->getLocation().getAs<CallEnter>()) {
622  if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
623  const ParmVarDecl *Param = cast<ParmVarDecl>(VR->getDecl());
624 
625  os << "Passing ";
626 
627  if (V.getAs<loc::ConcreteInt>()) {
628  if (Param->getType()->isObjCObjectPointerType())
629  os << "nil object reference";
630  else
631  os << "null pointer value";
632  } else if (V.isUndef()) {
633  os << "uninitialized value";
634  } else if (Optional<nonloc::ConcreteInt> CI =
635  V.getAs<nonloc::ConcreteInt>()) {
636  os << "the value " << CI->getValue();
637  } else {
638  os << "value";
639  }
640 
641  // Printed parameter indexes are 1-based, not 0-based.
642  unsigned Idx = Param->getFunctionScopeIndex() + 1;
643  os << " via " << Idx << llvm::getOrdinalSuffix(Idx) << " parameter";
644  if (R->canPrintPretty()) {
645  os << " ";
646  R->printPretty(os);
647  }
648  }
649  }
650 
651  if (os.str().empty()) {
652  if (V.getAs<loc::ConcreteInt>()) {
653  bool b = false;
654  if (R->isBoundable()) {
655  if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
656  if (TR->getValueType()->isObjCObjectPointerType()) {
657  os << "nil object reference stored";
658  b = true;
659  }
660  }
661  }
662  if (!b) {
663  if (R->canPrintPretty())
664  os << "Null pointer value stored";
665  else
666  os << "Storing null pointer value";
667  }
668 
669  } else if (V.isUndef()) {
670  if (R->canPrintPretty())
671  os << "Uninitialized value stored";
672  else
673  os << "Storing uninitialized value";
674 
675  } else if (Optional<nonloc::ConcreteInt> CV =
676  V.getAs<nonloc::ConcreteInt>()) {
677  if (R->canPrintPretty())
678  os << "The value " << CV->getValue() << " is assigned";
679  else
680  os << "Assigning " << CV->getValue();
681 
682  } else {
683  if (R->canPrintPretty())
684  os << "Value assigned";
685  else
686  os << "Assigning value";
687  }
688 
689  if (R->canPrintPretty()) {
690  os << " to ";
691  R->printPretty(os);
692  }
693  }
694 
695  // Construct a new PathDiagnosticPiece.
696  ProgramPoint P = StoreSite->getLocation();
698  if (P.getAs<CallEnter>() && InitE)
699  L = PathDiagnosticLocation(InitE, BRC.getSourceManager(),
700  P.getLocationContext());
701 
702  if (!L.isValid() || !L.asLocation().isValid())
704 
705  if (!L.isValid() || !L.asLocation().isValid())
706  return nullptr;
707 
708  return new PathDiagnosticEventPiece(L, os.str());
709 }
710 
711 void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
712  static int tag = 0;
713  ID.AddPointer(&tag);
714  ID.AddBoolean(Assumption);
715  ID.Add(Constraint);
716 }
717 
718 /// Return the tag associated with this visitor. This tag will be used
719 /// to make all PathDiagnosticPieces created by this visitor.
721  return "TrackConstraintBRVisitor";
722 }
723 
724 bool TrackConstraintBRVisitor::isUnderconstrained(const ExplodedNode *N) const {
725  if (IsZeroCheck)
726  return N->getState()->isNull(Constraint).isUnderconstrained();
727  return (bool)N->getState()->assume(Constraint, !Assumption);
728 }
729 
732  const ExplodedNode *PrevN,
733  BugReporterContext &BRC,
734  BugReport &BR) {
735  if (IsSatisfied)
736  return nullptr;
737 
738  // Start tracking after we see the first state in which the value is
739  // constrained.
740  if (!IsTrackingTurnedOn)
741  if (!isUnderconstrained(N))
742  IsTrackingTurnedOn = true;
743  if (!IsTrackingTurnedOn)
744  return nullptr;
745 
746  // Check if in the previous state it was feasible for this constraint
747  // to *not* be true.
748  if (isUnderconstrained(PrevN)) {
749 
750  IsSatisfied = true;
751 
752  // As a sanity check, make sure that the negation of the constraint
753  // was infeasible in the current state. If it is feasible, we somehow
754  // missed the transition point.
755  assert(!isUnderconstrained(N));
756 
757  // We found the transition point for the constraint. We now need to
758  // pretty-print the constraint. (work-in-progress)
759  SmallString<64> sbuf;
760  llvm::raw_svector_ostream os(sbuf);
761 
762  if (Constraint.getAs<Loc>()) {
763  os << "Assuming pointer value is ";
764  os << (Assumption ? "non-null" : "null");
765  }
766 
767  if (os.str().empty())
768  return nullptr;
769 
770  // Construct a new PathDiagnosticPiece.
771  ProgramPoint P = N->getLocation();
774  if (!L.isValid())
775  return nullptr;
776 
778  X->setTag(getTag());
779  return X;
780  }
781 
782  return nullptr;
783 }
784 
787  : V(Value), IsSatisfied(false), IsTrackingTurnedOn(false) {
788 
789  // Check if the visitor is disabled.
790  SubEngine *Eng = N->getState()->getStateManager().getOwningEngine();
791  assert(Eng && "Cannot file a bug report without an owning engine");
792  AnalyzerOptions &Options = Eng->getAnalysisManager().options;
794  IsSatisfied = true;
795 
796  assert(N->getState()->isNull(V).isConstrainedTrue() &&
797  "The visitor only tracks the cases where V is constrained to 0");
798 }
799 
800 void SuppressInlineDefensiveChecksVisitor::Profile(FoldingSetNodeID &ID) const {
801  static int id = 0;
802  ID.AddPointer(&id);
803  ID.Add(V);
804 }
805 
807  return "IDCVisitor";
808 }
809 
812  const ExplodedNode *Pred,
813  BugReporterContext &BRC,
814  BugReport &BR) {
815  if (IsSatisfied)
816  return nullptr;
817 
818  // Start tracking after we see the first state in which the value is null.
819  if (!IsTrackingTurnedOn)
820  if (Succ->getState()->isNull(V).isConstrainedTrue())
821  IsTrackingTurnedOn = true;
822  if (!IsTrackingTurnedOn)
823  return nullptr;
824 
825  // Check if in the previous state it was feasible for this value
826  // to *not* be null.
827  if (!Pred->getState()->isNull(V).isConstrainedTrue()) {
828  IsSatisfied = true;
829 
830  assert(Succ->getState()->isNull(V).isConstrainedTrue());
831 
832  // Check if this is inlined defensive checks.
833  const LocationContext *CurLC =Succ->getLocationContext();
834  const LocationContext *ReportLC = BR.getErrorNode()->getLocationContext();
835  if (CurLC != ReportLC && !CurLC->isParentOf(ReportLC)) {
836  BR.markInvalid("Suppress IDC", CurLC);
837  return nullptr;
838  }
839 
840  // Treat defensive checks in function-like macros as if they were an inlined
841  // defensive check. If the bug location is not in a macro and the
842  // terminator for the current location is in a macro then suppress the
843  // warning.
844  auto BugPoint = BR.getErrorNode()->getLocation().getAs<StmtPoint>();
845 
846  if (!BugPoint)
847  return nullptr;
848 
849  SourceLocation BugLoc = BugPoint->getStmt()->getLocStart();
850  if (BugLoc.isMacroID())
851  return nullptr;
852 
853  ProgramPoint CurPoint = Succ->getLocation();
854  const Stmt *CurTerminatorStmt = nullptr;
855  if (auto BE = CurPoint.getAs<BlockEdge>()) {
856  CurTerminatorStmt = BE->getSrc()->getTerminator().getStmt();
857  } else if (auto SP = CurPoint.getAs<StmtPoint>()) {
858  const Stmt *CurStmt = SP->getStmt();
859  if (!CurStmt->getLocStart().isMacroID())
860  return nullptr;
861 
862  CFGStmtMap *Map = CurLC->getAnalysisDeclContext()->getCFGStmtMap();
863  CurTerminatorStmt = Map->getBlock(CurStmt)->getTerminator();
864  } else {
865  return nullptr;
866  }
867 
868  if (!CurTerminatorStmt)
869  return nullptr;
870 
871  SourceLocation TerminatorLoc = CurTerminatorStmt->getLocStart();
872  if (TerminatorLoc.isMacroID()) {
873  const SourceManager &SMgr = BRC.getSourceManager();
874  std::pair<FileID, unsigned> TLInfo = SMgr.getDecomposedLoc(TerminatorLoc);
875  SrcMgr::SLocEntry SE = SMgr.getSLocEntry(TLInfo.first);
876  const SrcMgr::ExpansionInfo &EInfo = SE.getExpansion();
877  if (EInfo.isFunctionMacroExpansion()) {
878  BR.markInvalid("Suppress Macro IDC", CurLC);
879  return nullptr;
880  }
881  }
882  }
883  return nullptr;
884 }
885 
887  const ExplodedNode *N) {
888  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) {
889  if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
890  if (!VD->getType()->isReferenceType())
891  return nullptr;
892  ProgramStateManager &StateMgr = N->getState()->getStateManager();
893  MemRegionManager &MRMgr = StateMgr.getRegionManager();
894  return MRMgr.getVarRegion(VD, N->getLocationContext());
895  }
896  }
897 
898  // FIXME: This does not handle other kinds of null references,
899  // for example, references from FieldRegions:
900  // struct Wrapper { int &ref; };
901  // Wrapper w = { *(int *)0 };
902  // w.ref = 1;
903 
904  return nullptr;
905 }
906 
907 static const Expr *peelOffOuterExpr(const Expr *Ex,
908  const ExplodedNode *N) {
909  Ex = Ex->IgnoreParenCasts();
910  if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Ex))
911  return peelOffOuterExpr(EWC->getSubExpr(), N);
912  if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Ex))
913  return peelOffOuterExpr(OVE->getSourceExpr(), N);
914  if (auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {
915  auto *PropRef = dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
916  if (PropRef && PropRef->isMessagingGetter()) {
917  const Expr *GetterMessageSend =
918  POE->getSemanticExpr(POE->getNumSemanticExprs() - 1);
919  assert(isa<ObjCMessageExpr>(GetterMessageSend));
920  return peelOffOuterExpr(GetterMessageSend, N);
921  }
922  }
923 
924  // Peel off the ternary operator.
925  if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(Ex)) {
926  // Find a node where the branching occurred and find out which branch
927  // we took (true/false) by looking at the ExplodedGraph.
928  const ExplodedNode *NI = N;
929  do {
930  ProgramPoint ProgPoint = NI->getLocation();
931  if (Optional<BlockEdge> BE = ProgPoint.getAs<BlockEdge>()) {
932  const CFGBlock *srcBlk = BE->getSrc();
933  if (const Stmt *term = srcBlk->getTerminator()) {
934  if (term == CO) {
935  bool TookTrueBranch = (*(srcBlk->succ_begin()) == BE->getDst());
936  if (TookTrueBranch)
937  return peelOffOuterExpr(CO->getTrueExpr(), N);
938  else
939  return peelOffOuterExpr(CO->getFalseExpr(), N);
940  }
941  }
942  }
943  NI = NI->getFirstPred();
944  } while (NI);
945  }
946  return Ex;
947 }
948 
950  const Stmt *S,
951  BugReport &report, bool IsArg,
952  bool EnableNullFPSuppression) {
953  if (!S || !N)
954  return false;
955 
956  if (const Expr *Ex = dyn_cast<Expr>(S)) {
957  Ex = Ex->IgnoreParenCasts();
958  const Expr *PeeledEx = peelOffOuterExpr(Ex, N);
959  if (Ex != PeeledEx)
960  S = PeeledEx;
961  }
962 
963  const Expr *Inner = nullptr;
964  if (const Expr *Ex = dyn_cast<Expr>(S)) {
965  Ex = Ex->IgnoreParenCasts();
967  Inner = Ex;
968  }
969 
970  if (IsArg && !Inner) {
971  assert(N->getLocation().getAs<CallEnter>() && "Tracking arg but not at call");
972  } else {
973  // Walk through nodes until we get one that matches the statement exactly.
974  // Alternately, if we hit a known lvalue for the statement, we know we've
975  // gone too far (though we can likely track the lvalue better anyway).
976  do {
977  const ProgramPoint &pp = N->getLocation();
978  if (Optional<StmtPoint> ps = pp.getAs<StmtPoint>()) {
979  if (ps->getStmt() == S || ps->getStmt() == Inner)
980  break;
981  } else if (Optional<CallExitEnd> CEE = pp.getAs<CallExitEnd>()) {
982  if (CEE->getCalleeContext()->getCallSite() == S ||
983  CEE->getCalleeContext()->getCallSite() == Inner)
984  break;
985  }
986  N = N->getFirstPred();
987  } while (N);
988 
989  if (!N)
990  return false;
991  }
992 
994 
995  // The message send could be nil due to the receiver being nil.
996  // At this point in the path, the receiver should be live since we are at the
997  // message send expr. If it is nil, start tracking it.
998  if (const Expr *Receiver = NilReceiverBRVisitor::getNilReceiver(S, N))
999  trackNullOrUndefValue(N, Receiver, report, false, EnableNullFPSuppression);
1000 
1001 
1002  // See if the expression we're interested refers to a variable.
1003  // If so, we can track both its contents and constraints on its value.
1004  if (Inner && ExplodedGraph::isInterestingLValueExpr(Inner)) {
1005  const MemRegion *R = nullptr;
1006 
1007  // Find the ExplodedNode where the lvalue (the value of 'Ex')
1008  // was computed. We need this for getting the location value.
1009  const ExplodedNode *LVNode = N;
1010  while (LVNode) {
1011  if (Optional<PostStmt> P = LVNode->getLocation().getAs<PostStmt>()) {
1012  if (P->getStmt() == Inner)
1013  break;
1014  }
1015  LVNode = LVNode->getFirstPred();
1016  }
1017  assert(LVNode && "Unable to find the lvalue node.");
1018  ProgramStateRef LVState = LVNode->getState();
1019  SVal LVal = LVState->getSVal(Inner, LVNode->getLocationContext());
1020 
1021  if (LVState->isNull(LVal).isConstrainedTrue()) {
1022  // In case of C++ references, we want to differentiate between a null
1023  // reference and reference to null pointer.
1024  // If the LVal is null, check if we are dealing with null reference.
1025  // For those, we want to track the location of the reference.
1026  if (const MemRegion *RR = getLocationRegionIfReference(Inner, N))
1027  R = RR;
1028  } else {
1029  R = LVState->getSVal(Inner, LVNode->getLocationContext()).getAsRegion();
1030 
1031  // If this is a C++ reference to a null pointer, we are tracking the
1032  // pointer. In additon, we should find the store at which the reference
1033  // got initialized.
1034  if (const MemRegion *RR = getLocationRegionIfReference(Inner, N)) {
1035  if (Optional<KnownSVal> KV = LVal.getAs<KnownSVal>())
1036  report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1037  *KV, RR, EnableNullFPSuppression));
1038  }
1039  }
1040 
1041  if (R) {
1042  // Mark both the variable region and its contents as interesting.
1043  SVal V = LVState->getRawSVal(loc::MemRegionVal(R));
1044 
1045  report.markInteresting(R);
1046  report.markInteresting(V);
1047  report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(R));
1048 
1049  // If the contents are symbolic, find out when they became null.
1050  if (V.getAsLocSymbol(/*IncludeBaseRegions*/ true))
1051  report.addVisitor(llvm::make_unique<TrackConstraintBRVisitor>(
1052  V.castAs<DefinedSVal>(), false));
1053 
1054  // Add visitor, which will suppress inline defensive checks.
1055  if (Optional<DefinedSVal> DV = V.getAs<DefinedSVal>()) {
1056  if (!DV->isZeroConstant() && LVState->isNull(*DV).isConstrainedTrue() &&
1057  EnableNullFPSuppression) {
1058  report.addVisitor(
1059  llvm::make_unique<SuppressInlineDefensiveChecksVisitor>(*DV,
1060  LVNode));
1061  }
1062  }
1063 
1064  if (Optional<KnownSVal> KV = V.getAs<KnownSVal>())
1065  report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1066  *KV, R, EnableNullFPSuppression));
1067  return true;
1068  }
1069  }
1070 
1071  // If the expression is not an "lvalue expression", we can still
1072  // track the constraints on its contents.
1073  SVal V = state->getSValAsScalarOrLoc(S, N->getLocationContext());
1074 
1075  // If the value came from an inlined function call, we should at least make
1076  // sure that function isn't pruned in our output.
1077  if (const Expr *E = dyn_cast<Expr>(S))
1078  S = E->IgnoreParenCasts();
1079 
1080  ReturnVisitor::addVisitorIfNecessary(N, S, report, EnableNullFPSuppression);
1081 
1082  // Uncomment this to find cases where we aren't properly getting the
1083  // base value that was dereferenced.
1084  // assert(!V.isUnknownOrUndef());
1085  // Is it a symbolic value?
1087  // At this point we are dealing with the region's LValue.
1088  // However, if the rvalue is a symbolic region, we should track it as well.
1089  // Try to use the correct type when looking up the value.
1090  SVal RVal;
1091  if (const Expr *E = dyn_cast<Expr>(S))
1092  RVal = state->getRawSVal(L.getValue(), E->getType());
1093  else
1094  RVal = state->getSVal(L->getRegion());
1095 
1096  const MemRegion *RegionRVal = RVal.getAsRegion();
1097  report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(L->getRegion()));
1098 
1099  if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) {
1100  report.markInteresting(RegionRVal);
1101  report.addVisitor(llvm::make_unique<TrackConstraintBRVisitor>(
1102  loc::MemRegionVal(RegionRVal), false));
1103  }
1104  }
1105 
1106  return true;
1107 }
1108 
1110  const ExplodedNode *N) {
1111  const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S);
1112  if (!ME)
1113  return nullptr;
1114  if (const Expr *Receiver = ME->getInstanceReceiver()) {
1116  SVal V = state->getSVal(Receiver, N->getLocationContext());
1117  if (state->isNull(V).isConstrainedTrue())
1118  return Receiver;
1119  }
1120  return nullptr;
1121 }
1122 
1124  const ExplodedNode *PrevN,
1125  BugReporterContext &BRC,
1126  BugReport &BR) {
1128  if (!P)
1129  return nullptr;
1130 
1131  const Stmt *S = P->getStmt();
1132  const Expr *Receiver = getNilReceiver(S, N);
1133  if (!Receiver)
1134  return nullptr;
1135 
1137  llvm::raw_svector_ostream OS(Buf);
1138 
1139  if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
1140  OS << "'";
1141  ME->getSelector().print(OS);
1142  OS << "' not called";
1143  }
1144  else {
1145  OS << "No method is called";
1146  }
1147  OS << " because the receiver is nil";
1148 
1149  // The receiver was nil, and hence the method was skipped.
1150  // Register a BugReporterVisitor to issue a message telling us how
1151  // the receiver was null.
1152  bugreporter::trackNullOrUndefValue(N, Receiver, BR, /*IsArg*/ false,
1153  /*EnableNullFPSuppression*/ false);
1154  // Issue a message saying that the method was skipped.
1155  PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
1156  N->getLocationContext());
1157  return new PathDiagnosticEventPiece(L, OS.str());
1158 }
1159 
1160 // Registers every VarDecl inside a Stmt with a last store visitor.
1162  const Stmt *S,
1163  bool EnableNullFPSuppression) {
1164  const ExplodedNode *N = BR.getErrorNode();
1165  std::deque<const Stmt *> WorkList;
1166  WorkList.push_back(S);
1167 
1168  while (!WorkList.empty()) {
1169  const Stmt *Head = WorkList.front();
1170  WorkList.pop_front();
1171 
1173  ProgramStateManager &StateMgr = state->getStateManager();
1174 
1175  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) {
1176  if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
1177  const VarRegion *R =
1178  StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
1179 
1180  // What did we load?
1181  SVal V = state->getSVal(S, N->getLocationContext());
1182 
1183  if (V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) {
1184  // Register a new visitor with the BugReport.
1185  BR.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1186  V.castAs<KnownSVal>(), R, EnableNullFPSuppression));
1187  }
1188  }
1189  }
1190 
1191  for (const Stmt *SubStmt : Head->children())
1192  WorkList.push_back(SubStmt);
1193  }
1194 }
1195 
1196 //===----------------------------------------------------------------------===//
1197 // Visitor that tries to report interesting diagnostics from conditions.
1198 //===----------------------------------------------------------------------===//
1199 
1200 /// Return the tag associated with this visitor. This tag will be used
1201 /// to make all PathDiagnosticPieces created by this visitor.
1203  return "ConditionBRVisitor";
1204 }
1205 
1207  const ExplodedNode *Prev,
1208  BugReporterContext &BRC,
1209  BugReport &BR) {
1210  PathDiagnosticPiece *piece = VisitNodeImpl(N, Prev, BRC, BR);
1211  if (piece) {
1212  piece->setTag(getTag());
1213  if (PathDiagnosticEventPiece *ev=dyn_cast<PathDiagnosticEventPiece>(piece))
1214  ev->setPrunable(true, /* override */ false);
1215  }
1216  return piece;
1217 }
1218 
1220  const ExplodedNode *Prev,
1221  BugReporterContext &BRC,
1222  BugReport &BR) {
1223 
1224  ProgramPoint progPoint = N->getLocation();
1225  ProgramStateRef CurrentState = N->getState();
1226  ProgramStateRef PrevState = Prev->getState();
1227 
1228  // Compare the GDMs of the state, because that is where constraints
1229  // are managed. Note that ensure that we only look at nodes that
1230  // were generated by the analyzer engine proper, not checkers.
1231  if (CurrentState->getGDM().getRoot() ==
1232  PrevState->getGDM().getRoot())
1233  return nullptr;
1234 
1235  // If an assumption was made on a branch, it should be caught
1236  // here by looking at the state transition.
1237  if (Optional<BlockEdge> BE = progPoint.getAs<BlockEdge>()) {
1238  const CFGBlock *srcBlk = BE->getSrc();
1239  if (const Stmt *term = srcBlk->getTerminator())
1240  return VisitTerminator(term, N, srcBlk, BE->getDst(), BR, BRC);
1241  return nullptr;
1242  }
1243 
1244  if (Optional<PostStmt> PS = progPoint.getAs<PostStmt>()) {
1245  // FIXME: Assuming that BugReporter is a GRBugReporter is a layering
1246  // violation.
1247  const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags =
1248  cast<GRBugReporter>(BRC.getBugReporter()).
1249  getEngine().geteagerlyAssumeBinOpBifurcationTags();
1250 
1251  const ProgramPointTag *tag = PS->getTag();
1252  if (tag == tags.first)
1253  return VisitTrueTest(cast<Expr>(PS->getStmt()), true,
1254  BRC, BR, N);
1255  if (tag == tags.second)
1256  return VisitTrueTest(cast<Expr>(PS->getStmt()), false,
1257  BRC, BR, N);
1258 
1259  return nullptr;
1260  }
1261 
1262  return nullptr;
1263 }
1264 
1267  const ExplodedNode *N,
1268  const CFGBlock *srcBlk,
1269  const CFGBlock *dstBlk,
1270  BugReport &R,
1271  BugReporterContext &BRC) {
1272  const Expr *Cond = nullptr;
1273 
1274  switch (Term->getStmtClass()) {
1275  default:
1276  return nullptr;
1277  case Stmt::IfStmtClass:
1278  Cond = cast<IfStmt>(Term)->getCond();
1279  break;
1280  case Stmt::ConditionalOperatorClass:
1281  Cond = cast<ConditionalOperator>(Term)->getCond();
1282  break;
1283  }
1284 
1285  assert(Cond);
1286  assert(srcBlk->succ_size() == 2);
1287  const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk;
1288  return VisitTrueTest(Cond, tookTrue, BRC, R, N);
1289 }
1290 
1293  bool tookTrue,
1294  BugReporterContext &BRC,
1295  BugReport &R,
1296  const ExplodedNode *N) {
1297 
1298  const Expr *Ex = Cond;
1299 
1300  while (true) {
1301  Ex = Ex->IgnoreParenCasts();
1302  switch (Ex->getStmtClass()) {
1303  default:
1304  return nullptr;
1305  case Stmt::BinaryOperatorClass:
1306  return VisitTrueTest(Cond, cast<BinaryOperator>(Ex), tookTrue, BRC,
1307  R, N);
1308  case Stmt::DeclRefExprClass:
1309  return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC,
1310  R, N);
1311  case Stmt::UnaryOperatorClass: {
1312  const UnaryOperator *UO = cast<UnaryOperator>(Ex);
1313  if (UO->getOpcode() == UO_LNot) {
1314  tookTrue = !tookTrue;
1315  Ex = UO->getSubExpr();
1316  continue;
1317  }
1318  return nullptr;
1319  }
1320  }
1321  }
1322 }
1323 
1324 bool ConditionBRVisitor::patternMatch(const Expr *Ex, raw_ostream &Out,
1325  BugReporterContext &BRC,
1326  BugReport &report,
1327  const ExplodedNode *N,
1328  Optional<bool> &prunable) {
1329  const Expr *OriginalExpr = Ex;
1330  Ex = Ex->IgnoreParenCasts();
1331 
1332  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
1333  const bool quotes = isa<VarDecl>(DR->getDecl());
1334  if (quotes) {
1335  Out << '\'';
1336  const LocationContext *LCtx = N->getLocationContext();
1337  const ProgramState *state = N->getState().get();
1338  if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()),
1339  LCtx).getAsRegion()) {
1340  if (report.isInteresting(R))
1341  prunable = false;
1342  else {
1343  const ProgramState *state = N->getState().get();
1344  SVal V = state->getSVal(R);
1345  if (report.isInteresting(V))
1346  prunable = false;
1347  }
1348  }
1349  }
1350  Out << DR->getDecl()->getDeclName().getAsString();
1351  if (quotes)
1352  Out << '\'';
1353  return quotes;
1354  }
1355 
1356  if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) {
1357  QualType OriginalTy = OriginalExpr->getType();
1358  if (OriginalTy->isPointerType()) {
1359  if (IL->getValue() == 0) {
1360  Out << "null";
1361  return false;
1362  }
1363  }
1364  else if (OriginalTy->isObjCObjectPointerType()) {
1365  if (IL->getValue() == 0) {
1366  Out << "nil";
1367  return false;
1368  }
1369  }
1370 
1371  Out << IL->getValue();
1372  return false;
1373  }
1374 
1375  return false;
1376 }
1377 
1380  const BinaryOperator *BExpr,
1381  const bool tookTrue,
1382  BugReporterContext &BRC,
1383  BugReport &R,
1384  const ExplodedNode *N) {
1385 
1386  bool shouldInvert = false;
1387  Optional<bool> shouldPrune;
1388 
1389  SmallString<128> LhsString, RhsString;
1390  {
1391  llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
1392  const bool isVarLHS = patternMatch(BExpr->getLHS(), OutLHS, BRC, R, N,
1393  shouldPrune);
1394  const bool isVarRHS = patternMatch(BExpr->getRHS(), OutRHS, BRC, R, N,
1395  shouldPrune);
1396 
1397  shouldInvert = !isVarLHS && isVarRHS;
1398  }
1399 
1400  BinaryOperator::Opcode Op = BExpr->getOpcode();
1401 
1403  // For assignment operators, all that we care about is that the LHS
1404  // evaluates to "true" or "false".
1405  return VisitConditionVariable(LhsString, BExpr->getLHS(), tookTrue,
1406  BRC, R, N);
1407  }
1408 
1409  // For non-assignment operations, we require that we can understand
1410  // both the LHS and RHS.
1411  if (LhsString.empty() || RhsString.empty() ||
1413  return nullptr;
1414 
1415  // Should we invert the strings if the LHS is not a variable name?
1416  SmallString<256> buf;
1417  llvm::raw_svector_ostream Out(buf);
1418  Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is ";
1419 
1420  // Do we need to invert the opcode?
1421  if (shouldInvert)
1422  switch (Op) {
1423  default: break;
1424  case BO_LT: Op = BO_GT; break;
1425  case BO_GT: Op = BO_LT; break;
1426  case BO_LE: Op = BO_GE; break;
1427  case BO_GE: Op = BO_LE; break;
1428  }
1429 
1430  if (!tookTrue)
1431  switch (Op) {
1432  case BO_EQ: Op = BO_NE; break;
1433  case BO_NE: Op = BO_EQ; break;
1434  case BO_LT: Op = BO_GE; break;
1435  case BO_GT: Op = BO_LE; break;
1436  case BO_LE: Op = BO_GT; break;
1437  case BO_GE: Op = BO_LT; break;
1438  default:
1439  return nullptr;
1440  }
1441 
1442  switch (Op) {
1443  case BO_EQ:
1444  Out << "equal to ";
1445  break;
1446  case BO_NE:
1447  Out << "not equal to ";
1448  break;
1449  default:
1450  Out << BinaryOperator::getOpcodeStr(Op) << ' ';
1451  break;
1452  }
1453 
1454  Out << (shouldInvert ? LhsString : RhsString);
1455  const LocationContext *LCtx = N->getLocationContext();
1456  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
1457  PathDiagnosticEventPiece *event =
1458  new PathDiagnosticEventPiece(Loc, Out.str());
1459  if (shouldPrune.hasValue())
1460  event->setPrunable(shouldPrune.getValue());
1461  return event;
1462 }
1463 
1466  const Expr *CondVarExpr,
1467  const bool tookTrue,
1468  BugReporterContext &BRC,
1469  BugReport &report,
1470  const ExplodedNode *N) {
1471  // FIXME: If there's already a constraint tracker for this variable,
1472  // we shouldn't emit anything here (c.f. the double note in
1473  // test/Analysis/inlining/path-notes.c)
1474  SmallString<256> buf;
1475  llvm::raw_svector_ostream Out(buf);
1476  Out << "Assuming " << LhsString << " is ";
1477 
1478  QualType Ty = CondVarExpr->getType();
1479 
1480  if (Ty->isPointerType())
1481  Out << (tookTrue ? "not null" : "null");
1482  else if (Ty->isObjCObjectPointerType())
1483  Out << (tookTrue ? "not nil" : "nil");
1484  else if (Ty->isBooleanType())
1485  Out << (tookTrue ? "true" : "false");
1486  else if (Ty->isIntegralOrEnumerationType())
1487  Out << (tookTrue ? "non-zero" : "zero");
1488  else
1489  return nullptr;
1490 
1491  const LocationContext *LCtx = N->getLocationContext();
1492  PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
1493  PathDiagnosticEventPiece *event =
1494  new PathDiagnosticEventPiece(Loc, Out.str());
1495 
1496  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) {
1497  if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
1498  const ProgramState *state = N->getState().get();
1499  if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
1500  if (report.isInteresting(R))
1501  event->setPrunable(false);
1502  }
1503  }
1504  }
1505 
1506  return event;
1507 }
1508 
1511  const DeclRefExpr *DR,
1512  const bool tookTrue,
1513  BugReporterContext &BRC,
1514  BugReport &report,
1515  const ExplodedNode *N) {
1516 
1517  const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
1518  if (!VD)
1519  return nullptr;
1520 
1521  SmallString<256> Buf;
1522  llvm::raw_svector_ostream Out(Buf);
1523 
1524  Out << "Assuming '" << VD->getDeclName() << "' is ";
1525 
1526  QualType VDTy = VD->getType();
1527 
1528  if (VDTy->isPointerType())
1529  Out << (tookTrue ? "non-null" : "null");
1530  else if (VDTy->isObjCObjectPointerType())
1531  Out << (tookTrue ? "non-nil" : "nil");
1532  else if (VDTy->isScalarType())
1533  Out << (tookTrue ? "not equal to 0" : "0");
1534  else
1535  return nullptr;
1536 
1537  const LocationContext *LCtx = N->getLocationContext();
1538  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
1539  PathDiagnosticEventPiece *event =
1540  new PathDiagnosticEventPiece(Loc, Out.str());
1541 
1542  const ProgramState *state = N->getState().get();
1543  if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
1544  if (report.isInteresting(R))
1545  event->setPrunable(false);
1546  else {
1547  SVal V = state->getSVal(R);
1548  if (report.isInteresting(V))
1549  event->setPrunable(false);
1550  }
1551  }
1552  return event;
1553 }
1554 
1555 std::unique_ptr<PathDiagnosticPiece>
1557  const ExplodedNode *N,
1558  BugReport &BR) {
1559  // Here we suppress false positives coming from system headers. This list is
1560  // based on known issues.
1561  ExprEngine &Eng = BRC.getBugReporter().getEngine();
1562  AnalyzerOptions &Options = Eng.getAnalysisManager().options;
1563  const Decl *D = N->getLocationContext()->getDecl();
1564 
1566  // Skip reports within the 'std' namespace. Although these can sometimes be
1567  // the user's fault, we currently don't report them very well, and
1568  // Note that this will not help for any other data structure libraries, like
1569  // TR1, Boost, or llvm/ADT.
1570  if (Options.shouldSuppressFromCXXStandardLibrary()) {
1571  BR.markInvalid(getTag(), nullptr);
1572  return nullptr;
1573 
1574  } else {
1575  // If the complete 'std' suppression is not enabled, suppress reports
1576  // from the 'std' namespace that are known to produce false positives.
1577 
1578  // The analyzer issues a false use-after-free when std::list::pop_front
1579  // or std::list::pop_back are called multiple times because we cannot
1580  // reason about the internal invariants of the datastructure.
1581  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
1582  const CXXRecordDecl *CD = MD->getParent();
1583  if (CD->getName() == "list") {
1584  BR.markInvalid(getTag(), nullptr);
1585  return nullptr;
1586  }
1587  }
1588 
1589  // The analyzer issues a false positive when the constructor of
1590  // std::__independent_bits_engine from algorithms is used.
1591  if (const CXXConstructorDecl *MD = dyn_cast<CXXConstructorDecl>(D)) {
1592  const CXXRecordDecl *CD = MD->getParent();
1593  if (CD->getName() == "__independent_bits_engine") {
1594  BR.markInvalid(getTag(), nullptr);
1595  return nullptr;
1596  }
1597  }
1598 
1599  for (const LocationContext *LCtx = N->getLocationContext(); LCtx;
1600  LCtx = LCtx->getParent()) {
1601  const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
1602  if (!MD)
1603  continue;
1604 
1605  const CXXRecordDecl *CD = MD->getParent();
1606  // The analyzer issues a false positive on
1607  // std::basic_string<uint8_t> v; v.push_back(1);
1608  // and
1609  // std::u16string s; s += u'a';
1610  // because we cannot reason about the internal invariants of the
1611  // datastructure.
1612  if (CD->getName() == "basic_string") {
1613  BR.markInvalid(getTag(), nullptr);
1614  return nullptr;
1615  }
1616 
1617  // The analyzer issues a false positive on
1618  // std::shared_ptr<int> p(new int(1)); p = nullptr;
1619  // because it does not reason properly about temporary destructors.
1620  if (CD->getName() == "shared_ptr") {
1621  BR.markInvalid(getTag(), nullptr);
1622  return nullptr;
1623  }
1624  }
1625  }
1626  }
1627 
1628  // Skip reports within the sys/queue.h macros as we do not have the ability to
1629  // reason about data structure shapes.
1632  while (Loc.isMacroID()) {
1633  Loc = Loc.getSpellingLoc();
1634  if (SM.getFilename(Loc).endswith("sys/queue.h")) {
1635  BR.markInvalid(getTag(), nullptr);
1636  return nullptr;
1637  }
1638  }
1639 
1640  return nullptr;
1641 }
1642 
1645  const ExplodedNode *PrevN,
1646  BugReporterContext &BRC,
1647  BugReport &BR) {
1648 
1649  ProgramStateRef State = N->getState();
1650  ProgramPoint ProgLoc = N->getLocation();
1651 
1652  // We are only interested in visiting CallEnter nodes.
1653  Optional<CallEnter> CEnter = ProgLoc.getAs<CallEnter>();
1654  if (!CEnter)
1655  return nullptr;
1656 
1657  // Check if one of the arguments is the region the visitor is tracking.
1659  CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State);
1660  unsigned Idx = 0;
1661  ArrayRef<ParmVarDecl*> parms = Call->parameters();
1662 
1663  for (ArrayRef<ParmVarDecl*>::iterator I = parms.begin(), E = parms.end();
1664  I != E; ++I, ++Idx) {
1665  const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion();
1666 
1667  // Are we tracking the argument or its subregion?
1668  if ( !ArgReg || (ArgReg != R && !R->isSubRegionOf(ArgReg->StripCasts())))
1669  continue;
1670 
1671  // Check the function parameter type.
1672  const ParmVarDecl *ParamDecl = *I;
1673  assert(ParamDecl && "Formal parameter has no decl?");
1674  QualType T = ParamDecl->getType();
1675 
1676  if (!(T->isAnyPointerType() || T->isReferenceType())) {
1677  // Function can only change the value passed in by address.
1678  continue;
1679  }
1680 
1681  // If it is a const pointer value, the function does not intend to
1682  // change the value.
1683  if (T->getPointeeType().isConstQualified())
1684  continue;
1685 
1686  // Mark the call site (LocationContext) as interesting if the value of the
1687  // argument is undefined or '0'/'NULL'.
1688  SVal BoundVal = State->getSVal(R);
1689  if (BoundVal.isUndef() || BoundVal.isZeroConstant()) {
1690  BR.markInteresting(CEnter->getCalleeContext());
1691  return nullptr;
1692  }
1693  }
1694  return nullptr;
1695 }
ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC property.
Definition: ExprObjC.h:539
TypedValueRegion - An abstract class representing regions having a typed value.
Definition: MemRegion.h:494
const Expr * getDerefExpr(const Stmt *S)
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:237
void setTag(const char *tag)
Tag this PathDiagnosticPiece with the given C-string.
This is a discriminated union of FileInfo and ExpansionInfo.
A (possibly-)qualified type.
Definition: Type.h:598
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:79
bool isMacroID() const
bool isInteresting(SymbolRef sym)
succ_iterator succ_begin()
Definition: CFG.h:541
virtual bool canPrintPretty() const
Returns true if this region can be printed in a user-friendly way.
Definition: MemRegion.cpp:568
const ExplodedNode * getErrorNode() const
Definition: BugReporter.h:180
virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const
Return the "definitive" location of the reported bug.
bool shouldSuppressNullReturnPaths()
Returns whether or not paths that go through null returns should be suppressed.
PathDiagnosticPiece * VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
unsigned getFunctionScopeIndex() const
Returns the index of this parameter in its prototype or method scope.
Definition: Decl.h:1430
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
Represents a point when we begin processing an inlined call.
Definition: ProgramPoint.h:584
virtual bool isBoundable() const
Definition: MemRegion.h:152
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const
Manages the lifetime of CallEvent objects.
Definition: CallEvent.h:993
StringRef P
PathDiagnosticPiece * VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
Each ExpansionInfo encodes the expansion location - where the token was ultimately expanded...
const ExpansionInfo & getExpansion() const
const Expr * getInit() const
Definition: Decl.h:1139
bool isBooleanType() const
Definition: Type.h:5743
MemSpaceRegion - A memory region that represents a "memory space"; for example, the set of global var...
Definition: MemRegion.h:179
void setPrunable(bool isPrunable, bool override=false)
Mark the diagnostic piece as being potentially prunable.
PathDiagnosticPiece * VisitNode(const ExplodedNode *N, const ExplodedNode *Prev, BugReporterContext &BRC, BugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
bool shouldAvoidSuppressingNullArgumentPaths()
Returns whether a bug report should not be suppressed if its path includes a call with a null argumen...
const Stmt * GetDenomExpr(const ExplodedNode *N)
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2187
Value representing integer constant.
Definition: SVals.h:341
VarDecl - An instance of this class is created to represent a variable declaration or definition...
Definition: Decl.h:768
unsigned succ_size() const
Definition: CFG.h:551
static const Expr * peelOffOuterExpr(const Expr *Ex, const ExplodedNode *N)
Represents an expression – generally a full-expression – that introduces cleanups to be run at the en...
Definition: ExprCXX.h:2936
ParmVarDecl - Represents a parameter to a function.
Definition: Decl.h:1377
bool isZeroConstant() const
Definition: SVals.cpp:186
FullSourceLoc asLocation() const
bool isComparisonOp() const
Definition: Expr.h:2990
const MemSpaceRegion * getMemorySpace() const
Definition: MemRegion.cpp:1097
void Profile(llvm::FoldingSetNodeID &ID) const override
bool isScalarType() const
Definition: Type.h:5715
LineState State
bool isReferenceType() const
Definition: Type.h:5491
bool isAnyPointerType() const
Definition: Type.h:5485
Represents a program point after a store evaluation.
Definition: ProgramPoint.h:399
This class provides a convenience implementation for clone() using the Curiously-Recurring Template P...
MemRegionManager & getRegionManager()
Definition: ProgramState.h:508
SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const
If this SVal is a location and wraps a symbol, return that SymbolRef.
Definition: SVals.cpp:69
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
Optional< T > getLocationAs() const LLVM_LVALUE_FUNCTION
bool patternMatch(const Expr *Ex, raw_ostream &Out, BugReporterContext &BRC, BugReport &R, const ExplodedNode *N, Optional< bool > &prunable)
Expr * getLHS() const
Definition: Expr.h:2943
const VarDecl * getDecl() const
Definition: MemRegion.h:873
virtual llvm::iterator_range< ranges_iterator > getRanges()
Get the SourceRanges associated with the report.
std::unique_ptr< PathDiagnosticPiece > getEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR) override
Provide custom definition for the final diagnostic piece on the path - the piece, which is displayed ...
virtual std::unique_ptr< PathDiagnosticPiece > getEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR)
Provide custom definition for the final diagnostic piece on the path - the piece, which is displayed ...
BinaryOperatorKind
BlockDataRegion - A region that represents a block instance.
Definition: MemRegion.h:627
static bool isInStdNamespace(const Decl *D)
Returns true if the root namespace of the given declaration is the 'std' C++ namespace.
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
Definition: DeclCXX.h:1838
bool isUnknownOrUndef() const
Definition: SVals.h:125
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:2897
const Stmt * getCallSite() const
bool isParentOf(const LocationContext *LC) const
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
Definition: Expr.cpp:2326
static void registerStatementVarDecls(BugReport &BR, const Stmt *S, bool EnableNullFPSuppression)
Creates a visitor for every VarDecl inside a Stmt and registers it with the BugReport.
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
static const MemRegion * getLocationRegionIfReference(const Expr *E, const ExplodedNode *N)
StringRef getDescription() const
Definition: BugReporter.h:182
ExplodedNode * getFirstPred()
bool isStaticLocal() const
isStaticLocal - Returns true if a variable with function scope is a static local variable.
Definition: Decl.h:980
detail::InMemoryDirectory::const_iterator I
void addVisitor(std::unique_ptr< BugReporterVisitor > visitor)
Add custom or predefined bug report visitors to this report.
QualType getType() const
Definition: Decl.h:599
const LocationContext * getLocationContext() const
const StackFrameContext * getStackFrame() const
Definition: MemRegion.h:368
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:3170
bool isAssignmentOp() const
Definition: Expr.h:3025
bool shouldSuppressInlinedDefensiveChecks()
Returns whether or not diagnostics containing inlined defensive NULL checks should be suppressed...
Represents a ValueDecl that came out of a declarator.
Definition: Decl.h:646
StringRef getFilename(SourceLocation SpellingLoc) const
Return the filename of the file containing a SourceLocation.
CFGBlock - Represents a single basic block in a source-level CFG.
Definition: CFG.h:353
const MemRegion * StripCasts(bool StripBaseCasts=true) const
Definition: MemRegion.cpp:1155
static const char * getTag()
Return the tag associated with this visitor.
Represents a point when we finish the call exit sequence (for inlined call).
Definition: ProgramPoint.h:638
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
Definition: Type.cpp:415
ProgramState - This class encapsulates:
Definition: ProgramState.h:74
Expr - This represents one expression.
Definition: Expr.h:105
const ProgramStateRef & getState() const
CFGBlock * getBlock(Stmt *S)
Returns the CFGBlock the specified Stmt* appears in.
Definition: CFGStmtMap.cpp:27
CallEventRef getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State)
Definition: CallEvent.cpp:1058
SVal getSVal(const Stmt *S, const LocationContext *LCtx) const
Returns the SVal bound to the statement 'S' in the state's environment.
Definition: ProgramState.h:728
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:86
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...
void Profile(llvm::FoldingSetNodeID &ID) const override
SuppressInlineDefensiveChecksVisitor(DefinedSVal Val, const ExplodedNode *N)
Expr * getSubExpr() const
Definition: Expr.h:1695
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:1214
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
Definition: Stmt.h:1366
An expression that sends a message to the given Objective-C object or class.
Definition: ExprObjC.h:860
UnaryOperator - This represents the unary-expression's (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
Definition: Expr.h:1668
DeclarationName getDeclName() const
getDeclName - Get the actual, stored name of the declaration, which may be a special name...
Definition: Decl.h:258
void markInteresting(SymbolRef sym)
ValueDecl * getDecl()
Definition: Expr.h:1017
bool isGLValue() const
Definition: Expr.h:250
const SourceManager & SM
Definition: Format.cpp:1184
PathDiagnosticPiece * VisitTerminator(const Stmt *Term, const ExplodedNode *N, const CFGBlock *srcBlk, const CFGBlock *dstBlk, BugReport &R, BugReporterContext &BRC)
const MatchFinder::MatchFinderOptions & Options
CFGTerminator getTerminator()
Definition: CFG.h:622
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class...
Definition: Expr.h:848
static std::unique_ptr< PathDiagnosticPiece > getDefaultEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR)
Generates the default final diagnostic piece.
#define false
Definition: stdbool.h:33
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:5730
Encodes a location in the source.
const StackFrameContext * getCurrentStackFrame() const
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:265
ProgramPoints can be "tagged" as representing points specific to a given analysis entity...
Definition: ProgramPoint.h:40
AnalysisManager & getAnalysisManager() override
Definition: ExprEngine.h:125
void Profile(llvm::FoldingSetNodeID &ID) const override
bool isValid() const
Return true if this is a valid SourceLocation object.
const std::string ID
CallEventManager & getCallEventManager()
Definition: ProgramState.h:515
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Definition: Stmt.h:443
PathDiagnosticPiece * VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:1736
PathDiagnosticPiece * VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:46
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx)
Definition: Type.h:4262
PathDiagnosticPiece * VisitTrueTest(const Expr *Cond, bool tookTrue, BugReporterContext &BRC, BugReport &R, const ExplodedNode *N)
const Decl * getDecl() const
virtual void printPretty(raw_ostream &os) const
Print the region for use in diagnostics.
Definition: MemRegion.cpp:576
bool isUndef() const
Definition: SVals.h:121
PathDiagnosticPiece * VisitConditionVariable(StringRef LhsString, const Expr *CondVarExpr, const bool tookTrue, BugReporterContext &BRC, BugReport &R, const ExplodedNode *N)
Opcode getOpcode() const
Definition: Expr.h:1692
const Decl * getSingleDecl() const
Definition: Stmt.h:461
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
Definition: ExprObjC.h:1155
ast_type_traits::DynTypedNode Node
QualType getType() const
Definition: Expr.h:126
bool isDeclRefExprToReference(const Expr *E)
const LocationContext * getParent() const
StringRef getOpcodeStr() const
Definition: Expr.h:2959
const LocationContext * getLocationContext() const
Definition: ProgramPoint.h:178
const VarRegion * getVarRegion(const VarDecl *D, const LocationContext *LC)
getVarRegion - Retrieve or create the memory region associated with a specified VarDecl and LocationC...
Definition: MemRegion.cpp:821
static const char * getTag()
Return the tag associated with this visitor.
GRBugReporter & getBugReporter()
Definition: BugReporter.h:534
const Stmt * GetRetValExpr(const ExplodedNode *N)
detail::InMemoryDirectory::const_iterator E
const MemRegion * getAsRegion() const
Definition: SVals.cpp:135
const Expr * getRetValue() const
Definition: Stmt.cpp:899
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
Definition: ProgramPoint.h:150
unsigned Map[Count]
The type of a lookup table which maps from language-specific address spaces to target-specific ones...
Definition: AddressSpaces.h:45
Represents an SVal that is guaranteed to not be UnknownVal.
Definition: SVals.h:255
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2063
ProgramStateManager & getStateManager()
Definition: BugReporter.h:538
bool shouldSuppressFromCXXStandardLibrary()
Returns whether or not diagnostics reported within the C++ standard library should be suppressed...
ObjCIvarRefExpr - A reference to an ObjC instance variable.
Definition: ExprObjC.h:479
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
Definition: SemaDecl.cpp:12171
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:2315
Represents a C++ struct/union/class.
Definition: DeclCXX.h:263
bool isObjCObjectPointerType() const
Definition: Type.h:5554
Opcode getOpcode() const
Definition: Expr.h:2940
PathDiagnosticPiece * VisitNode(const ExplodedNode *Succ, const ExplodedNode *Pred, BugReporterContext &BRC, BugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
bool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R, bool IsArg=false, bool EnableNullFPSuppression=true)
Attempts to add visitors to trace a null or undefined value back to its point of origin, whether it is a symbol constrained to null or an explicit assignment.
PathDiagnosticPiece * VisitNodeImpl(const ExplodedNode *N, const ExplodedNode *Prev, BugReporterContext &BRC, BugReport &BR)
static PathDiagnosticLocation createEndOfPath(const ExplodedNode *N, const SourceManager &SM)
Create a location corresponding to the next valid ExplodedNode as end of path location.
void removeInvalidation(const void *Tag, const void *Data)
Reverses the effects of a previous invalidation.
Definition: BugReporter.h:235
bool isFunctionMacroExpansion() const
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:228
static bool isInitializationOfVar(const ExplodedNode *N, const VarRegion *VR)
Returns true if N represents the DeclStmt declaring and initializing VR.
Loc getLValue(const VarDecl *D, const LocationContext *LC) const
Get the lvalue for a variable reference.
Definition: ProgramState.h:694
Expr * getRHS() const
Definition: Expr.h:2945
A SourceLocation and its associated SourceManager.
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:932
virtual bool isSubRegionOf(const MemRegion *R) const
Check if the region is a subregion of the given region.
Definition: MemRegion.cpp:1147
A trivial tuple used to represent a source range.
This class provides an interface through which checkers can create individual bug reports...
Definition: BugReporter.h:55
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition: Type.h:5318
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Definition: SVals.h:75
static bool isInterestingLValueExpr(const Expr *Ex)
Returns true if nodes for the given expression kind are always kept around.
This class handles loading and caching of source files into memory.
SourceManager & getSourceManager()
Definition: BugReporter.h:550
bool hasLocalStorage() const
hasLocalStorage - Returns true if a variable with function scope is a non-static local variable...
Definition: Decl.h:963
FullSourceLoc getSpellingLoc() const
virtual AnalysisManager & getAnalysisManager()=0
ExprEngine & getEngine()
getEngine - Return the analysis engine used to analyze a given function or method.
Definition: BugReporter.h:499
static const char * getTag()
Return the tag associated with this visitor.
bool isPointerType() const
Definition: Type.h:5482