clang  6.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 
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  S = peelOffOuterExpr(Ex, N);
990 
991  const Expr *Inner = nullptr;
992  if (const Expr *Ex = dyn_cast<Expr>(S)) {
993  Ex = Ex->IgnoreParenCasts();
994 
995  // Performing operator `&' on an lvalue expression is essentially a no-op.
996  // Then, if we are taking addresses of fields or elements, these are also
997  // unlikely to matter.
998  // FIXME: There's a hack in our Store implementation that always computes
999  // field offsets around null pointers as if they are always equal to 0.
1000  // The idea here is to report accesses to fields as null dereferences
1001  // even though the pointer value that's being dereferenced is actually
1002  // the offset of the field rather than exactly 0.
1003  // See the FIXME in StoreManager's getLValueFieldOrIvar() method.
1004  // This code interacts heavily with this hack; otherwise the value
1005  // would not be null at all for most fields, so we'd be unable to track it.
1006  if (const auto *Op = dyn_cast<UnaryOperator>(Ex))
1007  if (Op->getOpcode() == UO_AddrOf && Op->getSubExpr()->isLValue())
1008  if (const Expr *DerefEx = getDerefExpr(Op->getSubExpr()))
1009  Ex = DerefEx;
1010 
1012  Inner = Ex;
1013  }
1014 
1015  if (IsArg && !Inner) {
1016  assert(N->getLocation().getAs<CallEnter>() && "Tracking arg but not at call");
1017  } else {
1018  // Walk through nodes until we get one that matches the statement exactly.
1019  // Alternately, if we hit a known lvalue for the statement, we know we've
1020  // gone too far (though we can likely track the lvalue better anyway).
1021  do {
1022  const ProgramPoint &pp = N->getLocation();
1023  if (Optional<StmtPoint> ps = pp.getAs<StmtPoint>()) {
1024  if (ps->getStmt() == S || ps->getStmt() == Inner)
1025  break;
1026  } else if (Optional<CallExitEnd> CEE = pp.getAs<CallExitEnd>()) {
1027  if (CEE->getCalleeContext()->getCallSite() == S ||
1028  CEE->getCalleeContext()->getCallSite() == Inner)
1029  break;
1030  }
1031  N = N->getFirstPred();
1032  } while (N);
1033 
1034  if (!N)
1035  return false;
1036  }
1037 
1039 
1040  // The message send could be nil due to the receiver being nil.
1041  // At this point in the path, the receiver should be live since we are at the
1042  // message send expr. If it is nil, start tracking it.
1043  if (const Expr *Receiver = NilReceiverBRVisitor::getNilReceiver(S, N))
1044  trackNullOrUndefValue(N, Receiver, report, false, EnableNullFPSuppression);
1045 
1046 
1047  // See if the expression we're interested refers to a variable.
1048  // If so, we can track both its contents and constraints on its value.
1049  if (Inner && ExplodedGraph::isInterestingLValueExpr(Inner)) {
1050  const MemRegion *R = nullptr;
1051 
1052  // Find the ExplodedNode where the lvalue (the value of 'Ex')
1053  // was computed. We need this for getting the location value.
1054  const ExplodedNode *LVNode = N;
1055  while (LVNode) {
1056  if (Optional<PostStmt> P = LVNode->getLocation().getAs<PostStmt>()) {
1057  if (P->getStmt() == Inner)
1058  break;
1059  }
1060  LVNode = LVNode->getFirstPred();
1061  }
1062  assert(LVNode && "Unable to find the lvalue node.");
1063  ProgramStateRef LVState = LVNode->getState();
1064  SVal LVal = LVState->getSVal(Inner, LVNode->getLocationContext());
1065 
1066  if (LVState->isNull(LVal).isConstrainedTrue()) {
1067  // In case of C++ references, we want to differentiate between a null
1068  // reference and reference to null pointer.
1069  // If the LVal is null, check if we are dealing with null reference.
1070  // For those, we want to track the location of the reference.
1071  if (const MemRegion *RR = getLocationRegionIfReference(Inner, N))
1072  R = RR;
1073  } else {
1074  R = LVState->getSVal(Inner, LVNode->getLocationContext()).getAsRegion();
1075 
1076  // If this is a C++ reference to a null pointer, we are tracking the
1077  // pointer. In addition, we should find the store at which the reference
1078  // got initialized.
1079  if (const MemRegion *RR = getLocationRegionIfReference(Inner, N)) {
1080  if (Optional<KnownSVal> KV = LVal.getAs<KnownSVal>())
1081  report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1082  *KV, RR, EnableNullFPSuppression));
1083  }
1084  }
1085 
1086  if (R) {
1087  // Mark both the variable region and its contents as interesting.
1088  SVal V = LVState->getRawSVal(loc::MemRegionVal(R));
1089 
1090  report.markInteresting(R);
1091  report.markInteresting(V);
1092  report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(R));
1093 
1094  // If the contents are symbolic, find out when they became null.
1095  if (V.getAsLocSymbol(/*IncludeBaseRegions*/ true))
1096  report.addVisitor(llvm::make_unique<TrackConstraintBRVisitor>(
1097  V.castAs<DefinedSVal>(), false));
1098 
1099  // Add visitor, which will suppress inline defensive checks.
1100  if (Optional<DefinedSVal> DV = V.getAs<DefinedSVal>()) {
1101  if (!DV->isZeroConstant() && LVState->isNull(*DV).isConstrainedTrue() &&
1102  EnableNullFPSuppression) {
1103  report.addVisitor(
1104  llvm::make_unique<SuppressInlineDefensiveChecksVisitor>(*DV,
1105  LVNode));
1106  }
1107  }
1108 
1109  if (Optional<KnownSVal> KV = V.getAs<KnownSVal>())
1110  report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1111  *KV, R, EnableNullFPSuppression));
1112  return true;
1113  }
1114  }
1115 
1116  // If the expression is not an "lvalue expression", we can still
1117  // track the constraints on its contents.
1118  SVal V = state->getSValAsScalarOrLoc(S, N->getLocationContext());
1119 
1120  // If the value came from an inlined function call, we should at least make
1121  // sure that function isn't pruned in our output.
1122  if (const Expr *E = dyn_cast<Expr>(S))
1123  S = E->IgnoreParenCasts();
1124 
1125  ReturnVisitor::addVisitorIfNecessary(N, S, report, EnableNullFPSuppression);
1126 
1127  // Uncomment this to find cases where we aren't properly getting the
1128  // base value that was dereferenced.
1129  // assert(!V.isUnknownOrUndef());
1130  // Is it a symbolic value?
1132  // At this point we are dealing with the region's LValue.
1133  // However, if the rvalue is a symbolic region, we should track it as well.
1134  // Try to use the correct type when looking up the value.
1135  SVal RVal;
1136  if (const Expr *E = dyn_cast<Expr>(S))
1137  RVal = state->getRawSVal(L.getValue(), E->getType());
1138  else
1139  RVal = state->getSVal(L->getRegion());
1140 
1141  report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(L->getRegion()));
1142  if (Optional<KnownSVal> KV = RVal.getAs<KnownSVal>())
1143  report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1144  *KV, L->getRegion(), EnableNullFPSuppression));
1145 
1146  const MemRegion *RegionRVal = RVal.getAsRegion();
1147  if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) {
1148  report.markInteresting(RegionRVal);
1149  report.addVisitor(llvm::make_unique<TrackConstraintBRVisitor>(
1150  loc::MemRegionVal(RegionRVal), false));
1151  }
1152  }
1153 
1154  return true;
1155 }
1156 
1158  const ExplodedNode *N) {
1159  const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S);
1160  if (!ME)
1161  return nullptr;
1162  if (const Expr *Receiver = ME->getInstanceReceiver()) {
1164  SVal V = state->getSVal(Receiver, N->getLocationContext());
1165  if (state->isNull(V).isConstrainedTrue())
1166  return Receiver;
1167  }
1168  return nullptr;
1169 }
1170 
1171 std::shared_ptr<PathDiagnosticPiece>
1173  const ExplodedNode *PrevN,
1174  BugReporterContext &BRC, BugReport &BR) {
1176  if (!P)
1177  return nullptr;
1178 
1179  const Stmt *S = P->getStmt();
1180  const Expr *Receiver = getNilReceiver(S, N);
1181  if (!Receiver)
1182  return nullptr;
1183 
1185  llvm::raw_svector_ostream OS(Buf);
1186 
1187  if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
1188  OS << "'";
1189  ME->getSelector().print(OS);
1190  OS << "' not called";
1191  }
1192  else {
1193  OS << "No method is called";
1194  }
1195  OS << " because the receiver is nil";
1196 
1197  // The receiver was nil, and hence the method was skipped.
1198  // Register a BugReporterVisitor to issue a message telling us how
1199  // the receiver was null.
1200  bugreporter::trackNullOrUndefValue(N, Receiver, BR, /*IsArg*/ false,
1201  /*EnableNullFPSuppression*/ false);
1202  // Issue a message saying that the method was skipped.
1203  PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
1204  N->getLocationContext());
1205  return std::make_shared<PathDiagnosticEventPiece>(L, OS.str());
1206 }
1207 
1208 // Registers every VarDecl inside a Stmt with a last store visitor.
1210  const Stmt *S,
1211  bool EnableNullFPSuppression) {
1212  const ExplodedNode *N = BR.getErrorNode();
1213  std::deque<const Stmt *> WorkList;
1214  WorkList.push_back(S);
1215 
1216  while (!WorkList.empty()) {
1217  const Stmt *Head = WorkList.front();
1218  WorkList.pop_front();
1219 
1221  ProgramStateManager &StateMgr = state->getStateManager();
1222 
1223  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) {
1224  if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
1225  const VarRegion *R =
1226  StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
1227 
1228  // What did we load?
1229  SVal V = state->getSVal(S, N->getLocationContext());
1230 
1231  if (V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) {
1232  // Register a new visitor with the BugReport.
1233  BR.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1234  V.castAs<KnownSVal>(), R, EnableNullFPSuppression));
1235  }
1236  }
1237  }
1238 
1239  for (const Stmt *SubStmt : Head->children())
1240  WorkList.push_back(SubStmt);
1241  }
1242 }
1243 
1244 //===----------------------------------------------------------------------===//
1245 // Visitor that tries to report interesting diagnostics from conditions.
1246 //===----------------------------------------------------------------------===//
1247 
1248 /// Return the tag associated with this visitor. This tag will be used
1249 /// to make all PathDiagnosticPieces created by this visitor.
1251  return "ConditionBRVisitor";
1252 }
1253 
1254 std::shared_ptr<PathDiagnosticPiece>
1256  BugReporterContext &BRC, BugReport &BR) {
1257  auto piece = VisitNodeImpl(N, Prev, BRC, BR);
1258  if (piece) {
1259  piece->setTag(getTag());
1260  if (auto *ev = dyn_cast<PathDiagnosticEventPiece>(piece.get()))
1261  ev->setPrunable(true, /* override */ false);
1262  }
1263  return piece;
1264 }
1265 
1266 std::shared_ptr<PathDiagnosticPiece>
1268  const ExplodedNode *Prev,
1269  BugReporterContext &BRC, BugReport &BR) {
1270 
1271  ProgramPoint progPoint = N->getLocation();
1272  ProgramStateRef CurrentState = N->getState();
1273  ProgramStateRef PrevState = Prev->getState();
1274 
1275  // Compare the GDMs of the state, because that is where constraints
1276  // are managed. Note that ensure that we only look at nodes that
1277  // were generated by the analyzer engine proper, not checkers.
1278  if (CurrentState->getGDM().getRoot() ==
1279  PrevState->getGDM().getRoot())
1280  return nullptr;
1281 
1282  // If an assumption was made on a branch, it should be caught
1283  // here by looking at the state transition.
1284  if (Optional<BlockEdge> BE = progPoint.getAs<BlockEdge>()) {
1285  const CFGBlock *srcBlk = BE->getSrc();
1286  if (const Stmt *term = srcBlk->getTerminator())
1287  return VisitTerminator(term, N, srcBlk, BE->getDst(), BR, BRC);
1288  return nullptr;
1289  }
1290 
1291  if (Optional<PostStmt> PS = progPoint.getAs<PostStmt>()) {
1292  // FIXME: Assuming that BugReporter is a GRBugReporter is a layering
1293  // violation.
1294  const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags =
1295  cast<GRBugReporter>(BRC.getBugReporter()).
1296  getEngine().geteagerlyAssumeBinOpBifurcationTags();
1297 
1298  const ProgramPointTag *tag = PS->getTag();
1299  if (tag == tags.first)
1300  return VisitTrueTest(cast<Expr>(PS->getStmt()), true,
1301  BRC, BR, N);
1302  if (tag == tags.second)
1303  return VisitTrueTest(cast<Expr>(PS->getStmt()), false,
1304  BRC, BR, N);
1305 
1306  return nullptr;
1307  }
1308 
1309  return nullptr;
1310 }
1311 
1312 std::shared_ptr<PathDiagnosticPiece> ConditionBRVisitor::VisitTerminator(
1313  const Stmt *Term, const ExplodedNode *N, const CFGBlock *srcBlk,
1314  const CFGBlock *dstBlk, BugReport &R, BugReporterContext &BRC) {
1315  const Expr *Cond = nullptr;
1316 
1317  // In the code below, Term is a CFG terminator and Cond is a branch condition
1318  // expression upon which the decision is made on this terminator.
1319  //
1320  // For example, in "if (x == 0)", the "if (x == 0)" statement is a terminator,
1321  // and "x == 0" is the respective condition.
1322  //
1323  // Another example: in "if (x && y)", we've got two terminators and two
1324  // conditions due to short-circuit nature of operator "&&":
1325  // 1. The "if (x && y)" statement is a terminator,
1326  // and "y" is the respective condition.
1327  // 2. Also "x && ..." is another terminator,
1328  // and "x" is its condition.
1329 
1330  switch (Term->getStmtClass()) {
1331  // FIXME: Stmt::SwitchStmtClass is worth handling, however it is a bit
1332  // more tricky because there are more than two branches to account for.
1333  default:
1334  return nullptr;
1335  case Stmt::IfStmtClass:
1336  Cond = cast<IfStmt>(Term)->getCond();
1337  break;
1338  case Stmt::ConditionalOperatorClass:
1339  Cond = cast<ConditionalOperator>(Term)->getCond();
1340  break;
1341  case Stmt::BinaryOperatorClass:
1342  // When we encounter a logical operator (&& or ||) as a CFG terminator,
1343  // then the condition is actually its LHS; otherwise, we'd encounter
1344  // the parent, such as if-statement, as a terminator.
1345  const auto *BO = cast<BinaryOperator>(Term);
1346  assert(BO->isLogicalOp() &&
1347  "CFG terminator is not a short-circuit operator!");
1348  Cond = BO->getLHS();
1349  break;
1350  }
1351 
1352  // However, when we encounter a logical operator as a branch condition,
1353  // then the condition is actually its RHS, because LHS would be
1354  // the condition for the logical operator terminator.
1355  while (const auto *InnerBO = dyn_cast<BinaryOperator>(Cond)) {
1356  if (!InnerBO->isLogicalOp())
1357  break;
1358  Cond = InnerBO->getRHS()->IgnoreParens();
1359  }
1360 
1361  assert(Cond);
1362  assert(srcBlk->succ_size() == 2);
1363  const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk;
1364  return VisitTrueTest(Cond, tookTrue, BRC, R, N);
1365 }
1366 
1367 std::shared_ptr<PathDiagnosticPiece>
1368 ConditionBRVisitor::VisitTrueTest(const Expr *Cond, bool tookTrue,
1369  BugReporterContext &BRC, BugReport &R,
1370  const ExplodedNode *N) {
1371  // These will be modified in code below, but we need to preserve the original
1372  // values in case we want to throw the generic message.
1373  const Expr *CondTmp = Cond;
1374  bool tookTrueTmp = tookTrue;
1375 
1376  while (true) {
1377  CondTmp = CondTmp->IgnoreParenCasts();
1378  switch (CondTmp->getStmtClass()) {
1379  default:
1380  break;
1381  case Stmt::BinaryOperatorClass:
1382  if (auto P = VisitTrueTest(Cond, cast<BinaryOperator>(CondTmp),
1383  tookTrueTmp, BRC, R, N))
1384  return P;
1385  break;
1386  case Stmt::DeclRefExprClass:
1387  if (auto P = VisitTrueTest(Cond, cast<DeclRefExpr>(CondTmp),
1388  tookTrueTmp, BRC, R, N))
1389  return P;
1390  break;
1391  case Stmt::UnaryOperatorClass: {
1392  const UnaryOperator *UO = cast<UnaryOperator>(CondTmp);
1393  if (UO->getOpcode() == UO_LNot) {
1394  tookTrueTmp = !tookTrueTmp;
1395  CondTmp = UO->getSubExpr();
1396  continue;
1397  }
1398  break;
1399  }
1400  }
1401  break;
1402  }
1403 
1404  // Condition too complex to explain? Just say something so that the user
1405  // knew we've made some path decision at this point.
1406  const LocationContext *LCtx = N->getLocationContext();
1407  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
1408  if (!Loc.isValid() || !Loc.asLocation().isValid())
1409  return nullptr;
1410 
1411  return std::make_shared<PathDiagnosticEventPiece>(
1412  Loc, tookTrue ? GenericTrueMessage : GenericFalseMessage);
1413 }
1414 
1416  const Expr *ParentEx,
1417  raw_ostream &Out,
1418  BugReporterContext &BRC,
1419  BugReport &report,
1420  const ExplodedNode *N,
1421  Optional<bool> &prunable) {
1422  const Expr *OriginalExpr = Ex;
1423  Ex = Ex->IgnoreParenCasts();
1424 
1425  // Use heuristics to determine if Ex is a macro expending to a literal and
1426  // if so, use the macro's name.
1427  SourceLocation LocStart = Ex->getLocStart();
1428  SourceLocation LocEnd = Ex->getLocEnd();
1429  if (LocStart.isMacroID() && LocEnd.isMacroID() &&
1430  (isa<GNUNullExpr>(Ex) ||
1431  isa<ObjCBoolLiteralExpr>(Ex) ||
1432  isa<CXXBoolLiteralExpr>(Ex) ||
1433  isa<IntegerLiteral>(Ex) ||
1434  isa<FloatingLiteral>(Ex))) {
1435 
1436  StringRef StartName = Lexer::getImmediateMacroNameForDiagnostics(LocStart,
1437  BRC.getSourceManager(), BRC.getASTContext().getLangOpts());
1438  StringRef EndName = Lexer::getImmediateMacroNameForDiagnostics(LocEnd,
1439  BRC.getSourceManager(), BRC.getASTContext().getLangOpts());
1440  bool beginAndEndAreTheSameMacro = StartName.equals(EndName);
1441 
1442  bool partOfParentMacro = false;
1443  if (ParentEx->getLocStart().isMacroID()) {
1445  ParentEx->getLocStart(), BRC.getSourceManager(),
1446  BRC.getASTContext().getLangOpts());
1447  partOfParentMacro = PName.equals(StartName);
1448  }
1449 
1450  if (beginAndEndAreTheSameMacro && !partOfParentMacro ) {
1451  // Get the location of the macro name as written by the caller.
1452  SourceLocation Loc = LocStart;
1453  while (LocStart.isMacroID()) {
1454  Loc = LocStart;
1455  LocStart = BRC.getSourceManager().getImmediateMacroCallerLoc(LocStart);
1456  }
1457  StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics(
1458  Loc, BRC.getSourceManager(), BRC.getASTContext().getLangOpts());
1459 
1460  // Return the macro name.
1461  Out << MacroName;
1462  return false;
1463  }
1464  }
1465 
1466  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
1467  const bool quotes = isa<VarDecl>(DR->getDecl());
1468  if (quotes) {
1469  Out << '\'';
1470  const LocationContext *LCtx = N->getLocationContext();
1471  const ProgramState *state = N->getState().get();
1472  if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()),
1473  LCtx).getAsRegion()) {
1474  if (report.isInteresting(R))
1475  prunable = false;
1476  else {
1477  const ProgramState *state = N->getState().get();
1478  SVal V = state->getSVal(R);
1479  if (report.isInteresting(V))
1480  prunable = false;
1481  }
1482  }
1483  }
1484  Out << DR->getDecl()->getDeclName().getAsString();
1485  if (quotes)
1486  Out << '\'';
1487  return quotes;
1488  }
1489 
1490  if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) {
1491  QualType OriginalTy = OriginalExpr->getType();
1492  if (OriginalTy->isPointerType()) {
1493  if (IL->getValue() == 0) {
1494  Out << "null";
1495  return false;
1496  }
1497  }
1498  else if (OriginalTy->isObjCObjectPointerType()) {
1499  if (IL->getValue() == 0) {
1500  Out << "nil";
1501  return false;
1502  }
1503  }
1504 
1505  Out << IL->getValue();
1506  return false;
1507  }
1508 
1509  return false;
1510 }
1511 
1512 std::shared_ptr<PathDiagnosticPiece>
1514  const bool tookTrue, BugReporterContext &BRC,
1515  BugReport &R, const ExplodedNode *N) {
1516 
1517  bool shouldInvert = false;
1518  Optional<bool> shouldPrune;
1519 
1520  SmallString<128> LhsString, RhsString;
1521  {
1522  llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
1523  const bool isVarLHS = patternMatch(BExpr->getLHS(), BExpr, OutLHS,
1524  BRC, R, N, shouldPrune);
1525  const bool isVarRHS = patternMatch(BExpr->getRHS(), BExpr, OutRHS,
1526  BRC, R, N, shouldPrune);
1527 
1528  shouldInvert = !isVarLHS && isVarRHS;
1529  }
1530 
1531  BinaryOperator::Opcode Op = BExpr->getOpcode();
1532 
1534  // For assignment operators, all that we care about is that the LHS
1535  // evaluates to "true" or "false".
1536  return VisitConditionVariable(LhsString, BExpr->getLHS(), tookTrue,
1537  BRC, R, N);
1538  }
1539 
1540  // For non-assignment operations, we require that we can understand
1541  // both the LHS and RHS.
1542  if (LhsString.empty() || RhsString.empty() ||
1543  !BinaryOperator::isComparisonOp(Op) || Op == BO_Cmp)
1544  return nullptr;
1545 
1546  // Should we invert the strings if the LHS is not a variable name?
1547  SmallString<256> buf;
1548  llvm::raw_svector_ostream Out(buf);
1549  Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is ";
1550 
1551  // Do we need to invert the opcode?
1552  if (shouldInvert)
1553  switch (Op) {
1554  default: break;
1555  case BO_LT: Op = BO_GT; break;
1556  case BO_GT: Op = BO_LT; break;
1557  case BO_LE: Op = BO_GE; break;
1558  case BO_GE: Op = BO_LE; break;
1559  }
1560 
1561  if (!tookTrue)
1562  switch (Op) {
1563  case BO_EQ: Op = BO_NE; break;
1564  case BO_NE: Op = BO_EQ; break;
1565  case BO_LT: Op = BO_GE; break;
1566  case BO_GT: Op = BO_LE; break;
1567  case BO_LE: Op = BO_GT; break;
1568  case BO_GE: Op = BO_LT; break;
1569  default:
1570  return nullptr;
1571  }
1572 
1573  switch (Op) {
1574  case BO_EQ:
1575  Out << "equal to ";
1576  break;
1577  case BO_NE:
1578  Out << "not equal to ";
1579  break;
1580  default:
1581  Out << BinaryOperator::getOpcodeStr(Op) << ' ';
1582  break;
1583  }
1584 
1585  Out << (shouldInvert ? LhsString : RhsString);
1586  const LocationContext *LCtx = N->getLocationContext();
1587  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
1588  auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
1589  if (shouldPrune.hasValue())
1590  event->setPrunable(shouldPrune.getValue());
1591  return event;
1592 }
1593 
1594 std::shared_ptr<PathDiagnosticPiece> ConditionBRVisitor::VisitConditionVariable(
1595  StringRef LhsString, const Expr *CondVarExpr, const bool tookTrue,
1596  BugReporterContext &BRC, BugReport &report, const ExplodedNode *N) {
1597  // FIXME: If there's already a constraint tracker for this variable,
1598  // we shouldn't emit anything here (c.f. the double note in
1599  // test/Analysis/inlining/path-notes.c)
1600  SmallString<256> buf;
1601  llvm::raw_svector_ostream Out(buf);
1602  Out << "Assuming " << LhsString << " is ";
1603 
1604  QualType Ty = CondVarExpr->getType();
1605 
1606  if (Ty->isPointerType())
1607  Out << (tookTrue ? "not null" : "null");
1608  else if (Ty->isObjCObjectPointerType())
1609  Out << (tookTrue ? "not nil" : "nil");
1610  else if (Ty->isBooleanType())
1611  Out << (tookTrue ? "true" : "false");
1612  else if (Ty->isIntegralOrEnumerationType())
1613  Out << (tookTrue ? "non-zero" : "zero");
1614  else
1615  return nullptr;
1616 
1617  const LocationContext *LCtx = N->getLocationContext();
1618  PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
1619  auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
1620 
1621  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) {
1622  if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
1623  const ProgramState *state = N->getState().get();
1624  if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
1625  if (report.isInteresting(R))
1626  event->setPrunable(false);
1627  }
1628  }
1629  }
1630 
1631  return event;
1632 }
1633 
1634 std::shared_ptr<PathDiagnosticPiece>
1636  const bool tookTrue, BugReporterContext &BRC,
1637  BugReport &report, const ExplodedNode *N) {
1638 
1639  const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
1640  if (!VD)
1641  return nullptr;
1642 
1643  SmallString<256> Buf;
1644  llvm::raw_svector_ostream Out(Buf);
1645 
1646  Out << "Assuming '" << VD->getDeclName() << "' is ";
1647 
1648  QualType VDTy = VD->getType();
1649 
1650  if (VDTy->isPointerType())
1651  Out << (tookTrue ? "non-null" : "null");
1652  else if (VDTy->isObjCObjectPointerType())
1653  Out << (tookTrue ? "non-nil" : "nil");
1654  else if (VDTy->isScalarType())
1655  Out << (tookTrue ? "not equal to 0" : "0");
1656  else
1657  return nullptr;
1658 
1659  const LocationContext *LCtx = N->getLocationContext();
1660  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
1661  auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
1662 
1663  const ProgramState *state = N->getState().get();
1664  if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
1665  if (report.isInteresting(R))
1666  event->setPrunable(false);
1667  else {
1668  SVal V = state->getSVal(R);
1669  if (report.isInteresting(V))
1670  event->setPrunable(false);
1671  }
1672  }
1673  return std::move(event);
1674 }
1675 
1676 const char *const ConditionBRVisitor::GenericTrueMessage =
1677  "Assuming the condition is true";
1678 const char *const ConditionBRVisitor::GenericFalseMessage =
1679  "Assuming the condition is false";
1680 
1682  const PathDiagnosticPiece *Piece) {
1683  return Piece->getString() == GenericTrueMessage ||
1684  Piece->getString() == GenericFalseMessage;
1685 }
1686 
1687 std::unique_ptr<PathDiagnosticPiece>
1689  const ExplodedNode *N,
1690  BugReport &BR) {
1691  // Here we suppress false positives coming from system headers. This list is
1692  // based on known issues.
1693  ExprEngine &Eng = BRC.getBugReporter().getEngine();
1694  AnalyzerOptions &Options = Eng.getAnalysisManager().options;
1695  const Decl *D = N->getLocationContext()->getDecl();
1696 
1698  // Skip reports within the 'std' namespace. Although these can sometimes be
1699  // the user's fault, we currently don't report them very well, and
1700  // Note that this will not help for any other data structure libraries, like
1701  // TR1, Boost, or llvm/ADT.
1702  if (Options.shouldSuppressFromCXXStandardLibrary()) {
1703  BR.markInvalid(getTag(), nullptr);
1704  return nullptr;
1705 
1706  } else {
1707  // If the complete 'std' suppression is not enabled, suppress reports
1708  // from the 'std' namespace that are known to produce false positives.
1709 
1710  // The analyzer issues a false use-after-free when std::list::pop_front
1711  // or std::list::pop_back are called multiple times because we cannot
1712  // reason about the internal invariants of the data structure.
1713  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
1714  const CXXRecordDecl *CD = MD->getParent();
1715  if (CD->getName() == "list") {
1716  BR.markInvalid(getTag(), nullptr);
1717  return nullptr;
1718  }
1719  }
1720 
1721  // The analyzer issues a false positive when the constructor of
1722  // std::__independent_bits_engine from algorithms is used.
1723  if (const CXXConstructorDecl *MD = dyn_cast<CXXConstructorDecl>(D)) {
1724  const CXXRecordDecl *CD = MD->getParent();
1725  if (CD->getName() == "__independent_bits_engine") {
1726  BR.markInvalid(getTag(), nullptr);
1727  return nullptr;
1728  }
1729  }
1730 
1731  for (const LocationContext *LCtx = N->getLocationContext(); LCtx;
1732  LCtx = LCtx->getParent()) {
1733  const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
1734  if (!MD)
1735  continue;
1736 
1737  const CXXRecordDecl *CD = MD->getParent();
1738  // The analyzer issues a false positive on
1739  // std::basic_string<uint8_t> v; v.push_back(1);
1740  // and
1741  // std::u16string s; s += u'a';
1742  // because we cannot reason about the internal invariants of the
1743  // data structure.
1744  if (CD->getName() == "basic_string") {
1745  BR.markInvalid(getTag(), nullptr);
1746  return nullptr;
1747  }
1748 
1749  // The analyzer issues a false positive on
1750  // std::shared_ptr<int> p(new int(1)); p = nullptr;
1751  // because it does not reason properly about temporary destructors.
1752  if (CD->getName() == "shared_ptr") {
1753  BR.markInvalid(getTag(), nullptr);
1754  return nullptr;
1755  }
1756  }
1757  }
1758  }
1759 
1760  // Skip reports within the sys/queue.h macros as we do not have the ability to
1761  // reason about data structure shapes.
1764  while (Loc.isMacroID()) {
1765  Loc = Loc.getSpellingLoc();
1766  if (SM.getFilename(Loc).endswith("sys/queue.h")) {
1767  BR.markInvalid(getTag(), nullptr);
1768  return nullptr;
1769  }
1770  }
1771 
1772  return nullptr;
1773 }
1774 
1775 std::shared_ptr<PathDiagnosticPiece>
1777  const ExplodedNode *PrevN,
1778  BugReporterContext &BRC, BugReport &BR) {
1779 
1781  ProgramPoint ProgLoc = N->getLocation();
1782 
1783  // We are only interested in visiting CallEnter nodes.
1784  Optional<CallEnter> CEnter = ProgLoc.getAs<CallEnter>();
1785  if (!CEnter)
1786  return nullptr;
1787 
1788  // Check if one of the arguments is the region the visitor is tracking.
1790  CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State);
1791  unsigned Idx = 0;
1792  ArrayRef<ParmVarDecl*> parms = Call->parameters();
1793 
1794  for (ArrayRef<ParmVarDecl*>::iterator I = parms.begin(), E = parms.end();
1795  I != E; ++I, ++Idx) {
1796  const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion();
1797 
1798  // Are we tracking the argument or its subregion?
1799  if ( !ArgReg || (ArgReg != R && !R->isSubRegionOf(ArgReg->StripCasts())))
1800  continue;
1801 
1802  // Check the function parameter type.
1803  const ParmVarDecl *ParamDecl = *I;
1804  assert(ParamDecl && "Formal parameter has no decl?");
1805  QualType T = ParamDecl->getType();
1806 
1807  if (!(T->isAnyPointerType() || T->isReferenceType())) {
1808  // Function can only change the value passed in by address.
1809  continue;
1810  }
1811 
1812  // If it is a const pointer value, the function does not intend to
1813  // change the value.
1814  if (T->getPointeeType().isConstQualified())
1815  continue;
1816 
1817  // Mark the call site (LocationContext) as interesting if the value of the
1818  // argument is undefined or '0'/'NULL'.
1819  SVal BoundVal = State->getSVal(R);
1820  if (BoundVal.isUndef() || BoundVal.isZeroConstant()) {
1821  BR.markInteresting(CEnter->getCalleeContext());
1822  return nullptr;
1823  }
1824  }
1825  return nullptr;
1826 }
1827 
1828 std::shared_ptr<PathDiagnosticPiece>
1830  const ExplodedNode *Pred,
1831  BugReporterContext &BRC, BugReport &BR) {
1832  if (Satisfied)
1833  return nullptr;
1834 
1835  auto Edge = Succ->getLocation().getAs<BlockEdge>();
1836  if (!Edge.hasValue())
1837  return nullptr;
1838 
1839  auto Tag = Edge->getTag();
1840  if (!Tag)
1841  return nullptr;
1842 
1843  if (Tag->getTagDescription() != "cplusplus.SelfAssignment")
1844  return nullptr;
1845 
1846  Satisfied = true;
1847 
1848  const auto *Met =
1849  dyn_cast<CXXMethodDecl>(Succ->getCodeDecl().getAsFunction());
1850  assert(Met && "Not a C++ method.");
1851  assert((Met->isCopyAssignmentOperator() || Met->isMoveAssignmentOperator()) &&
1852  "Not a copy/move assignment operator.");
1853 
1854  const auto *LCtx = Edge->getLocationContext();
1855 
1856  const auto &State = Succ->getState();
1857  auto &SVB = State->getStateManager().getSValBuilder();
1858 
1859  const auto Param =
1860  State->getSVal(State->getRegion(Met->getParamDecl(0), LCtx));
1861  const auto This =
1862  State->getSVal(SVB.getCXXThis(Met, LCtx->getCurrentStackFrame()));
1863 
1864  auto L = PathDiagnosticLocation::create(Met, BRC.getSourceManager());
1865 
1866  if (!L.isValid() || !L.asLocation().isValid())
1867  return nullptr;
1868 
1869  SmallString<256> Buf;
1870  llvm::raw_svector_ostream Out(Buf);
1871 
1872  Out << "Assuming " << Met->getParamDecl(0)->getName() <<
1873  ((Param == This) ? " == " : " != ") << "*this";
1874 
1875  auto Piece = std::make_shared<PathDiagnosticEventPiece>(L, Out.str());
1876  Piece->addRange(Met->getSourceRange());
1877 
1878  return std::move(Piece);
1879 }
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:928
bool isReferenceType() const
Definition: Type.h:5954
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:6219
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:6204
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:1335
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
Definition: Stmt.h:1417
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:5777
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:5946
bool isObjCObjectPointerType() const
Definition: Type.h:6039
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:6232
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:13020
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:5942
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.