clang  5.0.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"
18 #include "clang/Lex/Lexer.h"
25 #include "llvm/ADT/SmallString.h"
26 #include "llvm/ADT/StringExtras.h"
27 #include "llvm/Support/raw_ostream.h"
28 
29 using namespace clang;
30 using namespace ento;
31 
32 using llvm::FoldingSetNodeID;
33 
34 //===----------------------------------------------------------------------===//
35 // Utility functions.
36 //===----------------------------------------------------------------------===//
37 
39  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
40  return DRE->getDecl()->getType()->isReferenceType();
41  }
42  return false;
43 }
44 
46  // Pattern match for a few useful cases:
47  // a[0], p->f, *p
48  const Expr *E = dyn_cast<Expr>(S);
49  if (!E)
50  return nullptr;
51  E = E->IgnoreParenCasts();
52 
53  while (true) {
54  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) {
55  assert(B->isAssignmentOp());
56  E = B->getLHS()->IgnoreParenCasts();
57  continue;
58  }
59  else if (const UnaryOperator *U = dyn_cast<UnaryOperator>(E)) {
60  if (U->getOpcode() == UO_Deref)
61  return U->getSubExpr()->IgnoreParenCasts();
62  }
63  else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
64  if (ME->isImplicitAccess()) {
65  return ME;
66  } else if (ME->isArrow() || isDeclRefExprToReference(ME->getBase())) {
67  return ME->getBase()->IgnoreParenCasts();
68  } else {
69  // If we have a member expr with a dot, the base must have been
70  // dereferenced.
71  return getDerefExpr(ME->getBase());
72  }
73  }
74  else if (const ObjCIvarRefExpr *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) {
75  return IvarRef->getBase()->IgnoreParenCasts();
76  }
77  else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(E)) {
78  return getDerefExpr(AE->getBase());
79  }
80  else if (isa<DeclRefExpr>(E)) {
81  return E;
82  }
83  break;
84  }
85 
86  return nullptr;
87 }
88 
90  const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
91  if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S))
92  return BE->getRHS();
93  return nullptr;
94 }
95 
97  const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
98  if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S))
99  return RS->getRetValue();
100  return nullptr;
101 }
102 
103 //===----------------------------------------------------------------------===//
104 // Definitions for bug reporter visitors.
105 //===----------------------------------------------------------------------===//
106 
107 std::unique_ptr<PathDiagnosticPiece>
109  const ExplodedNode *EndPathNode, BugReport &BR) {
110  return nullptr;
111 }
112 
113 std::unique_ptr<PathDiagnosticPiece> BugReporterVisitor::getDefaultEndPath(
114  BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) {
117 
118  const auto &Ranges = BR.getRanges();
119 
120  // Only add the statement itself as a range if we didn't specify any
121  // special ranges for this report.
122  auto P = llvm::make_unique<PathDiagnosticEventPiece>(
123  L, BR.getDescription(), Ranges.begin() == Ranges.end());
124  for (SourceRange Range : Ranges)
125  P->addRange(Range);
126 
127  return std::move(P);
128 }
129 
130 
131 namespace {
132 /// Emits an extra note at the return statement of an interesting stack frame.
133 ///
134 /// The returned value is marked as an interesting value, and if it's null,
135 /// adds a visitor to track where it became null.
136 ///
137 /// This visitor is intended to be used when another visitor discovers that an
138 /// interesting value comes from an inlined function call.
139 class ReturnVisitor : public BugReporterVisitorImpl<ReturnVisitor> {
140  const StackFrameContext *StackFrame;
141  enum {
142  Initial,
143  MaybeUnsuppress,
144  Satisfied
145  } Mode;
146 
147  bool EnableNullFPSuppression;
148 
149 public:
150  ReturnVisitor(const StackFrameContext *Frame, bool Suppressed)
151  : StackFrame(Frame), Mode(Initial), EnableNullFPSuppression(Suppressed) {}
152 
153  static void *getTag() {
154  static int Tag = 0;
155  return static_cast<void *>(&Tag);
156  }
157 
158  void Profile(llvm::FoldingSetNodeID &ID) const override {
159  ID.AddPointer(ReturnVisitor::getTag());
160  ID.AddPointer(StackFrame);
161  ID.AddBoolean(EnableNullFPSuppression);
162  }
163 
164  /// Adds a ReturnVisitor if the given statement represents a call that was
165  /// inlined.
166  ///
167  /// This will search back through the ExplodedGraph, starting from the given
168  /// node, looking for when the given statement was processed. If it turns out
169  /// the statement is a call that was inlined, we add the visitor to the
170  /// bug report, so it can print a note later.
171  static void addVisitorIfNecessary(const ExplodedNode *Node, const Stmt *S,
172  BugReport &BR,
173  bool InEnableNullFPSuppression) {
174  if (!CallEvent::isCallStmt(S))
175  return;
176 
177  // First, find when we processed the statement.
178  do {
180  if (CEE->getCalleeContext()->getCallSite() == S)
181  break;
182  if (Optional<StmtPoint> SP = Node->getLocationAs<StmtPoint>())
183  if (SP->getStmt() == S)
184  break;
185 
186  Node = Node->getFirstPred();
187  } while (Node);
188 
189  // Next, step over any post-statement checks.
190  while (Node && Node->getLocation().getAs<PostStmt>())
191  Node = Node->getFirstPred();
192  if (!Node)
193  return;
194 
195  // Finally, see if we inlined the call.
197  if (!CEE)
198  return;
199 
200  const StackFrameContext *CalleeContext = CEE->getCalleeContext();
201  if (CalleeContext->getCallSite() != S)
202  return;
203 
204  // Check the return value.
205  ProgramStateRef State = Node->getState();
206  SVal RetVal = State->getSVal(S, Node->getLocationContext());
207 
208  // Handle cases where a reference is returned and then immediately used.
209  if (cast<Expr>(S)->isGLValue())
210  if (Optional<Loc> LValue = RetVal.getAs<Loc>())
211  RetVal = State->getSVal(*LValue);
212 
213  // See if the return value is NULL. If so, suppress the report.
214  SubEngine *Eng = State->getStateManager().getOwningEngine();
215  assert(Eng && "Cannot file a bug report without an owning engine");
217 
218  bool EnableNullFPSuppression = false;
219  if (InEnableNullFPSuppression && Options.shouldSuppressNullReturnPaths())
220  if (Optional<Loc> RetLoc = RetVal.getAs<Loc>())
221  EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
222 
223  BR.markInteresting(CalleeContext);
224  BR.addVisitor(llvm::make_unique<ReturnVisitor>(CalleeContext,
225  EnableNullFPSuppression));
226  }
227 
228  /// Returns true if any counter-suppression heuristics are enabled for
229  /// ReturnVisitor.
230  static bool hasCounterSuppression(AnalyzerOptions &Options) {
232  }
233 
234  std::shared_ptr<PathDiagnosticPiece>
235  visitNodeInitial(const ExplodedNode *N, const ExplodedNode *PrevN,
236  BugReporterContext &BRC, BugReport &BR) {
237  // Only print a message at the interesting return statement.
238  if (N->getLocationContext() != StackFrame)
239  return nullptr;
240 
242  if (!SP)
243  return nullptr;
244 
245  const ReturnStmt *Ret = dyn_cast<ReturnStmt>(SP->getStmt());
246  if (!Ret)
247  return nullptr;
248 
249  // Okay, we're at the right return statement, but do we have the return
250  // value available?
251  ProgramStateRef State = N->getState();
252  SVal V = State->getSVal(Ret, StackFrame);
253  if (V.isUnknownOrUndef())
254  return nullptr;
255 
256  // Don't print any more notes after this one.
257  Mode = Satisfied;
258 
259  const Expr *RetE = Ret->getRetValue();
260  assert(RetE && "Tracking a return value for a void function");
261 
262  // Handle cases where a reference is returned and then immediately used.
263  Optional<Loc> LValue;
264  if (RetE->isGLValue()) {
265  if ((LValue = V.getAs<Loc>())) {
266  SVal RValue = State->getRawSVal(*LValue, RetE->getType());
267  if (RValue.getAs<DefinedSVal>())
268  V = RValue;
269  }
270  }
271 
272  // Ignore aggregate rvalues.
273  if (V.getAs<nonloc::LazyCompoundVal>() ||
275  return nullptr;
276 
277  RetE = RetE->IgnoreParenCasts();
278 
279  // If we can't prove the return value is 0, just mark it interesting, and
280  // make sure to track it into any further inner functions.
281  if (!State->isNull(V).isConstrainedTrue()) {
282  BR.markInteresting(V);
283  ReturnVisitor::addVisitorIfNecessary(N, RetE, BR,
284  EnableNullFPSuppression);
285  return nullptr;
286  }
287 
288  // If we're returning 0, we should track where that 0 came from.
289  bugreporter::trackNullOrUndefValue(N, RetE, BR, /*IsArg*/ false,
290  EnableNullFPSuppression);
291 
292  // Build an appropriate message based on the return value.
293  SmallString<64> Msg;
294  llvm::raw_svector_ostream Out(Msg);
295 
296  if (V.getAs<Loc>()) {
297  // If we have counter-suppression enabled, make sure we keep visiting
298  // future nodes. We want to emit a path note as well, in case
299  // the report is resurrected as valid later on.
300  ExprEngine &Eng = BRC.getBugReporter().getEngine();
301  AnalyzerOptions &Options = Eng.getAnalysisManager().options;
302  if (EnableNullFPSuppression && hasCounterSuppression(Options))
303  Mode = MaybeUnsuppress;
304 
305  if (RetE->getType()->isObjCObjectPointerType())
306  Out << "Returning nil";
307  else
308  Out << "Returning null pointer";
309  } else {
310  Out << "Returning zero";
311  }
312 
313  if (LValue) {
314  if (const MemRegion *MR = LValue->getAsRegion()) {
315  if (MR->canPrintPretty()) {
316  Out << " (reference to ";
317  MR->printPretty(Out);
318  Out << ")";
319  }
320  }
321  } else {
322  // FIXME: We should have a more generalized location printing mechanism.
323  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(RetE))
324  if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(DR->getDecl()))
325  Out << " (loaded from '" << *DD << "')";
326  }
327 
328  PathDiagnosticLocation L(Ret, BRC.getSourceManager(), StackFrame);
329  if (!L.isValid() || !L.asLocation().isValid())
330  return nullptr;
331 
332  return std::make_shared<PathDiagnosticEventPiece>(L, Out.str());
333  }
334 
335  std::shared_ptr<PathDiagnosticPiece>
336  visitNodeMaybeUnsuppress(const ExplodedNode *N, const ExplodedNode *PrevN,
337  BugReporterContext &BRC, BugReport &BR) {
338 #ifndef NDEBUG
339  ExprEngine &Eng = BRC.getBugReporter().getEngine();
340  AnalyzerOptions &Options = Eng.getAnalysisManager().options;
341  assert(hasCounterSuppression(Options));
342 #endif
343 
344  // Are we at the entry node for this call?
346  if (!CE)
347  return nullptr;
348 
349  if (CE->getCalleeContext() != StackFrame)
350  return nullptr;
351 
352  Mode = Satisfied;
353 
354  // Don't automatically suppress a report if one of the arguments is
355  // known to be a null pointer. Instead, start tracking /that/ null
356  // value back to its origin.
357  ProgramStateManager &StateMgr = BRC.getStateManager();
358  CallEventManager &CallMgr = StateMgr.getCallEventManager();
359 
360  ProgramStateRef State = N->getState();
361  CallEventRef<> Call = CallMgr.getCaller(StackFrame, State);
362  for (unsigned I = 0, E = Call->getNumArgs(); I != E; ++I) {
363  Optional<Loc> ArgV = Call->getArgSVal(I).getAs<Loc>();
364  if (!ArgV)
365  continue;
366 
367  const Expr *ArgE = Call->getArgExpr(I);
368  if (!ArgE)
369  continue;
370 
371  // Is it possible for this argument to be non-null?
372  if (!State->isNull(*ArgV).isConstrainedTrue())
373  continue;
374 
375  if (bugreporter::trackNullOrUndefValue(N, ArgE, BR, /*IsArg=*/true,
376  EnableNullFPSuppression))
377  BR.removeInvalidation(ReturnVisitor::getTag(), StackFrame);
378 
379  // If we /can't/ track the null pointer, we should err on the side of
380  // false negatives, and continue towards marking this report invalid.
381  // (We will still look at the other arguments, though.)
382  }
383 
384  return nullptr;
385  }
386 
387  std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
388  const ExplodedNode *PrevN,
389  BugReporterContext &BRC,
390  BugReport &BR) override {
391  switch (Mode) {
392  case Initial:
393  return visitNodeInitial(N, PrevN, BRC, BR);
394  case MaybeUnsuppress:
395  return visitNodeMaybeUnsuppress(N, PrevN, BRC, BR);
396  case Satisfied:
397  return nullptr;
398  }
399 
400  llvm_unreachable("Invalid visit mode!");
401  }
402 
403  std::unique_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
404  const ExplodedNode *N,
405  BugReport &BR) override {
406  if (EnableNullFPSuppression)
407  BR.markInvalid(ReturnVisitor::getTag(), StackFrame);
408  return nullptr;
409  }
410 };
411 } // end anonymous namespace
412 
413 
414 void FindLastStoreBRVisitor ::Profile(llvm::FoldingSetNodeID &ID) const {
415  static int tag = 0;
416  ID.AddPointer(&tag);
417  ID.AddPointer(R);
418  ID.Add(V);
419  ID.AddBoolean(EnableNullFPSuppression);
420 }
421 
422 /// Returns true if \p N represents the DeclStmt declaring and initializing
423 /// \p VR.
424 static bool isInitializationOfVar(const ExplodedNode *N, const VarRegion *VR) {
426  if (!P)
427  return false;
428 
429  const DeclStmt *DS = P->getStmtAs<DeclStmt>();
430  if (!DS)
431  return false;
432 
433  if (DS->getSingleDecl() != VR->getDecl())
434  return false;
435 
436  const MemSpaceRegion *VarSpace = VR->getMemorySpace();
437  const StackSpaceRegion *FrameSpace = dyn_cast<StackSpaceRegion>(VarSpace);
438  if (!FrameSpace) {
439  // If we ever directly evaluate global DeclStmts, this assertion will be
440  // invalid, but this still seems preferable to silently accepting an
441  // initialization that may be for a path-sensitive variable.
442  assert(VR->getDecl()->isStaticLocal() && "non-static stackless VarRegion");
443  return true;
444  }
445 
446  assert(VR->getDecl()->hasLocalStorage());
447  const LocationContext *LCtx = N->getLocationContext();
448  return FrameSpace->getStackFrame() == LCtx->getCurrentStackFrame();
449 }
450 
451 std::shared_ptr<PathDiagnosticPiece>
453  const ExplodedNode *Pred,
454  BugReporterContext &BRC, BugReport &BR) {
455 
456  if (Satisfied)
457  return nullptr;
458 
459  const ExplodedNode *StoreSite = nullptr;
460  const Expr *InitE = nullptr;
461  bool IsParam = false;
462 
463  // First see if we reached the declaration of the region.
464  if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
465  if (isInitializationOfVar(Pred, VR)) {
466  StoreSite = Pred;
467  InitE = VR->getDecl()->getInit();
468  }
469  }
470 
471  // If this is a post initializer expression, initializing the region, we
472  // should track the initializer expression.
474  const MemRegion *FieldReg = (const MemRegion *)PIP->getLocationValue();
475  if (FieldReg && FieldReg == R) {
476  StoreSite = Pred;
477  InitE = PIP->getInitializer()->getInit();
478  }
479  }
480 
481  // Otherwise, see if this is the store site:
482  // (1) Succ has this binding and Pred does not, i.e. this is
483  // where the binding first occurred.
484  // (2) Succ has this binding and is a PostStore node for this region, i.e.
485  // the same binding was re-assigned here.
486  if (!StoreSite) {
487  if (Succ->getState()->getSVal(R) != V)
488  return nullptr;
489 
490  if (Pred->getState()->getSVal(R) == V) {
492  if (!PS || PS->getLocationValue() != R)
493  return nullptr;
494  }
495 
496  StoreSite = Succ;
497 
498  // If this is an assignment expression, we can track the value
499  // being assigned.
501  if (const BinaryOperator *BO = P->getStmtAs<BinaryOperator>())
502  if (BO->isAssignmentOp())
503  InitE = BO->getRHS();
504 
505  // If this is a call entry, the variable should be a parameter.
506  // FIXME: Handle CXXThisRegion as well. (This is not a priority because
507  // 'this' should never be NULL, but this visitor isn't just for NULL and
508  // UndefinedVal.)
509  if (Optional<CallEnter> CE = Succ->getLocationAs<CallEnter>()) {
510  if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
511  const ParmVarDecl *Param = cast<ParmVarDecl>(VR->getDecl());
512 
513  ProgramStateManager &StateMgr = BRC.getStateManager();
514  CallEventManager &CallMgr = StateMgr.getCallEventManager();
515 
516  CallEventRef<> Call = CallMgr.getCaller(CE->getCalleeContext(),
517  Succ->getState());
518  InitE = Call->getArgExpr(Param->getFunctionScopeIndex());
519  IsParam = true;
520  }
521  }
522 
523  // If this is a CXXTempObjectRegion, the Expr responsible for its creation
524  // is wrapped inside of it.
525  if (const CXXTempObjectRegion *TmpR = dyn_cast<CXXTempObjectRegion>(R))
526  InitE = TmpR->getExpr();
527  }
528 
529  if (!StoreSite)
530  return nullptr;
531  Satisfied = true;
532 
533  // If we have an expression that provided the value, try to track where it
534  // came from.
535  if (InitE) {
536  if (V.isUndef() ||
538  if (!IsParam)
539  InitE = InitE->IgnoreParenCasts();
540  bugreporter::trackNullOrUndefValue(StoreSite, InitE, BR, IsParam,
541  EnableNullFPSuppression);
542  } else {
543  ReturnVisitor::addVisitorIfNecessary(StoreSite, InitE->IgnoreParenCasts(),
544  BR, EnableNullFPSuppression);
545  }
546  }
547 
548  // Okay, we've found the binding. Emit an appropriate message.
549  SmallString<256> sbuf;
550  llvm::raw_svector_ostream os(sbuf);
551 
552  if (Optional<PostStmt> PS = StoreSite->getLocationAs<PostStmt>()) {
553  const Stmt *S = PS->getStmt();
554  const char *action = nullptr;
555  const DeclStmt *DS = dyn_cast<DeclStmt>(S);
556  const VarRegion *VR = dyn_cast<VarRegion>(R);
557 
558  if (DS) {
559  action = R->canPrintPretty() ? "initialized to " :
560  "Initializing to ";
561  } else if (isa<BlockExpr>(S)) {
562  action = R->canPrintPretty() ? "captured by block as " :
563  "Captured by block as ";
564  if (VR) {
565  // See if we can get the BlockVarRegion.
566  ProgramStateRef State = StoreSite->getState();
567  SVal V = State->getSVal(S, PS->getLocationContext());
568  if (const BlockDataRegion *BDR =
569  dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
570  if (const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) {
571  if (Optional<KnownSVal> KV =
572  State->getSVal(OriginalR).getAs<KnownSVal>())
573  BR.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
574  *KV, OriginalR, EnableNullFPSuppression));
575  }
576  }
577  }
578  }
579 
580  if (action) {
581  if (R->canPrintPretty()) {
582  R->printPretty(os);
583  os << " ";
584  }
585 
586  if (V.getAs<loc::ConcreteInt>()) {
587  bool b = false;
588  if (R->isBoundable()) {
589  if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
590  if (TR->getValueType()->isObjCObjectPointerType()) {
591  os << action << "nil";
592  b = true;
593  }
594  }
595  }
596 
597  if (!b)
598  os << action << "a null pointer value";
599  } else if (Optional<nonloc::ConcreteInt> CVal =
600  V.getAs<nonloc::ConcreteInt>()) {
601  os << action << CVal->getValue();
602  }
603  else if (DS) {
604  if (V.isUndef()) {
605  if (isa<VarRegion>(R)) {
606  const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
607  if (VD->getInit()) {
608  os << (R->canPrintPretty() ? "initialized" : "Initializing")
609  << " to a garbage value";
610  } else {
611  os << (R->canPrintPretty() ? "declared" : "Declaring")
612  << " without an initial value";
613  }
614  }
615  }
616  else {
617  os << (R->canPrintPretty() ? "initialized" : "Initialized")
618  << " here";
619  }
620  }
621  }
622  } else if (StoreSite->getLocation().getAs<CallEnter>()) {
623  if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
624  const ParmVarDecl *Param = cast<ParmVarDecl>(VR->getDecl());
625 
626  os << "Passing ";
627 
628  if (V.getAs<loc::ConcreteInt>()) {
629  if (Param->getType()->isObjCObjectPointerType())
630  os << "nil object reference";
631  else
632  os << "null pointer value";
633  } else if (V.isUndef()) {
634  os << "uninitialized value";
635  } else if (Optional<nonloc::ConcreteInt> CI =
636  V.getAs<nonloc::ConcreteInt>()) {
637  os << "the value " << CI->getValue();
638  } else {
639  os << "value";
640  }
641 
642  // Printed parameter indexes are 1-based, not 0-based.
643  unsigned Idx = Param->getFunctionScopeIndex() + 1;
644  os << " via " << Idx << llvm::getOrdinalSuffix(Idx) << " parameter";
645  if (R->canPrintPretty()) {
646  os << " ";
647  R->printPretty(os);
648  }
649  }
650  }
651 
652  if (os.str().empty()) {
653  if (V.getAs<loc::ConcreteInt>()) {
654  bool b = false;
655  if (R->isBoundable()) {
656  if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
657  if (TR->getValueType()->isObjCObjectPointerType()) {
658  os << "nil object reference stored";
659  b = true;
660  }
661  }
662  }
663  if (!b) {
664  if (R->canPrintPretty())
665  os << "Null pointer value stored";
666  else
667  os << "Storing null pointer value";
668  }
669 
670  } else if (V.isUndef()) {
671  if (R->canPrintPretty())
672  os << "Uninitialized value stored";
673  else
674  os << "Storing uninitialized value";
675 
676  } else if (Optional<nonloc::ConcreteInt> CV =
677  V.getAs<nonloc::ConcreteInt>()) {
678  if (R->canPrintPretty())
679  os << "The value " << CV->getValue() << " is assigned";
680  else
681  os << "Assigning " << CV->getValue();
682 
683  } else {
684  if (R->canPrintPretty())
685  os << "Value assigned";
686  else
687  os << "Assigning value";
688  }
689 
690  if (R->canPrintPretty()) {
691  os << " to ";
692  R->printPretty(os);
693  }
694  }
695 
696  // Construct a new PathDiagnosticPiece.
697  ProgramPoint P = StoreSite->getLocation();
699  if (P.getAs<CallEnter>() && InitE)
700  L = PathDiagnosticLocation(InitE, BRC.getSourceManager(),
701  P.getLocationContext());
702 
703  if (!L.isValid() || !L.asLocation().isValid())
705 
706  if (!L.isValid() || !L.asLocation().isValid())
707  return nullptr;
708 
709  return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
710 }
711 
712 void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
713  static int tag = 0;
714  ID.AddPointer(&tag);
715  ID.AddBoolean(Assumption);
716  ID.Add(Constraint);
717 }
718 
719 /// Return the tag associated with this visitor. This tag will be used
720 /// to make all PathDiagnosticPieces created by this visitor.
722  return "TrackConstraintBRVisitor";
723 }
724 
725 bool TrackConstraintBRVisitor::isUnderconstrained(const ExplodedNode *N) const {
726  if (IsZeroCheck)
727  return N->getState()->isNull(Constraint).isUnderconstrained();
728  return (bool)N->getState()->assume(Constraint, !Assumption);
729 }
730 
731 std::shared_ptr<PathDiagnosticPiece>
733  const ExplodedNode *PrevN,
734  BugReporterContext &BRC, 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 
777  auto X = std::make_shared<PathDiagnosticEventPiece>(L, os.str());
778  X->setTag(getTag());
779  return std::move(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 
810 std::shared_ptr<PathDiagnosticPiece>
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->IgnoreParenCasts()));
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();
966 
967  // Performing operator `&' on an lvalue expression is essentially a no-op.
968  // Then, if we are taking addresses of fields or elements, these are also
969  // unlikely to matter.
970  // FIXME: There's a hack in our Store implementation that always computes
971  // field offsets around null pointers as if they are always equal to 0.
972  // The idea here is to report accesses to fields as null dereferences
973  // even though the pointer value that's being dereferenced is actually
974  // the offset of the field rather than exactly 0.
975  // See the FIXME in StoreManager's getLValueFieldOrIvar() method.
976  // This code interacts heavily with this hack; otherwise the value
977  // would not be null at all for most fields, so we'd be unable to track it.
978  if (const auto *Op = dyn_cast<UnaryOperator>(Ex))
979  if (Op->getOpcode() == UO_AddrOf && Op->getSubExpr()->isLValue())
980  if (const Expr *DerefEx = getDerefExpr(Op->getSubExpr()))
981  Ex = DerefEx;
982 
984  Inner = Ex;
985  }
986 
987  if (IsArg && !Inner) {
988  assert(N->getLocation().getAs<CallEnter>() && "Tracking arg but not at call");
989  } else {
990  // Walk through nodes until we get one that matches the statement exactly.
991  // Alternately, if we hit a known lvalue for the statement, we know we've
992  // gone too far (though we can likely track the lvalue better anyway).
993  do {
994  const ProgramPoint &pp = N->getLocation();
995  if (Optional<StmtPoint> ps = pp.getAs<StmtPoint>()) {
996  if (ps->getStmt() == S || ps->getStmt() == Inner)
997  break;
998  } else if (Optional<CallExitEnd> CEE = pp.getAs<CallExitEnd>()) {
999  if (CEE->getCalleeContext()->getCallSite() == S ||
1000  CEE->getCalleeContext()->getCallSite() == Inner)
1001  break;
1002  }
1003  N = N->getFirstPred();
1004  } while (N);
1005 
1006  if (!N)
1007  return false;
1008  }
1009 
1011 
1012  // The message send could be nil due to the receiver being nil.
1013  // At this point in the path, the receiver should be live since we are at the
1014  // message send expr. If it is nil, start tracking it.
1015  if (const Expr *Receiver = NilReceiverBRVisitor::getNilReceiver(S, N))
1016  trackNullOrUndefValue(N, Receiver, report, false, EnableNullFPSuppression);
1017 
1018 
1019  // See if the expression we're interested refers to a variable.
1020  // If so, we can track both its contents and constraints on its value.
1021  if (Inner && ExplodedGraph::isInterestingLValueExpr(Inner)) {
1022  const MemRegion *R = nullptr;
1023 
1024  // Find the ExplodedNode where the lvalue (the value of 'Ex')
1025  // was computed. We need this for getting the location value.
1026  const ExplodedNode *LVNode = N;
1027  while (LVNode) {
1028  if (Optional<PostStmt> P = LVNode->getLocation().getAs<PostStmt>()) {
1029  if (P->getStmt() == Inner)
1030  break;
1031  }
1032  LVNode = LVNode->getFirstPred();
1033  }
1034  assert(LVNode && "Unable to find the lvalue node.");
1035  ProgramStateRef LVState = LVNode->getState();
1036  SVal LVal = LVState->getSVal(Inner, LVNode->getLocationContext());
1037 
1038  if (LVState->isNull(LVal).isConstrainedTrue()) {
1039  // In case of C++ references, we want to differentiate between a null
1040  // reference and reference to null pointer.
1041  // If the LVal is null, check if we are dealing with null reference.
1042  // For those, we want to track the location of the reference.
1043  if (const MemRegion *RR = getLocationRegionIfReference(Inner, N))
1044  R = RR;
1045  } else {
1046  R = LVState->getSVal(Inner, LVNode->getLocationContext()).getAsRegion();
1047 
1048  // If this is a C++ reference to a null pointer, we are tracking the
1049  // pointer. In addition, we should find the store at which the reference
1050  // got initialized.
1051  if (const MemRegion *RR = getLocationRegionIfReference(Inner, N)) {
1052  if (Optional<KnownSVal> KV = LVal.getAs<KnownSVal>())
1053  report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1054  *KV, RR, EnableNullFPSuppression));
1055  }
1056  }
1057 
1058  if (R) {
1059  // Mark both the variable region and its contents as interesting.
1060  SVal V = LVState->getRawSVal(loc::MemRegionVal(R));
1061 
1062  report.markInteresting(R);
1063  report.markInteresting(V);
1064  report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(R));
1065 
1066  // If the contents are symbolic, find out when they became null.
1067  if (V.getAsLocSymbol(/*IncludeBaseRegions*/ true))
1068  report.addVisitor(llvm::make_unique<TrackConstraintBRVisitor>(
1069  V.castAs<DefinedSVal>(), false));
1070 
1071  // Add visitor, which will suppress inline defensive checks.
1072  if (Optional<DefinedSVal> DV = V.getAs<DefinedSVal>()) {
1073  if (!DV->isZeroConstant() && LVState->isNull(*DV).isConstrainedTrue() &&
1074  EnableNullFPSuppression) {
1075  report.addVisitor(
1076  llvm::make_unique<SuppressInlineDefensiveChecksVisitor>(*DV,
1077  LVNode));
1078  }
1079  }
1080 
1081  if (Optional<KnownSVal> KV = V.getAs<KnownSVal>())
1082  report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1083  *KV, R, EnableNullFPSuppression));
1084  return true;
1085  }
1086  }
1087 
1088  // If the expression is not an "lvalue expression", we can still
1089  // track the constraints on its contents.
1090  SVal V = state->getSValAsScalarOrLoc(S, N->getLocationContext());
1091 
1092  // If the value came from an inlined function call, we should at least make
1093  // sure that function isn't pruned in our output.
1094  if (const Expr *E = dyn_cast<Expr>(S))
1095  S = E->IgnoreParenCasts();
1096 
1097  ReturnVisitor::addVisitorIfNecessary(N, S, report, EnableNullFPSuppression);
1098 
1099  // Uncomment this to find cases where we aren't properly getting the
1100  // base value that was dereferenced.
1101  // assert(!V.isUnknownOrUndef());
1102  // Is it a symbolic value?
1104  // At this point we are dealing with the region's LValue.
1105  // However, if the rvalue is a symbolic region, we should track it as well.
1106  // Try to use the correct type when looking up the value.
1107  SVal RVal;
1108  if (const Expr *E = dyn_cast<Expr>(S))
1109  RVal = state->getRawSVal(L.getValue(), E->getType());
1110  else
1111  RVal = state->getSVal(L->getRegion());
1112 
1113  const MemRegion *RegionRVal = RVal.getAsRegion();
1114  report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(L->getRegion()));
1115 
1116  if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) {
1117  report.markInteresting(RegionRVal);
1118  report.addVisitor(llvm::make_unique<TrackConstraintBRVisitor>(
1119  loc::MemRegionVal(RegionRVal), false));
1120  }
1121  }
1122 
1123  return true;
1124 }
1125 
1127  const ExplodedNode *N) {
1128  const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S);
1129  if (!ME)
1130  return nullptr;
1131  if (const Expr *Receiver = ME->getInstanceReceiver()) {
1133  SVal V = state->getSVal(Receiver, N->getLocationContext());
1134  if (state->isNull(V).isConstrainedTrue())
1135  return Receiver;
1136  }
1137  return nullptr;
1138 }
1139 
1140 std::shared_ptr<PathDiagnosticPiece>
1142  const ExplodedNode *PrevN,
1143  BugReporterContext &BRC, BugReport &BR) {
1145  if (!P)
1146  return nullptr;
1147 
1148  const Stmt *S = P->getStmt();
1149  const Expr *Receiver = getNilReceiver(S, N);
1150  if (!Receiver)
1151  return nullptr;
1152 
1154  llvm::raw_svector_ostream OS(Buf);
1155 
1156  if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
1157  OS << "'";
1158  ME->getSelector().print(OS);
1159  OS << "' not called";
1160  }
1161  else {
1162  OS << "No method is called";
1163  }
1164  OS << " because the receiver is nil";
1165 
1166  // The receiver was nil, and hence the method was skipped.
1167  // Register a BugReporterVisitor to issue a message telling us how
1168  // the receiver was null.
1169  bugreporter::trackNullOrUndefValue(N, Receiver, BR, /*IsArg*/ false,
1170  /*EnableNullFPSuppression*/ false);
1171  // Issue a message saying that the method was skipped.
1172  PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
1173  N->getLocationContext());
1174  return std::make_shared<PathDiagnosticEventPiece>(L, OS.str());
1175 }
1176 
1177 // Registers every VarDecl inside a Stmt with a last store visitor.
1179  const Stmt *S,
1180  bool EnableNullFPSuppression) {
1181  const ExplodedNode *N = BR.getErrorNode();
1182  std::deque<const Stmt *> WorkList;
1183  WorkList.push_back(S);
1184 
1185  while (!WorkList.empty()) {
1186  const Stmt *Head = WorkList.front();
1187  WorkList.pop_front();
1188 
1190  ProgramStateManager &StateMgr = state->getStateManager();
1191 
1192  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) {
1193  if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
1194  const VarRegion *R =
1195  StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
1196 
1197  // What did we load?
1198  SVal V = state->getSVal(S, N->getLocationContext());
1199 
1200  if (V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) {
1201  // Register a new visitor with the BugReport.
1202  BR.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1203  V.castAs<KnownSVal>(), R, EnableNullFPSuppression));
1204  }
1205  }
1206  }
1207 
1208  for (const Stmt *SubStmt : Head->children())
1209  WorkList.push_back(SubStmt);
1210  }
1211 }
1212 
1213 //===----------------------------------------------------------------------===//
1214 // Visitor that tries to report interesting diagnostics from conditions.
1215 //===----------------------------------------------------------------------===//
1216 
1217 /// Return the tag associated with this visitor. This tag will be used
1218 /// to make all PathDiagnosticPieces created by this visitor.
1220  return "ConditionBRVisitor";
1221 }
1222 
1223 std::shared_ptr<PathDiagnosticPiece>
1225  BugReporterContext &BRC, BugReport &BR) {
1226  auto piece = VisitNodeImpl(N, Prev, BRC, BR);
1227  if (piece) {
1228  piece->setTag(getTag());
1229  if (auto *ev = dyn_cast<PathDiagnosticEventPiece>(piece.get()))
1230  ev->setPrunable(true, /* override */ false);
1231  }
1232  return piece;
1233 }
1234 
1235 std::shared_ptr<PathDiagnosticPiece>
1237  const ExplodedNode *Prev,
1238  BugReporterContext &BRC, BugReport &BR) {
1239 
1240  ProgramPoint progPoint = N->getLocation();
1241  ProgramStateRef CurrentState = N->getState();
1242  ProgramStateRef PrevState = Prev->getState();
1243 
1244  // Compare the GDMs of the state, because that is where constraints
1245  // are managed. Note that ensure that we only look at nodes that
1246  // were generated by the analyzer engine proper, not checkers.
1247  if (CurrentState->getGDM().getRoot() ==
1248  PrevState->getGDM().getRoot())
1249  return nullptr;
1250 
1251  // If an assumption was made on a branch, it should be caught
1252  // here by looking at the state transition.
1253  if (Optional<BlockEdge> BE = progPoint.getAs<BlockEdge>()) {
1254  const CFGBlock *srcBlk = BE->getSrc();
1255  if (const Stmt *term = srcBlk->getTerminator())
1256  return VisitTerminator(term, N, srcBlk, BE->getDst(), BR, BRC);
1257  return nullptr;
1258  }
1259 
1260  if (Optional<PostStmt> PS = progPoint.getAs<PostStmt>()) {
1261  // FIXME: Assuming that BugReporter is a GRBugReporter is a layering
1262  // violation.
1263  const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags =
1264  cast<GRBugReporter>(BRC.getBugReporter()).
1265  getEngine().geteagerlyAssumeBinOpBifurcationTags();
1266 
1267  const ProgramPointTag *tag = PS->getTag();
1268  if (tag == tags.first)
1269  return VisitTrueTest(cast<Expr>(PS->getStmt()), true,
1270  BRC, BR, N);
1271  if (tag == tags.second)
1272  return VisitTrueTest(cast<Expr>(PS->getStmt()), false,
1273  BRC, BR, N);
1274 
1275  return nullptr;
1276  }
1277 
1278  return nullptr;
1279 }
1280 
1281 std::shared_ptr<PathDiagnosticPiece> ConditionBRVisitor::VisitTerminator(
1282  const Stmt *Term, const ExplodedNode *N, const CFGBlock *srcBlk,
1283  const CFGBlock *dstBlk, BugReport &R, BugReporterContext &BRC) {
1284  const Expr *Cond = nullptr;
1285 
1286  // In the code below, Term is a CFG terminator and Cond is a branch condition
1287  // expression upon which the decision is made on this terminator.
1288  //
1289  // For example, in "if (x == 0)", the "if (x == 0)" statement is a terminator,
1290  // and "x == 0" is the respective condition.
1291  //
1292  // Another example: in "if (x && y)", we've got two terminators and two
1293  // conditions due to short-circuit nature of operator "&&":
1294  // 1. The "if (x && y)" statement is a terminator,
1295  // and "y" is the respective condition.
1296  // 2. Also "x && ..." is another terminator,
1297  // and "x" is its condition.
1298 
1299  switch (Term->getStmtClass()) {
1300  // FIXME: Stmt::SwitchStmtClass is worth handling, however it is a bit
1301  // more tricky because there are more than two branches to account for.
1302  default:
1303  return nullptr;
1304  case Stmt::IfStmtClass:
1305  Cond = cast<IfStmt>(Term)->getCond();
1306  break;
1307  case Stmt::ConditionalOperatorClass:
1308  Cond = cast<ConditionalOperator>(Term)->getCond();
1309  break;
1310  case Stmt::BinaryOperatorClass:
1311  // When we encounter a logical operator (&& or ||) as a CFG terminator,
1312  // then the condition is actually its LHS; otherwise, we'd encounter
1313  // the parent, such as if-statement, as a terminator.
1314  const auto *BO = cast<BinaryOperator>(Term);
1315  assert(BO->isLogicalOp() &&
1316  "CFG terminator is not a short-circuit operator!");
1317  Cond = BO->getLHS();
1318  break;
1319  }
1320 
1321  // However, when we encounter a logical operator as a branch condition,
1322  // then the condition is actually its RHS, because LHS would be
1323  // the condition for the logical operator terminator.
1324  while (const auto *InnerBO = dyn_cast<BinaryOperator>(Cond)) {
1325  if (!InnerBO->isLogicalOp())
1326  break;
1327  Cond = InnerBO->getRHS()->IgnoreParens();
1328  }
1329 
1330  assert(Cond);
1331  assert(srcBlk->succ_size() == 2);
1332  const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk;
1333  return VisitTrueTest(Cond, tookTrue, BRC, R, N);
1334 }
1335 
1336 std::shared_ptr<PathDiagnosticPiece>
1337 ConditionBRVisitor::VisitTrueTest(const Expr *Cond, bool tookTrue,
1338  BugReporterContext &BRC, BugReport &R,
1339  const ExplodedNode *N) {
1340  // These will be modified in code below, but we need to preserve the original
1341  // values in case we want to throw the generic message.
1342  const Expr *CondTmp = Cond;
1343  bool tookTrueTmp = tookTrue;
1344 
1345  while (true) {
1346  CondTmp = CondTmp->IgnoreParenCasts();
1347  switch (CondTmp->getStmtClass()) {
1348  default:
1349  break;
1350  case Stmt::BinaryOperatorClass:
1351  if (auto P = VisitTrueTest(Cond, cast<BinaryOperator>(CondTmp),
1352  tookTrueTmp, BRC, R, N))
1353  return P;
1354  break;
1355  case Stmt::DeclRefExprClass:
1356  if (auto P = VisitTrueTest(Cond, cast<DeclRefExpr>(CondTmp),
1357  tookTrueTmp, BRC, R, N))
1358  return P;
1359  break;
1360  case Stmt::UnaryOperatorClass: {
1361  const UnaryOperator *UO = cast<UnaryOperator>(CondTmp);
1362  if (UO->getOpcode() == UO_LNot) {
1363  tookTrueTmp = !tookTrueTmp;
1364  CondTmp = UO->getSubExpr();
1365  continue;
1366  }
1367  break;
1368  }
1369  }
1370  break;
1371  }
1372 
1373  // Condition too complex to explain? Just say something so that the user
1374  // knew we've made some path decision at this point.
1375  const LocationContext *LCtx = N->getLocationContext();
1376  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
1377  if (!Loc.isValid() || !Loc.asLocation().isValid())
1378  return nullptr;
1379 
1380  return std::make_shared<PathDiagnosticEventPiece>(
1381  Loc, tookTrue ? GenericTrueMessage : GenericFalseMessage);
1382 }
1383 
1385  const Expr *ParentEx,
1386  raw_ostream &Out,
1387  BugReporterContext &BRC,
1388  BugReport &report,
1389  const ExplodedNode *N,
1390  Optional<bool> &prunable) {
1391  const Expr *OriginalExpr = Ex;
1392  Ex = Ex->IgnoreParenCasts();
1393 
1394  // Use heuristics to determine if Ex is a macro expending to a literal and
1395  // if so, use the macro's name.
1396  SourceLocation LocStart = Ex->getLocStart();
1397  SourceLocation LocEnd = Ex->getLocEnd();
1398  if (LocStart.isMacroID() && LocEnd.isMacroID() &&
1399  (isa<GNUNullExpr>(Ex) ||
1400  isa<ObjCBoolLiteralExpr>(Ex) ||
1401  isa<CXXBoolLiteralExpr>(Ex) ||
1402  isa<IntegerLiteral>(Ex) ||
1403  isa<FloatingLiteral>(Ex))) {
1404 
1405  StringRef StartName = Lexer::getImmediateMacroNameForDiagnostics(LocStart,
1406  BRC.getSourceManager(), BRC.getASTContext().getLangOpts());
1407  StringRef EndName = Lexer::getImmediateMacroNameForDiagnostics(LocEnd,
1408  BRC.getSourceManager(), BRC.getASTContext().getLangOpts());
1409  bool beginAndEndAreTheSameMacro = StartName.equals(EndName);
1410 
1411  bool partOfParentMacro = false;
1412  if (ParentEx->getLocStart().isMacroID()) {
1414  ParentEx->getLocStart(), BRC.getSourceManager(),
1415  BRC.getASTContext().getLangOpts());
1416  partOfParentMacro = PName.equals(StartName);
1417  }
1418 
1419  if (beginAndEndAreTheSameMacro && !partOfParentMacro ) {
1420  // Get the location of the macro name as written by the caller.
1421  SourceLocation Loc = LocStart;
1422  while (LocStart.isMacroID()) {
1423  Loc = LocStart;
1424  LocStart = BRC.getSourceManager().getImmediateMacroCallerLoc(LocStart);
1425  }
1426  StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics(
1427  Loc, BRC.getSourceManager(), BRC.getASTContext().getLangOpts());
1428 
1429  // Return the macro name.
1430  Out << MacroName;
1431  return false;
1432  }
1433  }
1434 
1435  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
1436  const bool quotes = isa<VarDecl>(DR->getDecl());
1437  if (quotes) {
1438  Out << '\'';
1439  const LocationContext *LCtx = N->getLocationContext();
1440  const ProgramState *state = N->getState().get();
1441  if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()),
1442  LCtx).getAsRegion()) {
1443  if (report.isInteresting(R))
1444  prunable = false;
1445  else {
1446  const ProgramState *state = N->getState().get();
1447  SVal V = state->getSVal(R);
1448  if (report.isInteresting(V))
1449  prunable = false;
1450  }
1451  }
1452  }
1453  Out << DR->getDecl()->getDeclName().getAsString();
1454  if (quotes)
1455  Out << '\'';
1456  return quotes;
1457  }
1458 
1459  if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) {
1460  QualType OriginalTy = OriginalExpr->getType();
1461  if (OriginalTy->isPointerType()) {
1462  if (IL->getValue() == 0) {
1463  Out << "null";
1464  return false;
1465  }
1466  }
1467  else if (OriginalTy->isObjCObjectPointerType()) {
1468  if (IL->getValue() == 0) {
1469  Out << "nil";
1470  return false;
1471  }
1472  }
1473 
1474  Out << IL->getValue();
1475  return false;
1476  }
1477 
1478  return false;
1479 }
1480 
1481 std::shared_ptr<PathDiagnosticPiece>
1483  const bool tookTrue, BugReporterContext &BRC,
1484  BugReport &R, const ExplodedNode *N) {
1485 
1486  bool shouldInvert = false;
1487  Optional<bool> shouldPrune;
1488 
1489  SmallString<128> LhsString, RhsString;
1490  {
1491  llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
1492  const bool isVarLHS = patternMatch(BExpr->getLHS(), BExpr, OutLHS,
1493  BRC, R, N, shouldPrune);
1494  const bool isVarRHS = patternMatch(BExpr->getRHS(), BExpr, OutRHS,
1495  BRC, R, N, shouldPrune);
1496 
1497  shouldInvert = !isVarLHS && isVarRHS;
1498  }
1499 
1500  BinaryOperator::Opcode Op = BExpr->getOpcode();
1501 
1503  // For assignment operators, all that we care about is that the LHS
1504  // evaluates to "true" or "false".
1505  return VisitConditionVariable(LhsString, BExpr->getLHS(), tookTrue,
1506  BRC, R, N);
1507  }
1508 
1509  // For non-assignment operations, we require that we can understand
1510  // both the LHS and RHS.
1511  if (LhsString.empty() || RhsString.empty() ||
1513  return nullptr;
1514 
1515  // Should we invert the strings if the LHS is not a variable name?
1516  SmallString<256> buf;
1517  llvm::raw_svector_ostream Out(buf);
1518  Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is ";
1519 
1520  // Do we need to invert the opcode?
1521  if (shouldInvert)
1522  switch (Op) {
1523  default: break;
1524  case BO_LT: Op = BO_GT; break;
1525  case BO_GT: Op = BO_LT; break;
1526  case BO_LE: Op = BO_GE; break;
1527  case BO_GE: Op = BO_LE; break;
1528  }
1529 
1530  if (!tookTrue)
1531  switch (Op) {
1532  case BO_EQ: Op = BO_NE; break;
1533  case BO_NE: Op = BO_EQ; break;
1534  case BO_LT: Op = BO_GE; break;
1535  case BO_GT: Op = BO_LE; break;
1536  case BO_LE: Op = BO_GT; break;
1537  case BO_GE: Op = BO_LT; break;
1538  default:
1539  return nullptr;
1540  }
1541 
1542  switch (Op) {
1543  case BO_EQ:
1544  Out << "equal to ";
1545  break;
1546  case BO_NE:
1547  Out << "not equal to ";
1548  break;
1549  default:
1550  Out << BinaryOperator::getOpcodeStr(Op) << ' ';
1551  break;
1552  }
1553 
1554  Out << (shouldInvert ? LhsString : RhsString);
1555  const LocationContext *LCtx = N->getLocationContext();
1556  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
1557  auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
1558  if (shouldPrune.hasValue())
1559  event->setPrunable(shouldPrune.getValue());
1560  return event;
1561 }
1562 
1563 std::shared_ptr<PathDiagnosticPiece> ConditionBRVisitor::VisitConditionVariable(
1564  StringRef LhsString, const Expr *CondVarExpr, const bool tookTrue,
1565  BugReporterContext &BRC, BugReport &report, const ExplodedNode *N) {
1566  // FIXME: If there's already a constraint tracker for this variable,
1567  // we shouldn't emit anything here (c.f. the double note in
1568  // test/Analysis/inlining/path-notes.c)
1569  SmallString<256> buf;
1570  llvm::raw_svector_ostream Out(buf);
1571  Out << "Assuming " << LhsString << " is ";
1572 
1573  QualType Ty = CondVarExpr->getType();
1574 
1575  if (Ty->isPointerType())
1576  Out << (tookTrue ? "not null" : "null");
1577  else if (Ty->isObjCObjectPointerType())
1578  Out << (tookTrue ? "not nil" : "nil");
1579  else if (Ty->isBooleanType())
1580  Out << (tookTrue ? "true" : "false");
1581  else if (Ty->isIntegralOrEnumerationType())
1582  Out << (tookTrue ? "non-zero" : "zero");
1583  else
1584  return nullptr;
1585 
1586  const LocationContext *LCtx = N->getLocationContext();
1587  PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
1588  auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
1589 
1590  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) {
1591  if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
1592  const ProgramState *state = N->getState().get();
1593  if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
1594  if (report.isInteresting(R))
1595  event->setPrunable(false);
1596  }
1597  }
1598  }
1599 
1600  return event;
1601 }
1602 
1603 std::shared_ptr<PathDiagnosticPiece>
1605  const bool tookTrue, BugReporterContext &BRC,
1606  BugReport &report, const ExplodedNode *N) {
1607 
1608  const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
1609  if (!VD)
1610  return nullptr;
1611 
1612  SmallString<256> Buf;
1613  llvm::raw_svector_ostream Out(Buf);
1614 
1615  Out << "Assuming '" << VD->getDeclName() << "' is ";
1616 
1617  QualType VDTy = VD->getType();
1618 
1619  if (VDTy->isPointerType())
1620  Out << (tookTrue ? "non-null" : "null");
1621  else if (VDTy->isObjCObjectPointerType())
1622  Out << (tookTrue ? "non-nil" : "nil");
1623  else if (VDTy->isScalarType())
1624  Out << (tookTrue ? "not equal to 0" : "0");
1625  else
1626  return nullptr;
1627 
1628  const LocationContext *LCtx = N->getLocationContext();
1629  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
1630  auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
1631 
1632  const ProgramState *state = N->getState().get();
1633  if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
1634  if (report.isInteresting(R))
1635  event->setPrunable(false);
1636  else {
1637  SVal V = state->getSVal(R);
1638  if (report.isInteresting(V))
1639  event->setPrunable(false);
1640  }
1641  }
1642  return std::move(event);
1643 }
1644 
1645 const char *const ConditionBRVisitor::GenericTrueMessage =
1646  "Assuming the condition is true";
1647 const char *const ConditionBRVisitor::GenericFalseMessage =
1648  "Assuming the condition is false";
1649 
1651  const PathDiagnosticPiece *Piece) {
1652  return Piece->getString() == GenericTrueMessage ||
1653  Piece->getString() == GenericFalseMessage;
1654 }
1655 
1656 std::unique_ptr<PathDiagnosticPiece>
1658  const ExplodedNode *N,
1659  BugReport &BR) {
1660  // Here we suppress false positives coming from system headers. This list is
1661  // based on known issues.
1662  ExprEngine &Eng = BRC.getBugReporter().getEngine();
1663  AnalyzerOptions &Options = Eng.getAnalysisManager().options;
1664  const Decl *D = N->getLocationContext()->getDecl();
1665 
1667  // Skip reports within the 'std' namespace. Although these can sometimes be
1668  // the user's fault, we currently don't report them very well, and
1669  // Note that this will not help for any other data structure libraries, like
1670  // TR1, Boost, or llvm/ADT.
1671  if (Options.shouldSuppressFromCXXStandardLibrary()) {
1672  BR.markInvalid(getTag(), nullptr);
1673  return nullptr;
1674 
1675  } else {
1676  // If the complete 'std' suppression is not enabled, suppress reports
1677  // from the 'std' namespace that are known to produce false positives.
1678 
1679  // The analyzer issues a false use-after-free when std::list::pop_front
1680  // or std::list::pop_back are called multiple times because we cannot
1681  // reason about the internal invariants of the data structure.
1682  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
1683  const CXXRecordDecl *CD = MD->getParent();
1684  if (CD->getName() == "list") {
1685  BR.markInvalid(getTag(), nullptr);
1686  return nullptr;
1687  }
1688  }
1689 
1690  // The analyzer issues a false positive when the constructor of
1691  // std::__independent_bits_engine from algorithms is used.
1692  if (const CXXConstructorDecl *MD = dyn_cast<CXXConstructorDecl>(D)) {
1693  const CXXRecordDecl *CD = MD->getParent();
1694  if (CD->getName() == "__independent_bits_engine") {
1695  BR.markInvalid(getTag(), nullptr);
1696  return nullptr;
1697  }
1698  }
1699 
1700  for (const LocationContext *LCtx = N->getLocationContext(); LCtx;
1701  LCtx = LCtx->getParent()) {
1702  const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
1703  if (!MD)
1704  continue;
1705 
1706  const CXXRecordDecl *CD = MD->getParent();
1707  // The analyzer issues a false positive on
1708  // std::basic_string<uint8_t> v; v.push_back(1);
1709  // and
1710  // std::u16string s; s += u'a';
1711  // because we cannot reason about the internal invariants of the
1712  // data structure.
1713  if (CD->getName() == "basic_string") {
1714  BR.markInvalid(getTag(), nullptr);
1715  return nullptr;
1716  }
1717 
1718  // The analyzer issues a false positive on
1719  // std::shared_ptr<int> p(new int(1)); p = nullptr;
1720  // because it does not reason properly about temporary destructors.
1721  if (CD->getName() == "shared_ptr") {
1722  BR.markInvalid(getTag(), nullptr);
1723  return nullptr;
1724  }
1725  }
1726  }
1727  }
1728 
1729  // Skip reports within the sys/queue.h macros as we do not have the ability to
1730  // reason about data structure shapes.
1733  while (Loc.isMacroID()) {
1734  Loc = Loc.getSpellingLoc();
1735  if (SM.getFilename(Loc).endswith("sys/queue.h")) {
1736  BR.markInvalid(getTag(), nullptr);
1737  return nullptr;
1738  }
1739  }
1740 
1741  return nullptr;
1742 }
1743 
1744 std::shared_ptr<PathDiagnosticPiece>
1746  const ExplodedNode *PrevN,
1747  BugReporterContext &BRC, BugReport &BR) {
1748 
1749  ProgramStateRef State = N->getState();
1750  ProgramPoint ProgLoc = N->getLocation();
1751 
1752  // We are only interested in visiting CallEnter nodes.
1753  Optional<CallEnter> CEnter = ProgLoc.getAs<CallEnter>();
1754  if (!CEnter)
1755  return nullptr;
1756 
1757  // Check if one of the arguments is the region the visitor is tracking.
1759  CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State);
1760  unsigned Idx = 0;
1761  ArrayRef<ParmVarDecl*> parms = Call->parameters();
1762 
1763  for (ArrayRef<ParmVarDecl*>::iterator I = parms.begin(), E = parms.end();
1764  I != E; ++I, ++Idx) {
1765  const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion();
1766 
1767  // Are we tracking the argument or its subregion?
1768  if ( !ArgReg || (ArgReg != R && !R->isSubRegionOf(ArgReg->StripCasts())))
1769  continue;
1770 
1771  // Check the function parameter type.
1772  const ParmVarDecl *ParamDecl = *I;
1773  assert(ParamDecl && "Formal parameter has no decl?");
1774  QualType T = ParamDecl->getType();
1775 
1776  if (!(T->isAnyPointerType() || T->isReferenceType())) {
1777  // Function can only change the value passed in by address.
1778  continue;
1779  }
1780 
1781  // If it is a const pointer value, the function does not intend to
1782  // change the value.
1783  if (T->getPointeeType().isConstQualified())
1784  continue;
1785 
1786  // Mark the call site (LocationContext) as interesting if the value of the
1787  // argument is undefined or '0'/'NULL'.
1788  SVal BoundVal = State->getSVal(R);
1789  if (BoundVal.isUndef() || BoundVal.isZeroConstant()) {
1790  BR.markInteresting(CEnter->getCalleeContext());
1791  return nullptr;
1792  }
1793  }
1794  return nullptr;
1795 }
1796 
1797 std::shared_ptr<PathDiagnosticPiece>
1799  const ExplodedNode *Pred,
1800  BugReporterContext &BRC, BugReport &BR) {
1801  if (Satisfied)
1802  return nullptr;
1803 
1804  auto Edge = Succ->getLocation().getAs<BlockEdge>();
1805  if (!Edge.hasValue())
1806  return nullptr;
1807 
1808  auto Tag = Edge->getTag();
1809  if (!Tag)
1810  return nullptr;
1811 
1812  if (Tag->getTagDescription() != "cplusplus.SelfAssignment")
1813  return nullptr;
1814 
1815  Satisfied = true;
1816 
1817  const auto *Met =
1818  dyn_cast<CXXMethodDecl>(Succ->getCodeDecl().getAsFunction());
1819  assert(Met && "Not a C++ method.");
1820  assert((Met->isCopyAssignmentOperator() || Met->isMoveAssignmentOperator()) &&
1821  "Not a copy/move assignment operator.");
1822 
1823  const auto *LCtx = Edge->getLocationContext();
1824 
1825  const auto &State = Succ->getState();
1826  auto &SVB = State->getStateManager().getSValBuilder();
1827 
1828  const auto Param =
1829  State->getSVal(State->getRegion(Met->getParamDecl(0), LCtx));
1830  const auto This =
1831  State->getSVal(SVB.getCXXThis(Met, LCtx->getCurrentStackFrame()));
1832 
1833  auto L = PathDiagnosticLocation::create(Met, BRC.getSourceManager());
1834 
1835  if (!L.isValid() || !L.asLocation().isValid())
1836  return nullptr;
1837 
1838  SmallString<256> Buf;
1839  llvm::raw_svector_ostream Out(Buf);
1840 
1841  Out << "Assuming " << Met->getParamDecl(0)->getName() <<
1842  ((Param == This) ? " == " : " != ") << "*this";
1843 
1844  auto Piece = std::make_shared<PathDiagnosticEventPiece>(L, Out.str());
1845  Piece->addRange(Met->getSourceRange());
1846 
1847  return std::move(Piece);
1848 }
ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC property.
Definition: ExprObjC.h:539
StmtClass getStmtClass() const
Definition: Stmt.h:361
TypedValueRegion - An abstract class representing regions having a typed value.
Definition: MemRegion.h:511
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
This is a discriminated union of FileInfo and ExpansionInfo.
A (possibly-)qualified type.
Definition: Type.h:616
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:79
bool isMacroID() const
std::shared_ptr< 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.
bool isInteresting(SymbolRef sym)
succ_iterator succ_begin()
Definition: CFG.h:576
virtual bool canPrintPretty() const
Returns true if this region can be printed in a user-friendly way.
Definition: MemRegion.cpp:526
const ExplodedNode * getErrorNode() const
Definition: BugReporter.h:194
Stmt - This represents one statement.
Definition: Stmt.h:60
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.
unsigned getFunctionScopeIndex() const
Returns the index of this parameter in its prototype or method scope.
Definition: Decl.h:1487
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:81
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:995
StringRef P
Each ExpansionInfo encodes the expansion location - where the token was ultimately expanded...
const ExpansionInfo & getExpansion() const
const Expr * getInit() const
Definition: Decl.h:1146
bool isBooleanType() const
Definition: Type.h:5969
MemSpaceRegion - A memory region that represents a "memory space"; for example, the set of global var...
Definition: MemRegion.h:179
std::shared_ptr< PathDiagnosticPiece > VisitNodeImpl(const ExplodedNode *N, const ExplodedNode *Prev, BugReporterContext &BRC, BugReport &BR)
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:2329
Value representing integer constant.
Definition: SVals.h:352
VarDecl - An instance of this class is created to represent a variable declaration or definition...
Definition: Decl.h:758
unsigned succ_size() const
Definition: CFG.h:593
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:2920
ParmVarDecl - Represents a parameter to a function.
Definition: Decl.h:1434
bool isZeroConstant() const
Definition: SVals.cpp:219
FullSourceLoc asLocation() const
bool isComparisonOp() const
Definition: Expr.h:3058
const MemSpaceRegion * getMemorySpace() const
Definition: MemRegion.cpp:1059
void Profile(llvm::FoldingSetNodeID &ID) const override
bool isScalarType() const
Definition: Type.h:5941
std::shared_ptr< PathDiagnosticPiece > VisitTrueTest(const Expr *Cond, bool tookTrue, BugReporterContext &BRC, BugReport &R, const ExplodedNode *N)
LineState State
bool isReferenceType() const
Definition: Type.h:5721
bool isAnyPointerType() const
Definition: Type.h:5715
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:520
SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const
If this SVal is a location and wraps a symbol, return that SymbolRef.
Definition: SVals.cpp:74
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
Expr * getLHS() const
Definition: Expr.h:3011
const VarDecl * getDecl() const
Definition: MemRegion.h:935
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:656
static bool isInStdNamespace(const Decl *D)
Returns true if the root namespace of the given declaration is the 'std' C++ namespace.
const LangOptions & getLangOpts() const
Definition: ASTContext.h:659
SourceLocation getImmediateMacroCallerLoc(SourceLocation Loc) const
Gets the location of the immediate macro caller, one level up the stack toward the initial macro type...
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
Definition: DeclCXX.h:2018
child_range children()
Definition: Stmt.cpp:208
std::shared_ptr< PathDiagnosticPiece > VisitConditionVariable(StringRef LhsString, const Expr *CondVarExpr, const bool tookTrue, BugReporterContext &BRC, BugReport &R, const ExplodedNode *N)
bool isUnknownOrUndef() const
Definition: SVals.h:136
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:2967
const Stmt * getCallSite() const
bool isParentOf(const LocationContext *LC) const
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
Definition: Expr.cpp:2399
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:196
ExplodedNode * getFirstPred()
bool isStaticLocal() const
isStaticLocal - Returns true if a variable with function scope is a static local variable.
Definition: Decl.h:987
std::shared_ptr< 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.
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:589
const LocationContext * getLocationContext() const
const StackFrameContext * getStackFrame() const
Definition: MemRegion.h:379
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:3245
bool isAssignmentOp() const
Definition: Expr.h:3093
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:636
std::shared_ptr< 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.
SourceLocation getLocEnd() const LLVM_READONLY
Definition: Stmt.cpp:270
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:377
const MemRegion * StripCasts(bool StripBaseCasts=true) const
Definition: MemRegion.cpp:1117
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:414
ProgramState - This class encapsulates:
Definition: ProgramState.h:74
Expr - This represents one expression.
Definition: Expr.h:105
const ProgramStateRef & getState() const
static bool isPieceMessageGeneric(const PathDiagnosticPiece *Piece)
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:1132
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:738
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:100
std::shared_ptr< 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.
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...
bool patternMatch(const Expr *Ex, const Expr *ParentEx, raw_ostream &Out, BugReporterContext &BRC, BugReport &R, const ExplodedNode *N, Optional< bool > &prunable)
void Profile(llvm::FoldingSetNodeID &ID) const override
SuppressInlineDefensiveChecksVisitor(DefinedSVal Val, const ExplodedNode *N)
std::shared_ptr< 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.
Expr * getSubExpr() const
Definition: Expr.h:1741
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:1294
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
Definition: Stmt.h:1392
An expression that sends a message to the given Objective-C object or class.
Definition: ExprObjC.h:860
unsigned Map[FirstTargetAddressSpace]
The type of a lookup table which maps from language-specific address spaces to target-specific ones...
Definition: AddressSpaces.h:53
UnaryOperator - This represents the unary-expression's (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
Definition: Expr.h:1714
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:1038
bool isGLValue() const
Definition: Expr.h:251
std::shared_ptr< 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.
const SourceManager & SM
Definition: Format.cpp:1293
std::shared_ptr< 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.
const MatchFinder::MatchFinderOptions & Options
CFGTerminator getTerminator()
Definition: CFG.h:664
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class...
Definition: Expr.h:865
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:5956
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
Definition: DeclBase.cpp:199
Encodes a location in the source.
std::shared_ptr< PathDiagnosticPiece > VisitTerminator(const Stmt *Term, const ExplodedNode *N, const CFGBlock *srcBlk, const CFGBlock *dstBlk, BugReport &R, BugReporterContext &BRC)
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:268
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:527
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Definition: Stmt.h:467
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:1903
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:63
const Decl * getDecl() const
virtual void printPretty(raw_ostream &os) const
Print the region for use in diagnostics.
Definition: MemRegion.cpp:534
bool isUndef() const
Definition: SVals.h:132
static StringRef getImmediateMacroNameForDiagnostics(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Retrieve the name of the immediate macro expansion.
Definition: Lexer.cpp:1006
Opcode getOpcode() const
Definition: Expr.h:1738
const Decl * getSingleDecl() const
Definition: Stmt.h:485
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:127
bool isDeclRefExprToReference(const Expr *E)
const LocationContext * getParent() const
StringRef getOpcodeStr() const
Definition: Expr.h:3027
const Decl & getCodeDecl() const
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:781
static const char * getTag()
Return the tag associated with this visitor.
GRBugReporter & getBugReporter()
Definition: BugReporter.h:549
const Stmt * GetRetValExpr(const ExplodedNode *N)
detail::InMemoryDirectory::const_iterator E
const MemRegion * getAsRegion() const
Definition: SVals.cpp:140
const Expr * getRetValue() const
Definition: Stmt.cpp:905
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
Definition: ProgramPoint.h:150
Represents an SVal that is guaranteed to not be UnknownVal.
Definition: SVals.h:266
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2118
ProgramStateManager & getStateManager()
Definition: BugReporter.h:553
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:13074
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:2378
const ProgramPointTag * getTag() const
Definition: ProgramPoint.h:176
Represents a C++ struct/union/class.
Definition: DeclCXX.h:267
bool isObjCObjectPointerType() const
Definition: Type.h:5784
Opcode getOpcode() const
Definition: Expr.h:3008
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.
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:249
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:242
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:704
Expr * getRHS() const
Definition: Expr.h:3013
A SourceLocation and its associated SourceManager.
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:953
virtual bool isSubRegionOf(const MemRegion *R) const
Check if the region is a subregion of the given region.
Definition: MemRegion.cpp:1109
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:5548
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Definition: SVals.h:92
SourceLocation getLocStart() const LLVM_READONLY
Definition: Stmt.cpp:257
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:565
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
Expr * IgnoreParens() LLVM_READONLY
IgnoreParens - Ignore parentheses.
Definition: Expr.cpp:2368
virtual AnalysisManager & getAnalysisManager()=0
ExprEngine & getEngine()
getEngine - Return the analysis engine used to analyze a given function or method.
Definition: BugReporter.h:514
static const char * getTag()
Return the tag associated with this visitor.
bool isPointerType() const
Definition: Type.h:5712