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