clang  13.0.0git
BugReporterVisitors.cpp
Go to the documentation of this file.
1 //===- BugReporterVisitors.cpp - Helpers for reporting bugs ---------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines a set of BugReporter "visitors" which can be used to
10 // enhance the diagnostics reported for a bug.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/Decl.h"
17 #include "clang/AST/DeclBase.h"
18 #include "clang/AST/DeclCXX.h"
19 #include "clang/AST/Expr.h"
20 #include "clang/AST/ExprCXX.h"
21 #include "clang/AST/ExprObjC.h"
22 #include "clang/AST/Stmt.h"
23 #include "clang/AST/Type.h"
27 #include "clang/Analysis/CFG.h"
32 #include "clang/Basic/LLVM.h"
35 #include "clang/Lex/Lexer.h"
48 #include "llvm/ADT/ArrayRef.h"
49 #include "llvm/ADT/None.h"
50 #include "llvm/ADT/Optional.h"
51 #include "llvm/ADT/STLExtras.h"
52 #include "llvm/ADT/SmallPtrSet.h"
53 #include "llvm/ADT/SmallString.h"
54 #include "llvm/ADT/SmallVector.h"
55 #include "llvm/ADT/StringExtras.h"
56 #include "llvm/ADT/StringRef.h"
57 #include "llvm/Support/Casting.h"
58 #include "llvm/Support/ErrorHandling.h"
59 #include "llvm/Support/raw_ostream.h"
60 #include <cassert>
61 #include <deque>
62 #include <memory>
63 #include <string>
64 #include <utility>
65 
66 using namespace clang;
67 using namespace ento;
68 
69 //===----------------------------------------------------------------------===//
70 // Utility functions.
71 //===----------------------------------------------------------------------===//
72 
73 static const Expr *peelOffPointerArithmetic(const BinaryOperator *B) {
74  if (B->isAdditiveOp() && B->getType()->isPointerType()) {
75  if (B->getLHS()->getType()->isPointerType()) {
76  return B->getLHS();
77  } else if (B->getRHS()->getType()->isPointerType()) {
78  return B->getRHS();
79  }
80  }
81  return nullptr;
82 }
83 
84 /// Given that expression S represents a pointer that would be dereferenced,
85 /// try to find a sub-expression from which the pointer came from.
86 /// This is used for tracking down origins of a null or undefined value:
87 /// "this is null because that is null because that is null" etc.
88 /// We wipe away field and element offsets because they merely add offsets.
89 /// We also wipe away all casts except lvalue-to-rvalue casts, because the
90 /// latter represent an actual pointer dereference; however, we remove
91 /// the final lvalue-to-rvalue cast before returning from this function
92 /// because it demonstrates more clearly from where the pointer rvalue was
93 /// loaded. Examples:
94 /// x->y.z ==> x (lvalue)
95 /// foo()->y.z ==> foo() (rvalue)
96 const Expr *bugreporter::getDerefExpr(const Stmt *S) {
97  const auto *E = dyn_cast<Expr>(S);
98  if (!E)
99  return nullptr;
100 
101  while (true) {
102  if (const auto *CE = dyn_cast<CastExpr>(E)) {
103  if (CE->getCastKind() == CK_LValueToRValue) {
104  // This cast represents the load we're looking for.
105  break;
106  }
107  E = CE->getSubExpr();
108  } else if (const auto *B = dyn_cast<BinaryOperator>(E)) {
109  // Pointer arithmetic: '*(x + 2)' -> 'x') etc.
110  if (const Expr *Inner = peelOffPointerArithmetic(B)) {
111  E = Inner;
112  } else {
113  // Probably more arithmetic can be pattern-matched here,
114  // but for now give up.
115  break;
116  }
117  } else if (const auto *U = dyn_cast<UnaryOperator>(E)) {
118  if (U->getOpcode() == UO_Deref || U->getOpcode() == UO_AddrOf ||
119  (U->isIncrementDecrementOp() && U->getType()->isPointerType())) {
120  // Operators '*' and '&' don't actually mean anything.
121  // We look at casts instead.
122  E = U->getSubExpr();
123  } else {
124  // Probably more arithmetic can be pattern-matched here,
125  // but for now give up.
126  break;
127  }
128  }
129  // Pattern match for a few useful cases: a[0], p->f, *p etc.
130  else if (const auto *ME = dyn_cast<MemberExpr>(E)) {
131  E = ME->getBase();
132  } else if (const auto *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) {
133  E = IvarRef->getBase();
134  } else if (const auto *AE = dyn_cast<ArraySubscriptExpr>(E)) {
135  E = AE->getBase();
136  } else if (const auto *PE = dyn_cast<ParenExpr>(E)) {
137  E = PE->getSubExpr();
138  } else if (const auto *FE = dyn_cast<FullExpr>(E)) {
139  E = FE->getSubExpr();
140  } else {
141  // Other arbitrary stuff.
142  break;
143  }
144  }
145 
146  // Special case: remove the final lvalue-to-rvalue cast, but do not recurse
147  // deeper into the sub-expression. This way we return the lvalue from which
148  // our pointer rvalue was loaded.
149  if (const auto *CE = dyn_cast<ImplicitCastExpr>(E))
150  if (CE->getCastKind() == CK_LValueToRValue)
151  E = CE->getSubExpr();
152 
153  return E;
154 }
155 
156 /// Comparing internal representations of symbolic values (via
157 /// SVal::operator==()) is a valid way to check if the value was updated,
158 /// unless it's a LazyCompoundVal that may have a different internal
159 /// representation every time it is loaded from the state. In this function we
160 /// do an approximate comparison for lazy compound values, checking that they
161 /// are the immediate snapshots of the tracked region's bindings within the
162 /// node's respective states but not really checking that these snapshots
163 /// actually contain the same set of bindings.
164 static bool hasVisibleUpdate(const ExplodedNode *LeftNode, SVal LeftVal,
165  const ExplodedNode *RightNode, SVal RightVal) {
166  if (LeftVal == RightVal)
167  return true;
168 
169  const auto LLCV = LeftVal.getAs<nonloc::LazyCompoundVal>();
170  if (!LLCV)
171  return false;
172 
173  const auto RLCV = RightVal.getAs<nonloc::LazyCompoundVal>();
174  if (!RLCV)
175  return false;
176 
177  return LLCV->getRegion() == RLCV->getRegion() &&
178  LLCV->getStore() == LeftNode->getState()->getStore() &&
179  RLCV->getStore() == RightNode->getState()->getStore();
180 }
181 
182 static Optional<SVal> getSValForVar(const Expr *CondVarExpr,
183  const ExplodedNode *N) {
184  ProgramStateRef State = N->getState();
185  const LocationContext *LCtx = N->getLocationContext();
186 
187  assert(CondVarExpr);
188  CondVarExpr = CondVarExpr->IgnoreImpCasts();
189 
190  // The declaration of the value may rely on a pointer so take its l-value.
191  // FIXME: As seen in VisitCommonDeclRefExpr, sometimes DeclRefExpr may
192  // evaluate to a FieldRegion when it refers to a declaration of a lambda
193  // capture variable. We most likely need to duplicate that logic here.
194  if (const auto *DRE = dyn_cast<DeclRefExpr>(CondVarExpr))
195  if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
196  return State->getSVal(State->getLValue(VD, LCtx));
197 
198  if (const auto *ME = dyn_cast<MemberExpr>(CondVarExpr))
199  if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
200  if (auto FieldL = State->getSVal(ME, LCtx).getAs<Loc>())
201  return State->getRawSVal(*FieldL, FD->getType());
202 
203  return None;
204 }
205 
207 getConcreteIntegerValue(const Expr *CondVarExpr, const ExplodedNode *N) {
208 
209  if (Optional<SVal> V = getSValForVar(CondVarExpr, N))
210  if (auto CI = V->getAs<nonloc::ConcreteInt>())
211  return &CI->getValue();
212  return None;
213 }
214 
215 static bool isVarAnInterestingCondition(const Expr *CondVarExpr,
216  const ExplodedNode *N,
217  const PathSensitiveBugReport *B) {
218  // Even if this condition is marked as interesting, it isn't *that*
219  // interesting if it didn't happen in a nested stackframe, the user could just
220  // follow the arrows.
221  if (!B->getErrorNode()->getStackFrame()->isParentOf(N->getStackFrame()))
222  return false;
223 
224  if (Optional<SVal> V = getSValForVar(CondVarExpr, N))
225  if (Optional<bugreporter::TrackingKind> K = B->getInterestingnessKind(*V))
227 
228  return false;
229 }
230 
231 static bool isInterestingExpr(const Expr *E, const ExplodedNode *N,
232  const PathSensitiveBugReport *B) {
233  if (Optional<SVal> V = getSValForVar(E, N))
234  return B->getInterestingnessKind(*V).hasValue();
235  return false;
236 }
237 
238 /// \return name of the macro inside the location \p Loc.
239 static StringRef getMacroName(SourceLocation Loc,
240  BugReporterContext &BRC) {
242  Loc,
243  BRC.getSourceManager(),
244  BRC.getASTContext().getLangOpts());
245 }
246 
247 /// \return Whether given spelling location corresponds to an expansion
248 /// of a function-like macro.
250  const SourceManager &SM) {
251  if (!Loc.isMacroID())
252  return false;
253  while (SM.isMacroArgExpansion(Loc))
254  Loc = SM.getImmediateExpansionRange(Loc).getBegin();
255  std::pair<FileID, unsigned> TLInfo = SM.getDecomposedLoc(Loc);
256  SrcMgr::SLocEntry SE = SM.getSLocEntry(TLInfo.first);
257  const SrcMgr::ExpansionInfo &EInfo = SE.getExpansion();
258  return EInfo.isFunctionMacroExpansion();
259 }
260 
261 /// \return Whether \c RegionOfInterest was modified at \p N,
262 /// where \p ValueAfter is \c RegionOfInterest's value at the end of the
263 /// stack frame.
264 static bool wasRegionOfInterestModifiedAt(const SubRegion *RegionOfInterest,
265  const ExplodedNode *N,
266  SVal ValueAfter) {
267  ProgramStateRef State = N->getState();
268  ProgramStateManager &Mgr = N->getState()->getStateManager();
269 
270  if (!N->getLocationAs<PostStore>() && !N->getLocationAs<PostInitializer>() &&
271  !N->getLocationAs<PostStmt>())
272  return false;
273 
274  // Writing into region of interest.
275  if (auto PS = N->getLocationAs<PostStmt>())
276  if (auto *BO = PS->getStmtAs<BinaryOperator>())
277  if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(
278  N->getSVal(BO->getLHS()).getAsRegion()))
279  return true;
280 
281  // SVal after the state is possibly different.
282  SVal ValueAtN = N->getState()->getSVal(RegionOfInterest);
283  if (!Mgr.getSValBuilder()
284  .areEqual(State, ValueAtN, ValueAfter)
285  .isConstrainedTrue() &&
286  (!ValueAtN.isUndef() || !ValueAfter.isUndef()))
287  return true;
288 
289  return false;
290 }
291 
292 //===----------------------------------------------------------------------===//
293 // Implementation of BugReporterVisitor.
294 //===----------------------------------------------------------------------===//
295 
297  const ExplodedNode *,
299  return nullptr;
300 }
301 
303  const ExplodedNode *,
305 
308  const ExplodedNode *EndPathNode,
309  const PathSensitiveBugReport &BR) {
311  const auto &Ranges = BR.getRanges();
312 
313  // Only add the statement itself as a range if we didn't specify any
314  // special ranges for this report.
315  auto P = std::make_shared<PathDiagnosticEventPiece>(
316  L, BR.getDescription(), Ranges.begin() == Ranges.end());
317  for (SourceRange Range : Ranges)
318  P->addRange(Range);
319 
320  return P;
321 }
322 
323 //===----------------------------------------------------------------------===//
324 // Implementation of NoStoreFuncVisitor.
325 //===----------------------------------------------------------------------===//
326 
327 namespace {
328 
329 /// Put a diagnostic on return statement of all inlined functions
330 /// for which the region of interest \p RegionOfInterest was passed into,
331 /// but not written inside, and it has caused an undefined read or a null
332 /// pointer dereference outside.
333 class NoStoreFuncVisitor final : public BugReporterVisitor {
334  const SubRegion *RegionOfInterest;
335  MemRegionManager &MmrMgr;
336  const SourceManager &SM;
337  const PrintingPolicy &PP;
339 
340  /// Recursion limit for dereferencing fields when looking for the
341  /// region of interest.
342  /// The limit of two indicates that we will dereference fields only once.
343  static const unsigned DEREFERENCE_LIMIT = 2;
344 
345  /// Frames writing into \c RegionOfInterest.
346  /// This visitor generates a note only if a function does not write into
347  /// a region of interest. This information is not immediately available
348  /// by looking at the node associated with the exit from the function
349  /// (usually the return statement). To avoid recomputing the same information
350  /// many times (going up the path for each node and checking whether the
351  /// region was written into) we instead lazily compute the
352  /// stack frames along the path which write into the region of interest.
354  llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingCalculated;
355 
356  using RegionVector = SmallVector<const MemRegion *, 5>;
357 
358 public:
359  NoStoreFuncVisitor(const SubRegion *R, bugreporter::TrackingKind TKind)
360  : RegionOfInterest(R), MmrMgr(R->getMemRegionManager()),
361  SM(MmrMgr.getContext().getSourceManager()),
362  PP(MmrMgr.getContext().getPrintingPolicy()), TKind(TKind) {}
363 
364  void Profile(llvm::FoldingSetNodeID &ID) const override {
365  static int Tag = 0;
366  ID.AddPointer(&Tag);
367  ID.AddPointer(RegionOfInterest);
368  }
369 
370  void *getTag() const {
371  static int Tag = 0;
372  return static_cast<void *>(&Tag);
373  }
374 
375  PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
376  BugReporterContext &BR,
377  PathSensitiveBugReport &R) override;
378 
379 private:
380  /// Attempts to find the region of interest in a given record decl,
381  /// by either following the base classes or fields.
382  /// Dereferences fields up to a given recursion limit.
383  /// Note that \p Vec is passed by value, leading to quadratic copying cost,
384  /// but it's OK in practice since its length is limited to DEREFERENCE_LIMIT.
385  /// \return A chain fields leading to the region of interest or None.
387  findRegionOfInterestInRecord(const RecordDecl *RD, ProgramStateRef State,
388  const MemRegion *R, const RegionVector &Vec = {},
389  int depth = 0);
390 
391  /// Check and lazily calculate whether the region of interest is
392  /// modified in the stack frame to which \p N belongs.
393  /// The calculation is cached in FramesModifyingRegion.
394  bool isRegionOfInterestModifiedInFrame(const ExplodedNode *N) {
395  const LocationContext *Ctx = N->getLocationContext();
396  const StackFrameContext *SCtx = Ctx->getStackFrame();
397  if (!FramesModifyingCalculated.count(SCtx))
398  findModifyingFrames(N);
399  return FramesModifyingRegion.count(SCtx);
400  }
401 
402  /// Write to \c FramesModifyingRegion all stack frames along
403  /// the path in the current stack frame which modify \c RegionOfInterest.
404  void findModifyingFrames(const ExplodedNode *N);
405 
406  /// Consume the information on the no-store stack frame in order to
407  /// either emit a note or suppress the report enirely.
408  /// \return Diagnostics piece for region not modified in the current function,
409  /// if it decides to emit one.
411  maybeEmitNote(PathSensitiveBugReport &R, const CallEvent &Call,
412  const ExplodedNode *N, const RegionVector &FieldChain,
413  const MemRegion *MatchedRegion, StringRef FirstElement,
414  bool FirstIsReferenceType, unsigned IndirectionLevel);
415 
416  /// Pretty-print region \p MatchedRegion to \p os.
417  /// \return Whether printing succeeded.
418  bool prettyPrintRegionName(StringRef FirstElement, bool FirstIsReferenceType,
419  const MemRegion *MatchedRegion,
420  const RegionVector &FieldChain,
421  int IndirectionLevel,
422  llvm::raw_svector_ostream &os);
423 
424  /// Print first item in the chain, return new separator.
425  static StringRef prettyPrintFirstElement(StringRef FirstElement,
426  bool MoreItemsExpected,
427  int IndirectionLevel,
428  llvm::raw_svector_ostream &os);
429 };
430 
431 } // end of anonymous namespace
432 
433 /// \return Whether the method declaration \p Parent
434 /// syntactically has a binary operation writing into the ivar \p Ivar.
436  const ObjCIvarDecl *Ivar) {
437  using namespace ast_matchers;
438  const char *IvarBind = "Ivar";
439  if (!Parent || !Parent->hasBody())
440  return false;
441  StatementMatcher WriteIntoIvarM = binaryOperator(
442  hasOperatorName("="),
443  hasLHS(ignoringParenImpCasts(
444  objcIvarRefExpr(hasDeclaration(equalsNode(Ivar))).bind(IvarBind))));
445  StatementMatcher ParentM = stmt(hasDescendant(WriteIntoIvarM));
446  auto Matches = match(ParentM, *Parent->getBody(), Parent->getASTContext());
447  for (BoundNodes &Match : Matches) {
448  auto IvarRef = Match.getNodeAs<ObjCIvarRefExpr>(IvarBind);
449  if (IvarRef->isFreeIvar())
450  return true;
451 
452  const Expr *Base = IvarRef->getBase();
453  if (const auto *ICE = dyn_cast<ImplicitCastExpr>(Base))
454  Base = ICE->getSubExpr();
455 
456  if (const auto *DRE = dyn_cast<DeclRefExpr>(Base))
457  if (const auto *ID = dyn_cast<ImplicitParamDecl>(DRE->getDecl()))
458  if (ID->getParameterKind() == ImplicitParamDecl::ObjCSelf)
459  return true;
460 
461  return false;
462  }
463  return false;
464 }
465 
466 /// Get parameters associated with runtime definition in order
467 /// to get the correct parameter name.
468 static ArrayRef<ParmVarDecl *> getCallParameters(CallEventRef<> Call) {
469  // Use runtime definition, if available.
470  RuntimeDefinition RD = Call->getRuntimeDefinition();
471  if (const auto *FD = dyn_cast_or_null<FunctionDecl>(RD.getDecl()))
472  return FD->parameters();
473  if (const auto *MD = dyn_cast_or_null<ObjCMethodDecl>(RD.getDecl()))
474  return MD->parameters();
475 
476  return Call->parameters();
477 }
478 
479 /// \return whether \p Ty points to a const type, or is a const reference.
480 static bool isPointerToConst(QualType Ty) {
481  return !Ty->getPointeeType().isNull() &&
483 }
484 
485 /// Attempts to find the region of interest in a given CXX decl,
486 /// by either following the base classes or fields.
487 /// Dereferences fields up to a given recursion limit.
488 /// Note that \p Vec is passed by value, leading to quadratic copying cost,
489 /// but it's OK in practice since its length is limited to DEREFERENCE_LIMIT.
490 /// \return A chain fields leading to the region of interest or None.
492 NoStoreFuncVisitor::findRegionOfInterestInRecord(
493  const RecordDecl *RD, ProgramStateRef State, const MemRegion *R,
494  const NoStoreFuncVisitor::RegionVector &Vec /* = {} */,
495  int depth /* = 0 */) {
496 
497  if (depth == DEREFERENCE_LIMIT) // Limit the recursion depth.
498  return None;
499 
500  if (const auto *RDX = dyn_cast<CXXRecordDecl>(RD))
501  if (!RDX->hasDefinition())
502  return None;
503 
504  // Recursively examine the base classes.
505  // Note that following base classes does not increase the recursion depth.
506  if (const auto *RDX = dyn_cast<CXXRecordDecl>(RD))
507  for (const auto &II : RDX->bases())
508  if (const RecordDecl *RRD = II.getType()->getAsRecordDecl())
509  if (Optional<RegionVector> Out =
510  findRegionOfInterestInRecord(RRD, State, R, Vec, depth))
511  return Out;
512 
513  for (const FieldDecl *I : RD->fields()) {
514  QualType FT = I->getType();
515  const FieldRegion *FR = MmrMgr.getFieldRegion(I, cast<SubRegion>(R));
516  const SVal V = State->getSVal(FR);
517  const MemRegion *VR = V.getAsRegion();
518 
519  RegionVector VecF = Vec;
520  VecF.push_back(FR);
521 
522  if (RegionOfInterest == VR)
523  return VecF;
524 
525  if (const RecordDecl *RRD = FT->getAsRecordDecl())
526  if (auto Out =
527  findRegionOfInterestInRecord(RRD, State, FR, VecF, depth + 1))
528  return Out;
529 
530  QualType PT = FT->getPointeeType();
531  if (PT.isNull() || PT->isVoidType() || !VR)
532  continue;
533 
534  if (const RecordDecl *RRD = PT->getAsRecordDecl())
535  if (Optional<RegionVector> Out =
536  findRegionOfInterestInRecord(RRD, State, VR, VecF, depth + 1))
537  return Out;
538  }
539 
540  return None;
541 }
542 
544 NoStoreFuncVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BR,
545  PathSensitiveBugReport &R) {
546 
547  const LocationContext *Ctx = N->getLocationContext();
548  const StackFrameContext *SCtx = Ctx->getStackFrame();
549  ProgramStateRef State = N->getState();
550  auto CallExitLoc = N->getLocationAs<CallExitBegin>();
551 
552  // No diagnostic if region was modified inside the frame.
553  if (!CallExitLoc || isRegionOfInterestModifiedInFrame(N))
554  return nullptr;
555 
556  CallEventRef<> Call =
557  BR.getStateManager().getCallEventManager().getCaller(SCtx, State);
558 
559  // Region of interest corresponds to an IVar, exiting a method
560  // which could have written into that IVar, but did not.
561  if (const auto *MC = dyn_cast<ObjCMethodCall>(Call)) {
562  if (const auto *IvarR = dyn_cast<ObjCIvarRegion>(RegionOfInterest)) {
563  const MemRegion *SelfRegion = MC->getReceiverSVal().getAsRegion();
564  if (RegionOfInterest->isSubRegionOf(SelfRegion) &&
565  potentiallyWritesIntoIvar(Call->getRuntimeDefinition().getDecl(),
566  IvarR->getDecl()))
567  return maybeEmitNote(R, *Call, N, {}, SelfRegion, "self",
568  /*FirstIsReferenceType=*/false, 1);
569  }
570  }
571 
572  if (const auto *CCall = dyn_cast<CXXConstructorCall>(Call)) {
573  const MemRegion *ThisR = CCall->getCXXThisVal().getAsRegion();
574  if (RegionOfInterest->isSubRegionOf(ThisR) &&
575  !CCall->getDecl()->isImplicit())
576  return maybeEmitNote(R, *Call, N, {}, ThisR, "this",
577  /*FirstIsReferenceType=*/false, 1);
578 
579  // Do not generate diagnostics for not modified parameters in
580  // constructors.
581  return nullptr;
582  }
583 
584  ArrayRef<ParmVarDecl *> parameters = getCallParameters(Call);
585  for (unsigned I = 0; I < Call->getNumArgs() && I < parameters.size(); ++I) {
586  const ParmVarDecl *PVD = parameters[I];
587  SVal V = Call->getArgSVal(I);
588  bool ParamIsReferenceType = PVD->getType()->isReferenceType();
589  std::string ParamName = PVD->getNameAsString();
590 
591  int IndirectionLevel = 1;
592  QualType T = PVD->getType();
593  while (const MemRegion *MR = V.getAsRegion()) {
594  if (RegionOfInterest->isSubRegionOf(MR) && !isPointerToConst(T))
595  return maybeEmitNote(R, *Call, N, {}, MR, ParamName,
596  ParamIsReferenceType, IndirectionLevel);
597 
598  QualType PT = T->getPointeeType();
599  if (PT.isNull() || PT->isVoidType())
600  break;
601 
602  if (const RecordDecl *RD = PT->getAsRecordDecl())
604  findRegionOfInterestInRecord(RD, State, MR))
605  return maybeEmitNote(R, *Call, N, *P, RegionOfInterest, ParamName,
606  ParamIsReferenceType, IndirectionLevel);
607 
608  V = State->getSVal(MR, PT);
609  T = PT;
610  IndirectionLevel++;
611  }
612  }
613 
614  return nullptr;
615 }
616 
617 void NoStoreFuncVisitor::findModifyingFrames(const ExplodedNode *N) {
618  assert(N->getLocationAs<CallExitBegin>());
619  ProgramStateRef LastReturnState = N->getState();
620  SVal ValueAtReturn = LastReturnState->getSVal(RegionOfInterest);
621  const LocationContext *Ctx = N->getLocationContext();
622  const StackFrameContext *OriginalSCtx = Ctx->getStackFrame();
623 
624  do {
625  ProgramStateRef State = N->getState();
626  auto CallExitLoc = N->getLocationAs<CallExitBegin>();
627  if (CallExitLoc) {
628  LastReturnState = State;
629  ValueAtReturn = LastReturnState->getSVal(RegionOfInterest);
630  }
631 
632  FramesModifyingCalculated.insert(N->getLocationContext()->getStackFrame());
633 
634  if (wasRegionOfInterestModifiedAt(RegionOfInterest, N, ValueAtReturn)) {
635  const StackFrameContext *SCtx = N->getStackFrame();
636  while (!SCtx->inTopFrame()) {
637  auto p = FramesModifyingRegion.insert(SCtx);
638  if (!p.second)
639  break; // Frame and all its parents already inserted.
640  SCtx = SCtx->getParent()->getStackFrame();
641  }
642  }
643 
644  // Stop calculation at the call to the current function.
645  if (auto CE = N->getLocationAs<CallEnter>())
646  if (CE->getCalleeContext() == OriginalSCtx)
647  break;
648 
649  N = N->getFirstPred();
650  } while (N);
651 }
652 
653 static llvm::StringLiteral WillBeUsedForACondition =
654  ", which participates in a condition later";
655 
656 PathDiagnosticPieceRef NoStoreFuncVisitor::maybeEmitNote(
657  PathSensitiveBugReport &R, const CallEvent &Call, const ExplodedNode *N,
658  const RegionVector &FieldChain, const MemRegion *MatchedRegion,
659  StringRef FirstElement, bool FirstIsReferenceType,
660  unsigned IndirectionLevel) {
661  // Optimistically suppress uninitialized value bugs that result
662  // from system headers having a chance to initialize the value
663  // but failing to do so. It's too unlikely a system header's fault.
664  // It's much more likely a situation in which the function has a failure
665  // mode that the user decided not to check. If we want to hunt such
666  // omitted checks, we should provide an explicit function-specific note
667  // describing the precondition under which the function isn't supposed to
668  // initialize its out-parameter, and additionally check that such
669  // precondition can actually be fulfilled on the current path.
670  if (Call.isInSystemHeader()) {
671  // We make an exception for system header functions that have no branches.
672  // Such functions unconditionally fail to initialize the variable.
673  // If they call other functions that have more paths within them,
674  // this suppression would still apply when we visit these inner functions.
675  // One common example of a standard function that doesn't ever initialize
676  // its out parameter is operator placement new; it's up to the follow-up
677  // constructor (if any) to initialize the memory.
678  if (!N->getStackFrame()->getCFG()->isLinear())
679  R.markInvalid(getTag(), nullptr);
680  return nullptr;
681  }
682 
683  PathDiagnosticLocation L =
684  PathDiagnosticLocation::create(N->getLocation(), SM);
685 
686  // For now this shouldn't trigger, but once it does (as we add more
687  // functions to the body farm), we'll need to decide if these reports
688  // are worth suppressing as well.
689  if (!L.hasValidLocation())
690  return nullptr;
691 
692  SmallString<256> sbuf;
693  llvm::raw_svector_ostream os(sbuf);
694  os << "Returning without writing to '";
695 
696  // Do not generate the note if failed to pretty-print.
697  if (!prettyPrintRegionName(FirstElement, FirstIsReferenceType, MatchedRegion,
698  FieldChain, IndirectionLevel, os))
699  return nullptr;
700 
701  os << "'";
704  return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
705 }
706 
707 bool NoStoreFuncVisitor::prettyPrintRegionName(StringRef FirstElement,
708  bool FirstIsReferenceType,
709  const MemRegion *MatchedRegion,
710  const RegionVector &FieldChain,
711  int IndirectionLevel,
712  llvm::raw_svector_ostream &os) {
713 
714  if (FirstIsReferenceType)
715  IndirectionLevel--;
716 
717  RegionVector RegionSequence;
718 
719  // Add the regions in the reverse order, then reverse the resulting array.
720  assert(RegionOfInterest->isSubRegionOf(MatchedRegion));
721  const MemRegion *R = RegionOfInterest;
722  while (R != MatchedRegion) {
723  RegionSequence.push_back(R);
724  R = cast<SubRegion>(R)->getSuperRegion();
725  }
726  std::reverse(RegionSequence.begin(), RegionSequence.end());
727  RegionSequence.append(FieldChain.begin(), FieldChain.end());
728 
729  StringRef Sep;
730  for (const MemRegion *R : RegionSequence) {
731 
732  // Just keep going up to the base region.
733  // Element regions may appear due to casts.
734  if (isa<CXXBaseObjectRegion>(R) || isa<CXXTempObjectRegion>(R))
735  continue;
736 
737  if (Sep.empty())
738  Sep = prettyPrintFirstElement(FirstElement,
739  /*MoreItemsExpected=*/true,
740  IndirectionLevel, os);
741 
742  os << Sep;
743 
744  // Can only reasonably pretty-print DeclRegions.
745  if (!isa<DeclRegion>(R))
746  return false;
747 
748  const auto *DR = cast<DeclRegion>(R);
749  Sep = DR->getValueType()->isAnyPointerType() ? "->" : ".";
750  DR->getDecl()->getDeclName().print(os, PP);
751  }
752 
753  if (Sep.empty())
754  prettyPrintFirstElement(FirstElement,
755  /*MoreItemsExpected=*/false, IndirectionLevel, os);
756  return true;
757 }
758 
759 StringRef NoStoreFuncVisitor::prettyPrintFirstElement(
760  StringRef FirstElement, bool MoreItemsExpected, int IndirectionLevel,
761  llvm::raw_svector_ostream &os) {
762  StringRef Out = ".";
763 
764  if (IndirectionLevel > 0 && MoreItemsExpected) {
765  IndirectionLevel--;
766  Out = "->";
767  }
768 
769  if (IndirectionLevel > 0 && MoreItemsExpected)
770  os << "(";
771 
772  for (int i = 0; i < IndirectionLevel; i++)
773  os << "*";
774  os << FirstElement;
775 
776  if (IndirectionLevel > 0 && MoreItemsExpected)
777  os << ")";
778 
779  return Out;
780 }
781 
782 //===----------------------------------------------------------------------===//
783 // Implementation of MacroNullReturnSuppressionVisitor.
784 //===----------------------------------------------------------------------===//
785 
786 namespace {
787 
788 /// Suppress null-pointer-dereference bugs where dereferenced null was returned
789 /// the macro.
790 class MacroNullReturnSuppressionVisitor final : public BugReporterVisitor {
791  const SubRegion *RegionOfInterest;
792  const SVal ValueAtDereference;
793 
794  // Do not invalidate the reports where the value was modified
795  // after it got assigned to from the macro.
796  bool WasModified = false;
797 
798 public:
799  MacroNullReturnSuppressionVisitor(const SubRegion *R, const SVal V)
800  : RegionOfInterest(R), ValueAtDereference(V) {}
801 
802  PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
803  BugReporterContext &BRC,
804  PathSensitiveBugReport &BR) override {
805  if (WasModified)
806  return nullptr;
807 
808  auto BugPoint = BR.getErrorNode()->getLocation().getAs<StmtPoint>();
809  if (!BugPoint)
810  return nullptr;
811 
812  const SourceManager &SMgr = BRC.getSourceManager();
813  if (auto Loc = matchAssignment(N)) {
814  if (isFunctionMacroExpansion(*Loc, SMgr)) {
815  std::string MacroName = std::string(getMacroName(*Loc, BRC));
816  SourceLocation BugLoc = BugPoint->getStmt()->getBeginLoc();
817  if (!BugLoc.isMacroID() || getMacroName(BugLoc, BRC) != MacroName)
818  BR.markInvalid(getTag(), MacroName.c_str());
819  }
820  }
821 
822  if (wasRegionOfInterestModifiedAt(RegionOfInterest, N, ValueAtDereference))
823  WasModified = true;
824 
825  return nullptr;
826  }
827 
828  static void addMacroVisitorIfNecessary(
829  const ExplodedNode *N, const MemRegion *R,
830  bool EnableNullFPSuppression, PathSensitiveBugReport &BR,
831  const SVal V) {
832  AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
833  if (EnableNullFPSuppression &&
834  Options.ShouldSuppressNullReturnPaths && V.getAs<Loc>())
835  BR.addVisitor(std::make_unique<MacroNullReturnSuppressionVisitor>(
836  R->getAs<SubRegion>(), V));
837  }
838 
839  void* getTag() const {
840  static int Tag = 0;
841  return static_cast<void *>(&Tag);
842  }
843 
844  void Profile(llvm::FoldingSetNodeID &ID) const override {
845  ID.AddPointer(getTag());
846  }
847 
848 private:
849  /// \return Source location of right hand side of an assignment
850  /// into \c RegionOfInterest, empty optional if none found.
851  Optional<SourceLocation> matchAssignment(const ExplodedNode *N) {
852  const Stmt *S = N->getStmtForDiagnostics();
853  ProgramStateRef State = N->getState();
854  auto *LCtx = N->getLocationContext();
855  if (!S)
856  return None;
857 
858  if (const auto *DS = dyn_cast<DeclStmt>(S)) {
859  if (const auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl()))
860  if (const Expr *RHS = VD->getInit())
861  if (RegionOfInterest->isSubRegionOf(
862  State->getLValue(VD, LCtx).getAsRegion()))
863  return RHS->getBeginLoc();
864  } else if (const auto *BO = dyn_cast<BinaryOperator>(S)) {
865  const MemRegion *R = N->getSVal(BO->getLHS()).getAsRegion();
866  const Expr *RHS = BO->getRHS();
867  if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(R)) {
868  return RHS->getBeginLoc();
869  }
870  }
871  return None;
872  }
873 };
874 
875 } // end of anonymous namespace
876 
877 namespace {
878 
879 /// Emits an extra note at the return statement of an interesting stack frame.
880 ///
881 /// The returned value is marked as an interesting value, and if it's null,
882 /// adds a visitor to track where it became null.
883 ///
884 /// This visitor is intended to be used when another visitor discovers that an
885 /// interesting value comes from an inlined function call.
886 class ReturnVisitor : public BugReporterVisitor {
887  const StackFrameContext *CalleeSFC;
888  enum {
889  Initial,
890  MaybeUnsuppress,
891  Satisfied
892  } Mode = Initial;
893 
894  bool EnableNullFPSuppression;
895  bool ShouldInvalidate = true;
896  AnalyzerOptions& Options;
898 
899 public:
900  ReturnVisitor(const StackFrameContext *Frame, bool Suppressed,
902  : CalleeSFC(Frame), EnableNullFPSuppression(Suppressed),
903  Options(Options), TKind(TKind) {}
904 
905  static void *getTag() {
906  static int Tag = 0;
907  return static_cast<void *>(&Tag);
908  }
909 
910  void Profile(llvm::FoldingSetNodeID &ID) const override {
911  ID.AddPointer(ReturnVisitor::getTag());
912  ID.AddPointer(CalleeSFC);
913  ID.AddBoolean(EnableNullFPSuppression);
914  }
915 
916  /// Adds a ReturnVisitor if the given statement represents a call that was
917  /// inlined.
918  ///
919  /// This will search back through the ExplodedGraph, starting from the given
920  /// node, looking for when the given statement was processed. If it turns out
921  /// the statement is a call that was inlined, we add the visitor to the
922  /// bug report, so it can print a note later.
923  static void addVisitorIfNecessary(const ExplodedNode *Node, const Stmt *S,
924  PathSensitiveBugReport &BR,
925  bool InEnableNullFPSuppression,
927  if (!CallEvent::isCallStmt(S))
928  return;
929 
930  // First, find when we processed the statement.
931  // If we work with a 'CXXNewExpr' that is going to be purged away before
932  // its call take place. We would catch that purge in the last condition
933  // as a 'StmtPoint' so we have to bypass it.
934  const bool BypassCXXNewExprEval = isa<CXXNewExpr>(S);
935 
936  // This is moving forward when we enter into another context.
937  const StackFrameContext *CurrentSFC = Node->getStackFrame();
938 
939  do {
940  // If that is satisfied we found our statement as an inlined call.
941  if (Optional<CallExitEnd> CEE = Node->getLocationAs<CallExitEnd>())
942  if (CEE->getCalleeContext()->getCallSite() == S)
943  break;
944 
945  // Try to move forward to the end of the call-chain.
946  Node = Node->getFirstPred();
947  if (!Node)
948  break;
949 
950  const StackFrameContext *PredSFC = Node->getStackFrame();
951 
952  // If that is satisfied we found our statement.
953  // FIXME: This code currently bypasses the call site for the
954  // conservatively evaluated allocator.
955  if (!BypassCXXNewExprEval)
956  if (Optional<StmtPoint> SP = Node->getLocationAs<StmtPoint>())
957  // See if we do not enter into another context.
958  if (SP->getStmt() == S && CurrentSFC == PredSFC)
959  break;
960 
961  CurrentSFC = PredSFC;
962  } while (Node->getStackFrame() == CurrentSFC);
963 
964  // Next, step over any post-statement checks.
965  while (Node && Node->getLocation().getAs<PostStmt>())
966  Node = Node->getFirstPred();
967  if (!Node)
968  return;
969 
970  // Finally, see if we inlined the call.
971  Optional<CallExitEnd> CEE = Node->getLocationAs<CallExitEnd>();
972  if (!CEE)
973  return;
974 
975  const StackFrameContext *CalleeContext = CEE->getCalleeContext();
976  if (CalleeContext->getCallSite() != S)
977  return;
978 
979  // Check the return value.
980  ProgramStateRef State = Node->getState();
981  SVal RetVal = Node->getSVal(S);
982 
983  // Handle cases where a reference is returned and then immediately used.
984  if (cast<Expr>(S)->isGLValue())
985  if (Optional<Loc> LValue = RetVal.getAs<Loc>())
986  RetVal = State->getSVal(*LValue);
987 
988  // See if the return value is NULL. If so, suppress the report.
989  AnalyzerOptions &Options = State->getAnalysisManager().options;
990 
991  bool EnableNullFPSuppression = false;
992  if (InEnableNullFPSuppression &&
993  Options.ShouldSuppressNullReturnPaths)
994  if (Optional<Loc> RetLoc = RetVal.getAs<Loc>())
995  EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
996 
997  BR.addVisitor(std::make_unique<ReturnVisitor>(CalleeContext,
998  EnableNullFPSuppression,
999  Options, TKind));
1000  }
1001 
1002  PathDiagnosticPieceRef visitNodeInitial(const ExplodedNode *N,
1003  BugReporterContext &BRC,
1004  PathSensitiveBugReport &BR) {
1005  // Only print a message at the interesting return statement.
1006  if (N->getLocationContext() != CalleeSFC)
1007  return nullptr;
1008 
1009  Optional<StmtPoint> SP = N->getLocationAs<StmtPoint>();
1010  if (!SP)
1011  return nullptr;
1012 
1013  const auto *Ret = dyn_cast<ReturnStmt>(SP->getStmt());
1014  if (!Ret)
1015  return nullptr;
1016 
1017  // Okay, we're at the right return statement, but do we have the return
1018  // value available?
1019  ProgramStateRef State = N->getState();
1020  SVal V = State->getSVal(Ret, CalleeSFC);
1021  if (V.isUnknownOrUndef())
1022  return nullptr;
1023 
1024  // Don't print any more notes after this one.
1025  Mode = Satisfied;
1026 
1027  const Expr *RetE = Ret->getRetValue();
1028  assert(RetE && "Tracking a return value for a void function");
1029 
1030  // Handle cases where a reference is returned and then immediately used.
1031  Optional<Loc> LValue;
1032  if (RetE->isGLValue()) {
1033  if ((LValue = V.getAs<Loc>())) {
1034  SVal RValue = State->getRawSVal(*LValue, RetE->getType());
1035  if (RValue.getAs<DefinedSVal>())
1036  V = RValue;
1037  }
1038  }
1039 
1040  // Ignore aggregate rvalues.
1041  if (V.getAs<nonloc::LazyCompoundVal>() ||
1042  V.getAs<nonloc::CompoundVal>())
1043  return nullptr;
1044 
1045  RetE = RetE->IgnoreParenCasts();
1046 
1047  // Let's track the return value.
1049  N, RetE, BR, TKind, EnableNullFPSuppression);
1050 
1051  // Build an appropriate message based on the return value.
1052  SmallString<64> Msg;
1053  llvm::raw_svector_ostream Out(Msg);
1054 
1055  bool WouldEventBeMeaningless = false;
1056 
1057  if (State->isNull(V).isConstrainedTrue()) {
1058  if (V.getAs<Loc>()) {
1059 
1060  // If we have counter-suppression enabled, make sure we keep visiting
1061  // future nodes. We want to emit a path note as well, in case
1062  // the report is resurrected as valid later on.
1063  if (EnableNullFPSuppression &&
1064  Options.ShouldAvoidSuppressingNullArgumentPaths)
1065  Mode = MaybeUnsuppress;
1066 
1067  if (RetE->getType()->isObjCObjectPointerType()) {
1068  Out << "Returning nil";
1069  } else {
1070  Out << "Returning null pointer";
1071  }
1072  } else {
1073  Out << "Returning zero";
1074  }
1075 
1076  } else {
1077  if (auto CI = V.getAs<nonloc::ConcreteInt>()) {
1078  Out << "Returning the value " << CI->getValue();
1079  } else {
1080  // There is nothing interesting about returning a value, when it is
1081  // plain value without any constraints, and the function is guaranteed
1082  // to return that every time. We could use CFG::isLinear() here, but
1083  // constexpr branches are obvious to the compiler, not necesserily to
1084  // the programmer.
1085  if (N->getCFG().size() == 3)
1086  WouldEventBeMeaningless = true;
1087 
1088  if (V.getAs<Loc>())
1089  Out << "Returning pointer";
1090  else
1091  Out << "Returning value";
1092  }
1093  }
1094 
1095  if (LValue) {
1096  if (const MemRegion *MR = LValue->getAsRegion()) {
1097  if (MR->canPrintPretty()) {
1098  Out << " (reference to ";
1099  MR->printPretty(Out);
1100  Out << ")";
1101  }
1102  }
1103  } else {
1104  // FIXME: We should have a more generalized location printing mechanism.
1105  if (const auto *DR = dyn_cast<DeclRefExpr>(RetE))
1106  if (const auto *DD = dyn_cast<DeclaratorDecl>(DR->getDecl()))
1107  Out << " (loaded from '" << *DD << "')";
1108  }
1109 
1110  PathDiagnosticLocation L(Ret, BRC.getSourceManager(), CalleeSFC);
1111  if (!L.isValid() || !L.asLocation().isValid())
1112  return nullptr;
1113 
1115  Out << WillBeUsedForACondition;
1116 
1117  auto EventPiece = std::make_shared<PathDiagnosticEventPiece>(L, Out.str());
1118 
1119  // If we determined that the note is meaningless, make it prunable, and
1120  // don't mark the stackframe interesting.
1121  if (WouldEventBeMeaningless)
1122  EventPiece->setPrunable(true);
1123  else
1124  BR.markInteresting(CalleeSFC);
1125 
1126  return EventPiece;
1127  }
1128 
1129  PathDiagnosticPieceRef visitNodeMaybeUnsuppress(const ExplodedNode *N,
1130  BugReporterContext &BRC,
1131  PathSensitiveBugReport &BR) {
1132  assert(Options.ShouldAvoidSuppressingNullArgumentPaths);
1133 
1134  // Are we at the entry node for this call?
1135  Optional<CallEnter> CE = N->getLocationAs<CallEnter>();
1136  if (!CE)
1137  return nullptr;
1138 
1139  if (CE->getCalleeContext() != CalleeSFC)
1140  return nullptr;
1141 
1142  Mode = Satisfied;
1143 
1144  // Don't automatically suppress a report if one of the arguments is
1145  // known to be a null pointer. Instead, start tracking /that/ null
1146  // value back to its origin.
1147  ProgramStateManager &StateMgr = BRC.getStateManager();
1148  CallEventManager &CallMgr = StateMgr.getCallEventManager();
1149 
1150  ProgramStateRef State = N->getState();
1151  CallEventRef<> Call = CallMgr.getCaller(CalleeSFC, State);
1152  for (unsigned I = 0, E = Call->getNumArgs(); I != E; ++I) {
1153  Optional<Loc> ArgV = Call->getArgSVal(I).getAs<Loc>();
1154  if (!ArgV)
1155  continue;
1156 
1157  const Expr *ArgE = Call->getArgExpr(I);
1158  if (!ArgE)
1159  continue;
1160 
1161  // Is it possible for this argument to be non-null?
1162  if (!State->isNull(*ArgV).isConstrainedTrue())
1163  continue;
1164 
1165  if (trackExpressionValue(N, ArgE, BR, TKind, EnableNullFPSuppression))
1166  ShouldInvalidate = false;
1167 
1168  // If we /can't/ track the null pointer, we should err on the side of
1169  // false negatives, and continue towards marking this report invalid.
1170  // (We will still look at the other arguments, though.)
1171  }
1172 
1173  return nullptr;
1174  }
1175 
1176  PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
1177  BugReporterContext &BRC,
1178  PathSensitiveBugReport &BR) override {
1179  switch (Mode) {
1180  case Initial:
1181  return visitNodeInitial(N, BRC, BR);
1182  case MaybeUnsuppress:
1183  return visitNodeMaybeUnsuppress(N, BRC, BR);
1184  case Satisfied:
1185  return nullptr;
1186  }
1187 
1188  llvm_unreachable("Invalid visit mode!");
1189  }
1190 
1191  void finalizeVisitor(BugReporterContext &, const ExplodedNode *,
1192  PathSensitiveBugReport &BR) override {
1193  if (EnableNullFPSuppression && ShouldInvalidate)
1194  BR.markInvalid(ReturnVisitor::getTag(), CalleeSFC);
1195  }
1196 };
1197 
1198 } // end of anonymous namespace
1199 
1200 //===----------------------------------------------------------------------===//
1201 // Implementation of FindLastStoreBRVisitor.
1202 //===----------------------------------------------------------------------===//
1203 
1204 void FindLastStoreBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
1205  static int tag = 0;
1206  ID.AddPointer(&tag);
1207  ID.AddPointer(R);
1208  ID.Add(V);
1209  ID.AddInteger(static_cast<int>(TKind));
1210  ID.AddBoolean(EnableNullFPSuppression);
1211 }
1212 
1213 /// Returns true if \p N represents the DeclStmt declaring and initializing
1214 /// \p VR.
1215 static bool isInitializationOfVar(const ExplodedNode *N, const VarRegion *VR) {
1216  Optional<PostStmt> P = N->getLocationAs<PostStmt>();
1217  if (!P)
1218  return false;
1219 
1220  const DeclStmt *DS = P->getStmtAs<DeclStmt>();
1221  if (!DS)
1222  return false;
1223 
1224  if (DS->getSingleDecl() != VR->getDecl())
1225  return false;
1226 
1227  const MemSpaceRegion *VarSpace = VR->getMemorySpace();
1228  const auto *FrameSpace = dyn_cast<StackSpaceRegion>(VarSpace);
1229  if (!FrameSpace) {
1230  // If we ever directly evaluate global DeclStmts, this assertion will be
1231  // invalid, but this still seems preferable to silently accepting an
1232  // initialization that may be for a path-sensitive variable.
1233  assert(VR->getDecl()->isStaticLocal() && "non-static stackless VarRegion");
1234  return true;
1235  }
1236 
1237  assert(VR->getDecl()->hasLocalStorage());
1238  const LocationContext *LCtx = N->getLocationContext();
1239  return FrameSpace->getStackFrame() == LCtx->getStackFrame();
1240 }
1241 
1242 /// Show diagnostics for initializing or declaring a region \p R with a bad value.
1243 static void showBRDiagnostics(const char *action, llvm::raw_svector_ostream &os,
1244  const MemRegion *R, SVal V, const DeclStmt *DS) {
1245  if (R->canPrintPretty()) {
1246  R->printPretty(os);
1247  os << " ";
1248  }
1249 
1250  if (V.getAs<loc::ConcreteInt>()) {
1251  bool b = false;
1252  if (R->isBoundable()) {
1253  if (const auto *TR = dyn_cast<TypedValueRegion>(R)) {
1254  if (TR->getValueType()->isObjCObjectPointerType()) {
1255  os << action << "nil";
1256  b = true;
1257  }
1258  }
1259  }
1260  if (!b)
1261  os << action << "a null pointer value";
1262 
1263  } else if (auto CVal = V.getAs<nonloc::ConcreteInt>()) {
1264  os << action << CVal->getValue();
1265  } else if (DS) {
1266  if (V.isUndef()) {
1267  if (isa<VarRegion>(R)) {
1268  const auto *VD = cast<VarDecl>(DS->getSingleDecl());
1269  if (VD->getInit()) {
1270  os << (R->canPrintPretty() ? "initialized" : "Initializing")
1271  << " to a garbage value";
1272  } else {
1273  os << (R->canPrintPretty() ? "declared" : "Declaring")
1274  << " without an initial value";
1275  }
1276  }
1277  } else {
1278  os << (R->canPrintPretty() ? "initialized" : "Initialized")
1279  << " here";
1280  }
1281  }
1282 }
1283 
1284 /// Display diagnostics for passing bad region as a parameter.
1285 static void showBRParamDiagnostics(llvm::raw_svector_ostream& os,
1286  const VarRegion *VR,
1287  SVal V) {
1288  const auto *Param = cast<ParmVarDecl>(VR->getDecl());
1289 
1290  os << "Passing ";
1291 
1292  if (V.getAs<loc::ConcreteInt>()) {
1293  if (Param->getType()->isObjCObjectPointerType())
1294  os << "nil object reference";
1295  else
1296  os << "null pointer value";
1297  } else if (V.isUndef()) {
1298  os << "uninitialized value";
1299  } else if (auto CI = V.getAs<nonloc::ConcreteInt>()) {
1300  os << "the value " << CI->getValue();
1301  } else {
1302  os << "value";
1303  }
1304 
1305  // Printed parameter indexes are 1-based, not 0-based.
1306  unsigned Idx = Param->getFunctionScopeIndex() + 1;
1307  os << " via " << Idx << llvm::getOrdinalSuffix(Idx) << " parameter";
1308  if (VR->canPrintPretty()) {
1309  os << " ";
1310  VR->printPretty(os);
1311  }
1312 }
1313 
1314 /// Show default diagnostics for storing bad region.
1315 static void showBRDefaultDiagnostics(llvm::raw_svector_ostream &os,
1316  const MemRegion *R, SVal V) {
1317  if (V.getAs<loc::ConcreteInt>()) {
1318  bool b = false;
1319  if (R->isBoundable()) {
1320  if (const auto *TR = dyn_cast<TypedValueRegion>(R)) {
1321  if (TR->getValueType()->isObjCObjectPointerType()) {
1322  os << "nil object reference stored";
1323  b = true;
1324  }
1325  }
1326  }
1327  if (!b) {
1328  if (R->canPrintPretty())
1329  os << "Null pointer value stored";
1330  else
1331  os << "Storing null pointer value";
1332  }
1333 
1334  } else if (V.isUndef()) {
1335  if (R->canPrintPretty())
1336  os << "Uninitialized value stored";
1337  else
1338  os << "Storing uninitialized value";
1339 
1340  } else if (auto CV = V.getAs<nonloc::ConcreteInt>()) {
1341  if (R->canPrintPretty())
1342  os << "The value " << CV->getValue() << " is assigned";
1343  else
1344  os << "Assigning " << CV->getValue();
1345 
1346  } else {
1347  if (R->canPrintPretty())
1348  os << "Value assigned";
1349  else
1350  os << "Assigning value";
1351  }
1352 
1353  if (R->canPrintPretty()) {
1354  os << " to ";
1355  R->printPretty(os);
1356  }
1357 }
1358 
1361  BugReporterContext &BRC,
1362  PathSensitiveBugReport &BR) {
1363  if (Satisfied)
1364  return nullptr;
1365 
1366  const ExplodedNode *StoreSite = nullptr;
1367  const ExplodedNode *Pred = Succ->getFirstPred();
1368  const Expr *InitE = nullptr;
1369  bool IsParam = false;
1370 
1371  // First see if we reached the declaration of the region.
1372  if (const auto *VR = dyn_cast<VarRegion>(R)) {
1373  if (isInitializationOfVar(Pred, VR)) {
1374  StoreSite = Pred;
1375  InitE = VR->getDecl()->getInit();
1376  }
1377  }
1378 
1379  // If this is a post initializer expression, initializing the region, we
1380  // should track the initializer expression.
1382  const MemRegion *FieldReg = (const MemRegion *)PIP->getLocationValue();
1383  if (FieldReg == R) {
1384  StoreSite = Pred;
1385  InitE = PIP->getInitializer()->getInit();
1386  }
1387  }
1388 
1389  // Otherwise, see if this is the store site:
1390  // (1) Succ has this binding and Pred does not, i.e. this is
1391  // where the binding first occurred.
1392  // (2) Succ has this binding and is a PostStore node for this region, i.e.
1393  // the same binding was re-assigned here.
1394  if (!StoreSite) {
1395  if (Succ->getState()->getSVal(R) != V)
1396  return nullptr;
1397 
1398  if (hasVisibleUpdate(Pred, Pred->getState()->getSVal(R), Succ, V)) {
1400  if (!PS || PS->getLocationValue() != R)
1401  return nullptr;
1402  }
1403 
1404  StoreSite = Succ;
1405 
1406  // If this is an assignment expression, we can track the value
1407  // being assigned.
1408  if (Optional<PostStmt> P = Succ->getLocationAs<PostStmt>())
1409  if (const BinaryOperator *BO = P->getStmtAs<BinaryOperator>())
1410  if (BO->isAssignmentOp())
1411  InitE = BO->getRHS();
1412 
1413  // If this is a call entry, the variable should be a parameter.
1414  // FIXME: Handle CXXThisRegion as well. (This is not a priority because
1415  // 'this' should never be NULL, but this visitor isn't just for NULL and
1416  // UndefinedVal.)
1417  if (Optional<CallEnter> CE = Succ->getLocationAs<CallEnter>()) {
1418  if (const auto *VR = dyn_cast<VarRegion>(R)) {
1419 
1420  if (const auto *Param = dyn_cast<ParmVarDecl>(VR->getDecl())) {
1421  ProgramStateManager &StateMgr = BRC.getStateManager();
1422  CallEventManager &CallMgr = StateMgr.getCallEventManager();
1423 
1424  CallEventRef<> Call = CallMgr.getCaller(CE->getCalleeContext(),
1425  Succ->getState());
1426  InitE = Call->getArgExpr(Param->getFunctionScopeIndex());
1427  } else {
1428  // Handle Objective-C 'self'.
1429  assert(isa<ImplicitParamDecl>(VR->getDecl()));
1430  InitE = cast<ObjCMessageExpr>(CE->getCalleeContext()->getCallSite())
1431  ->getInstanceReceiver()->IgnoreParenCasts();
1432  }
1433  IsParam = true;
1434  }
1435  }
1436 
1437  // If this is a CXXTempObjectRegion, the Expr responsible for its creation
1438  // is wrapped inside of it.
1439  if (const auto *TmpR = dyn_cast<CXXTempObjectRegion>(R))
1440  InitE = TmpR->getExpr();
1441  }
1442 
1443  if (!StoreSite)
1444  return nullptr;
1445 
1446  Satisfied = true;
1447 
1448  // If we have an expression that provided the value, try to track where it
1449  // came from.
1450  if (InitE) {
1451  if (!IsParam)
1452  InitE = InitE->IgnoreParenCasts();
1453 
1455  StoreSite, InitE, BR, TKind, EnableNullFPSuppression);
1456  }
1457 
1458  if (TKind == TrackingKind::Condition &&
1459  !OriginSFC->isParentOf(StoreSite->getStackFrame()))
1460  return nullptr;
1461 
1462  // Okay, we've found the binding. Emit an appropriate message.
1463  SmallString<256> sbuf;
1464  llvm::raw_svector_ostream os(sbuf);
1465 
1466  if (Optional<PostStmt> PS = StoreSite->getLocationAs<PostStmt>()) {
1467  const Stmt *S = PS->getStmt();
1468  const char *action = nullptr;
1469  const auto *DS = dyn_cast<DeclStmt>(S);
1470  const auto *VR = dyn_cast<VarRegion>(R);
1471 
1472  if (DS) {
1473  action = R->canPrintPretty() ? "initialized to " :
1474  "Initializing to ";
1475  } else if (isa<BlockExpr>(S)) {
1476  action = R->canPrintPretty() ? "captured by block as " :
1477  "Captured by block as ";
1478  if (VR) {
1479  // See if we can get the BlockVarRegion.
1480  ProgramStateRef State = StoreSite->getState();
1481  SVal V = StoreSite->getSVal(S);
1482  if (const auto *BDR =
1483  dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
1484  if (const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) {
1485  if (auto KV = State->getSVal(OriginalR).getAs<KnownSVal>())
1486  BR.addVisitor(std::make_unique<FindLastStoreBRVisitor>(
1487  *KV, OriginalR, EnableNullFPSuppression, TKind, OriginSFC));
1488  }
1489  }
1490  }
1491  }
1492  if (action)
1493  showBRDiagnostics(action, os, R, V, DS);
1494 
1495  } else if (StoreSite->getLocation().getAs<CallEnter>()) {
1496  if (const auto *VR = dyn_cast<VarRegion>(R))
1497  showBRParamDiagnostics(os, VR, V);
1498  }
1499 
1500  if (os.str().empty())
1501  showBRDefaultDiagnostics(os, R, V);
1502 
1505 
1506  // Construct a new PathDiagnosticPiece.
1507  ProgramPoint P = StoreSite->getLocation();
1509  if (P.getAs<CallEnter>() && InitE)
1510  L = PathDiagnosticLocation(InitE, BRC.getSourceManager(),
1511  P.getLocationContext());
1512 
1513  if (!L.isValid() || !L.asLocation().isValid())
1515 
1516  if (!L.isValid() || !L.asLocation().isValid())
1517  return nullptr;
1518 
1519  return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
1520 }
1521 
1522 //===----------------------------------------------------------------------===//
1523 // Implementation of TrackConstraintBRVisitor.
1524 //===----------------------------------------------------------------------===//
1525 
1526 void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
1527  static int tag = 0;
1528  ID.AddPointer(&tag);
1529  ID.AddBoolean(Assumption);
1530  ID.Add(Constraint);
1531 }
1532 
1533 /// Return the tag associated with this visitor. This tag will be used
1534 /// to make all PathDiagnosticPieces created by this visitor.
1536  return "TrackConstraintBRVisitor";
1537 }
1538 
1539 bool TrackConstraintBRVisitor::isUnderconstrained(const ExplodedNode *N) const {
1540  if (IsZeroCheck)
1541  return N->getState()->isNull(Constraint).isUnderconstrained();
1542  return (bool)N->getState()->assume(Constraint, !Assumption);
1543 }
1544 
1547  const ExplodedNode *PrevN = N->getFirstPred();
1548  if (IsSatisfied)
1549  return nullptr;
1550 
1551  // Start tracking after we see the first state in which the value is
1552  // constrained.
1553  if (!IsTrackingTurnedOn)
1554  if (!isUnderconstrained(N))
1555  IsTrackingTurnedOn = true;
1556  if (!IsTrackingTurnedOn)
1557  return nullptr;
1558 
1559  // Check if in the previous state it was feasible for this constraint
1560  // to *not* be true.
1561  if (isUnderconstrained(PrevN)) {
1562  IsSatisfied = true;
1563 
1564  // As a sanity check, make sure that the negation of the constraint
1565  // was infeasible in the current state. If it is feasible, we somehow
1566  // missed the transition point.
1567  assert(!isUnderconstrained(N));
1568 
1569  // We found the transition point for the constraint. We now need to
1570  // pretty-print the constraint. (work-in-progress)
1571  SmallString<64> sbuf;
1572  llvm::raw_svector_ostream os(sbuf);
1573 
1574  if (Constraint.getAs<Loc>()) {
1575  os << "Assuming pointer value is ";
1576  os << (Assumption ? "non-null" : "null");
1577  }
1578 
1579  if (os.str().empty())
1580  return nullptr;
1581 
1582  // Construct a new PathDiagnosticPiece.
1583  ProgramPoint P = N->getLocation();
1586  if (!L.isValid())
1587  return nullptr;
1588 
1589  auto X = std::make_shared<PathDiagnosticEventPiece>(L, os.str());
1590  X->setTag(getTag());
1591  return std::move(X);
1592  }
1593 
1594  return nullptr;
1595 }
1596 
1597 //===----------------------------------------------------------------------===//
1598 // Implementation of SuppressInlineDefensiveChecksVisitor.
1599 //===----------------------------------------------------------------------===//
1600 
1603  : V(Value) {
1604  // Check if the visitor is disabled.
1605  AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
1606  if (!Options.ShouldSuppressInlinedDefensiveChecks)
1607  IsSatisfied = true;
1608 }
1609 
1611  llvm::FoldingSetNodeID &ID) const {
1612  static int id = 0;
1613  ID.AddPointer(&id);
1614  ID.Add(V);
1615 }
1616 
1618  return "IDCVisitor";
1619 }
1620 
1623  BugReporterContext &BRC,
1624  PathSensitiveBugReport &BR) {
1625  const ExplodedNode *Pred = Succ->getFirstPred();
1626  if (IsSatisfied)
1627  return nullptr;
1628 
1629  // Start tracking after we see the first state in which the value is null.
1630  if (!IsTrackingTurnedOn)
1631  if (Succ->getState()->isNull(V).isConstrainedTrue())
1632  IsTrackingTurnedOn = true;
1633  if (!IsTrackingTurnedOn)
1634  return nullptr;
1635 
1636  // Check if in the previous state it was feasible for this value
1637  // to *not* be null.
1638  if (!Pred->getState()->isNull(V).isConstrainedTrue() &&
1639  Succ->getState()->isNull(V).isConstrainedTrue()) {
1640  IsSatisfied = true;
1641 
1642  // Check if this is inlined defensive checks.
1643  const LocationContext *CurLC = Succ->getLocationContext();
1644  const LocationContext *ReportLC = BR.getErrorNode()->getLocationContext();
1645  if (CurLC != ReportLC && !CurLC->isParentOf(ReportLC)) {
1646  BR.markInvalid("Suppress IDC", CurLC);
1647  return nullptr;
1648  }
1649 
1650  // Treat defensive checks in function-like macros as if they were an inlined
1651  // defensive check. If the bug location is not in a macro and the
1652  // terminator for the current location is in a macro then suppress the
1653  // warning.
1654  auto BugPoint = BR.getErrorNode()->getLocation().getAs<StmtPoint>();
1655 
1656  if (!BugPoint)
1657  return nullptr;
1658 
1659  ProgramPoint CurPoint = Succ->getLocation();
1660  const Stmt *CurTerminatorStmt = nullptr;
1661  if (auto BE = CurPoint.getAs<BlockEdge>()) {
1662  CurTerminatorStmt = BE->getSrc()->getTerminator().getStmt();
1663  } else if (auto SP = CurPoint.getAs<StmtPoint>()) {
1664  const Stmt *CurStmt = SP->getStmt();
1665  if (!CurStmt->getBeginLoc().isMacroID())
1666  return nullptr;
1667 
1668  CFGStmtMap *Map = CurLC->getAnalysisDeclContext()->getCFGStmtMap();
1669  CurTerminatorStmt = Map->getBlock(CurStmt)->getTerminatorStmt();
1670  } else {
1671  return nullptr;
1672  }
1673 
1674  if (!CurTerminatorStmt)
1675  return nullptr;
1676 
1677  SourceLocation TerminatorLoc = CurTerminatorStmt->getBeginLoc();
1678  if (TerminatorLoc.isMacroID()) {
1679  SourceLocation BugLoc = BugPoint->getStmt()->getBeginLoc();
1680 
1681  // Suppress reports unless we are in that same macro.
1682  if (!BugLoc.isMacroID() ||
1683  getMacroName(BugLoc, BRC) != getMacroName(TerminatorLoc, BRC)) {
1684  BR.markInvalid("Suppress Macro IDC", CurLC);
1685  }
1686  return nullptr;
1687  }
1688  }
1689  return nullptr;
1690 }
1691 
1692 //===----------------------------------------------------------------------===//
1693 // TrackControlDependencyCondBRVisitor.
1694 //===----------------------------------------------------------------------===//
1695 
1696 namespace {
1697 /// Tracks the expressions that are a control dependency of the node that was
1698 /// supplied to the constructor.
1699 /// For example:
1700 ///
1701 /// cond = 1;
1702 /// if (cond)
1703 /// 10 / 0;
1704 ///
1705 /// An error is emitted at line 3. This visitor realizes that the branch
1706 /// on line 2 is a control dependency of line 3, and tracks it's condition via
1707 /// trackExpressionValue().
1708 class TrackControlDependencyCondBRVisitor final : public BugReporterVisitor {
1709  const ExplodedNode *Origin;
1710  ControlDependencyCalculator ControlDeps;
1711  llvm::SmallSet<const CFGBlock *, 32> VisitedBlocks;
1712 
1713 public:
1714  TrackControlDependencyCondBRVisitor(const ExplodedNode *O)
1715  : Origin(O), ControlDeps(&O->getCFG()) {}
1716 
1717  void Profile(llvm::FoldingSetNodeID &ID) const override {
1718  static int x = 0;
1719  ID.AddPointer(&x);
1720  }
1721 
1722  PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
1723  BugReporterContext &BRC,
1724  PathSensitiveBugReport &BR) override;
1725 };
1726 } // end of anonymous namespace
1727 
1728 static std::shared_ptr<PathDiagnosticEventPiece>
1730  const ExplodedNode *N,
1731  BugReporterContext &BRC) {
1732 
1733  if (BRC.getAnalyzerOptions().AnalysisDiagOpt == PD_NONE ||
1734  !BRC.getAnalyzerOptions().ShouldTrackConditionsDebug)
1735  return nullptr;
1736 
1739  BRC.getSourceManager(), BRC.getASTContext().getLangOpts()));
1740 
1741  return std::make_shared<PathDiagnosticEventPiece>(
1743  Cond, BRC.getSourceManager(), N->getLocationContext()),
1744  (Twine() + "Tracking condition '" + ConditionText + "'").str());
1745 }
1746 
1747 static bool isAssertlikeBlock(const CFGBlock *B, ASTContext &Context) {
1748  if (B->succ_size() != 2)
1749  return false;
1750 
1751  const CFGBlock *Then = B->succ_begin()->getReachableBlock();
1752  const CFGBlock *Else = (B->succ_begin() + 1)->getReachableBlock();
1753 
1754  if (!Then || !Else)
1755  return false;
1756 
1757  if (Then->isInevitablySinking() != Else->isInevitablySinking())
1758  return true;
1759 
1760  // For the following condition the following CFG would be built:
1761  //
1762  // ------------->
1763  // / \
1764  // [B1] -> [B2] -> [B3] -> [sink]
1765  // assert(A && B || C); \ \
1766  // -----------> [go on with the execution]
1767  //
1768  // It so happens that CFGBlock::getTerminatorCondition returns 'A' for block
1769  // B1, 'A && B' for B2, and 'A && B || C' for B3. Let's check whether we
1770  // reached the end of the condition!
1771  if (const Stmt *ElseCond = Else->getTerminatorCondition())
1772  if (const auto *BinOp = dyn_cast<BinaryOperator>(ElseCond))
1773  if (BinOp->isLogicalOp())
1774  return isAssertlikeBlock(Else, Context);
1775 
1776  return false;
1777 }
1778 
1780 TrackControlDependencyCondBRVisitor::VisitNode(const ExplodedNode *N,
1781  BugReporterContext &BRC,
1782  PathSensitiveBugReport &BR) {
1783  // We can only reason about control dependencies within the same stack frame.
1784  if (Origin->getStackFrame() != N->getStackFrame())
1785  return nullptr;
1786 
1787  CFGBlock *NB = const_cast<CFGBlock *>(N->getCFGBlock());
1788 
1789  // Skip if we already inspected this block.
1790  if (!VisitedBlocks.insert(NB).second)
1791  return nullptr;
1792 
1793  CFGBlock *OriginB = const_cast<CFGBlock *>(Origin->getCFGBlock());
1794 
1795  // TODO: Cache CFGBlocks for each ExplodedNode.
1796  if (!OriginB || !NB)
1797  return nullptr;
1798 
1799  if (isAssertlikeBlock(NB, BRC.getASTContext()))
1800  return nullptr;
1801 
1802  if (ControlDeps.isControlDependent(OriginB, NB)) {
1803  // We don't really want to explain for range loops. Evidence suggests that
1804  // the only thing that leads to is the addition of calls to operator!=.
1805  if (llvm::isa_and_nonnull<CXXForRangeStmt>(NB->getTerminatorStmt()))
1806  return nullptr;
1807 
1808  if (const Expr *Condition = NB->getLastCondition()) {
1809  // Keeping track of the already tracked conditions on a visitor level
1810  // isn't sufficient, because a new visitor is created for each tracked
1811  // expression, hence the BugReport level set.
1812  if (BR.addTrackedCondition(N)) {
1814  N, Condition, BR, bugreporter::TrackingKind::Condition,
1815  /*EnableNullFPSuppression=*/false);
1816  return constructDebugPieceForTrackedCondition(Condition, N, BRC);
1817  }
1818  }
1819  }
1820 
1821  return nullptr;
1822 }
1823 
1824 //===----------------------------------------------------------------------===//
1825 // Implementation of trackExpressionValue.
1826 //===----------------------------------------------------------------------===//
1827 
1828 static const MemRegion *getLocationRegionIfReference(const Expr *E,
1829  const ExplodedNode *N) {
1830  if (const auto *DR = dyn_cast<DeclRefExpr>(E)) {
1831  if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
1832  if (!VD->getType()->isReferenceType())
1833  return nullptr;
1834  ProgramStateManager &StateMgr = N->getState()->getStateManager();
1835  MemRegionManager &MRMgr = StateMgr.getRegionManager();
1836  return MRMgr.getVarRegion(VD, N->getLocationContext());
1837  }
1838  }
1839 
1840  // FIXME: This does not handle other kinds of null references,
1841  // for example, references from FieldRegions:
1842  // struct Wrapper { int &ref; };
1843  // Wrapper w = { *(int *)0 };
1844  // w.ref = 1;
1845 
1846  return nullptr;
1847 }
1848 
1849 /// \return A subexpression of @c Ex which represents the
1850 /// expression-of-interest.
1851 static const Expr *peelOffOuterExpr(const Expr *Ex,
1852  const ExplodedNode *N) {
1853  Ex = Ex->IgnoreParenCasts();
1854  if (const auto *FE = dyn_cast<FullExpr>(Ex))
1855  return peelOffOuterExpr(FE->getSubExpr(), N);
1856  if (const auto *OVE = dyn_cast<OpaqueValueExpr>(Ex))
1857  return peelOffOuterExpr(OVE->getSourceExpr(), N);
1858  if (const auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {
1859  const auto *PropRef = dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
1860  if (PropRef && PropRef->isMessagingGetter()) {
1861  const Expr *GetterMessageSend =
1862  POE->getSemanticExpr(POE->getNumSemanticExprs() - 1);
1863  assert(isa<ObjCMessageExpr>(GetterMessageSend->IgnoreParenCasts()));
1864  return peelOffOuterExpr(GetterMessageSend, N);
1865  }
1866  }
1867 
1868  // Peel off the ternary operator.
1869  if (const auto *CO = dyn_cast<ConditionalOperator>(Ex)) {
1870  // Find a node where the branching occurred and find out which branch
1871  // we took (true/false) by looking at the ExplodedGraph.
1872  const ExplodedNode *NI = N;
1873  do {
1874  ProgramPoint ProgPoint = NI->getLocation();
1875  if (Optional<BlockEdge> BE = ProgPoint.getAs<BlockEdge>()) {
1876  const CFGBlock *srcBlk = BE->getSrc();
1877  if (const Stmt *term = srcBlk->getTerminatorStmt()) {
1878  if (term == CO) {
1879  bool TookTrueBranch = (*(srcBlk->succ_begin()) == BE->getDst());
1880  if (TookTrueBranch)
1881  return peelOffOuterExpr(CO->getTrueExpr(), N);
1882  else
1883  return peelOffOuterExpr(CO->getFalseExpr(), N);
1884  }
1885  }
1886  }
1887  NI = NI->getFirstPred();
1888  } while (NI);
1889  }
1890 
1891  if (auto *BO = dyn_cast<BinaryOperator>(Ex))
1892  if (const Expr *SubEx = peelOffPointerArithmetic(BO))
1893  return peelOffOuterExpr(SubEx, N);
1894 
1895  if (auto *UO = dyn_cast<UnaryOperator>(Ex)) {
1896  if (UO->getOpcode() == UO_LNot)
1897  return peelOffOuterExpr(UO->getSubExpr(), N);
1898 
1899  // FIXME: There's a hack in our Store implementation that always computes
1900  // field offsets around null pointers as if they are always equal to 0.
1901  // The idea here is to report accesses to fields as null dereferences
1902  // even though the pointer value that's being dereferenced is actually
1903  // the offset of the field rather than exactly 0.
1904  // See the FIXME in StoreManager's getLValueFieldOrIvar() method.
1905  // This code interacts heavily with this hack; otherwise the value
1906  // would not be null at all for most fields, so we'd be unable to track it.
1907  if (UO->getOpcode() == UO_AddrOf && UO->getSubExpr()->isLValue())
1908  if (const Expr *DerefEx = bugreporter::getDerefExpr(UO->getSubExpr()))
1909  return peelOffOuterExpr(DerefEx, N);
1910  }
1911 
1912  return Ex;
1913 }
1914 
1915 /// Find the ExplodedNode where the lvalue (the value of 'Ex')
1916 /// was computed.
1917 static const ExplodedNode* findNodeForExpression(const ExplodedNode *N,
1918  const Expr *Inner) {
1919  while (N) {
1920  if (N->getStmtForDiagnostics() == Inner)
1921  return N;
1922  N = N->getFirstPred();
1923  }
1924  return N;
1925 }
1926 
1927 /// Attempts to add visitors to track an RValue expression back to its point of
1928 /// origin. Works similarly to trackExpressionValue, but accepts only RValues.
1929 static void trackRValueExpression(const ExplodedNode *InputNode, const Expr *E,
1930  PathSensitiveBugReport &report,
1932  bool EnableNullFPSuppression) {
1933  assert(E->isRValue() && "The expression is not an rvalue!");
1934  const ExplodedNode *RVNode = findNodeForExpression(InputNode, E);
1935  if (!RVNode)
1936  return;
1937  ProgramStateRef RVState = RVNode->getState();
1938  SVal V = RVState->getSValAsScalarOrLoc(E, RVNode->getLocationContext());
1939  const auto *BO = dyn_cast<BinaryOperator>(E);
1940  if (!BO)
1941  return;
1942  if (!V.isZeroConstant())
1943  return;
1944  if (!BO->isMultiplicativeOp())
1945  return;
1946 
1947  SVal RHSV = RVState->getSVal(BO->getRHS(), RVNode->getLocationContext());
1948  SVal LHSV = RVState->getSVal(BO->getLHS(), RVNode->getLocationContext());
1949 
1950  // Track both LHS and RHS of a multiplication.
1951  if (BO->getOpcode() == BO_Mul) {
1952  if (LHSV.isZeroConstant())
1953  trackExpressionValue(InputNode, BO->getLHS(), report, TKind,
1954  EnableNullFPSuppression);
1955  if (RHSV.isZeroConstant())
1956  trackExpressionValue(InputNode, BO->getRHS(), report, TKind,
1957  EnableNullFPSuppression);
1958  } else { // Track only the LHS of a division or a modulo.
1959  if (LHSV.isZeroConstant())
1960  trackExpressionValue(InputNode, BO->getLHS(), report, TKind,
1961  EnableNullFPSuppression);
1962  }
1963 }
1964 
1965 bool bugreporter::trackExpressionValue(const ExplodedNode *InputNode,
1966  const Expr *E,
1967  PathSensitiveBugReport &report,
1969  bool EnableNullFPSuppression) {
1970 
1971  if (!E || !InputNode)
1972  return false;
1973 
1974  const Expr *Inner = peelOffOuterExpr(E, InputNode);
1975  const ExplodedNode *LVNode = findNodeForExpression(InputNode, Inner);
1976  if (!LVNode)
1977  return false;
1978 
1979  ProgramStateRef LVState = LVNode->getState();
1980  const StackFrameContext *SFC = LVNode->getStackFrame();
1981 
1982  // We only track expressions if we believe that they are important. Chances
1983  // are good that control dependencies to the tracking point are also important
1984  // because of this, let's explain why we believe control reached this point.
1985  // TODO: Shouldn't we track control dependencies of every bug location, rather
1986  // than only tracked expressions?
1987  if (LVState->getAnalysisManager().getAnalyzerOptions().ShouldTrackConditions)
1988  report.addVisitor(std::make_unique<TrackControlDependencyCondBRVisitor>(
1989  InputNode));
1990 
1991  // The message send could be nil due to the receiver being nil.
1992  // At this point in the path, the receiver should be live since we are at the
1993  // message send expr. If it is nil, start tracking it.
1994  if (const Expr *Receiver = NilReceiverBRVisitor::getNilReceiver(Inner, LVNode))
1996  LVNode, Receiver, report, TKind, EnableNullFPSuppression);
1997 
1998  // Track the index if this is an array subscript.
1999  if (const auto *Arr = dyn_cast<ArraySubscriptExpr>(Inner))
2001  LVNode, Arr->getIdx(), report, TKind, /*EnableNullFPSuppression*/false);
2002 
2003  // See if the expression we're interested refers to a variable.
2004  // If so, we can track both its contents and constraints on its value.
2006  SVal LVal = LVNode->getSVal(Inner);
2007 
2008  const MemRegion *RR = getLocationRegionIfReference(Inner, LVNode);
2009  bool LVIsNull = LVState->isNull(LVal).isConstrainedTrue();
2010 
2011  // If this is a C++ reference to a null pointer, we are tracking the
2012  // pointer. In addition, we should find the store at which the reference
2013  // got initialized.
2014  if (RR && !LVIsNull)
2015  if (auto KV = LVal.getAs<KnownSVal>())
2016  report.addVisitor(std::make_unique<FindLastStoreBRVisitor>(
2017  *KV, RR, EnableNullFPSuppression, TKind, SFC));
2018 
2019  // In case of C++ references, we want to differentiate between a null
2020  // reference and reference to null pointer.
2021  // If the LVal is null, check if we are dealing with null reference.
2022  // For those, we want to track the location of the reference.
2023  const MemRegion *R = (RR && LVIsNull) ? RR :
2024  LVNode->getSVal(Inner).getAsRegion();
2025 
2026  if (R) {
2027 
2028  // Mark both the variable region and its contents as interesting.
2029  SVal V = LVState->getRawSVal(loc::MemRegionVal(R));
2030  report.addVisitor(
2031  std::make_unique<NoStoreFuncVisitor>(cast<SubRegion>(R), TKind));
2032 
2033  MacroNullReturnSuppressionVisitor::addMacroVisitorIfNecessary(
2034  LVNode, R, EnableNullFPSuppression, report, V);
2035 
2036  report.markInteresting(V, TKind);
2037  report.addVisitor(std::make_unique<UndefOrNullArgVisitor>(R));
2038 
2039  // If the contents are symbolic and null, find out when they became null.
2040  if (V.getAsLocSymbol(/*IncludeBaseRegions=*/true))
2041  if (LVState->isNull(V).isConstrainedTrue())
2042  report.addVisitor(std::make_unique<TrackConstraintBRVisitor>(
2043  V.castAs<DefinedSVal>(), false));
2044 
2045  // Add visitor, which will suppress inline defensive checks.
2046  if (auto DV = V.getAs<DefinedSVal>())
2047  if (!DV->isZeroConstant() && EnableNullFPSuppression) {
2048  // Note that LVNode may be too late (i.e., too far from the InputNode)
2049  // because the lvalue may have been computed before the inlined call
2050  // was evaluated. InputNode may as well be too early here, because
2051  // the symbol is already dead; this, however, is fine because we can
2052  // still find the node in which it collapsed to null previously.
2053  report.addVisitor(
2054  std::make_unique<SuppressInlineDefensiveChecksVisitor>(
2055  *DV, InputNode));
2056  }
2057 
2058  if (auto KV = V.getAs<KnownSVal>())
2059  report.addVisitor(std::make_unique<FindLastStoreBRVisitor>(
2060  *KV, R, EnableNullFPSuppression, TKind, SFC));
2061  return true;
2062  }
2063  }
2064 
2065  // If the expression is not an "lvalue expression", we can still
2066  // track the constraints on its contents.
2067  SVal V = LVState->getSValAsScalarOrLoc(Inner, LVNode->getLocationContext());
2068 
2069  ReturnVisitor::addVisitorIfNecessary(
2070  LVNode, Inner, report, EnableNullFPSuppression, TKind);
2071 
2072  // Is it a symbolic value?
2073  if (auto L = V.getAs<loc::MemRegionVal>()) {
2074  // FIXME: this is a hack for fixing a later crash when attempting to
2075  // dereference a void* pointer.
2076  // We should not try to dereference pointers at all when we don't care
2077  // what is written inside the pointer.
2078  bool CanDereference = true;
2079  if (const auto *SR = L->getRegionAs<SymbolicRegion>()) {
2080  if (SR->getSymbol()->getType()->getPointeeType()->isVoidType())
2081  CanDereference = false;
2082  } else if (L->getRegionAs<AllocaRegion>())
2083  CanDereference = false;
2084 
2085  // At this point we are dealing with the region's LValue.
2086  // However, if the rvalue is a symbolic region, we should track it as well.
2087  // Try to use the correct type when looking up the value.
2088  SVal RVal;
2090  RVal = LVState->getRawSVal(L.getValue(), Inner->getType());
2091  else if (CanDereference)
2092  RVal = LVState->getSVal(L->getRegion());
2093 
2094  if (CanDereference) {
2095  report.addVisitor(
2096  std::make_unique<UndefOrNullArgVisitor>(L->getRegion()));
2097 
2098  if (auto KV = RVal.getAs<KnownSVal>())
2099  report.addVisitor(std::make_unique<FindLastStoreBRVisitor>(
2100  *KV, L->getRegion(), EnableNullFPSuppression, TKind, SFC));
2101  }
2102 
2103  const MemRegion *RegionRVal = RVal.getAsRegion();
2104  if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) {
2105  report.markInteresting(RegionRVal, TKind);
2106  report.addVisitor(std::make_unique<TrackConstraintBRVisitor>(
2107  loc::MemRegionVal(RegionRVal), /*assumption=*/false));
2108  }
2109  }
2110 
2111  if (Inner->isRValue())
2112  trackRValueExpression(LVNode, Inner, report, TKind,
2113  EnableNullFPSuppression);
2114 
2115  return true;
2116 }
2117 
2118 //===----------------------------------------------------------------------===//
2119 // Implementation of NulReceiverBRVisitor.
2120 //===----------------------------------------------------------------------===//
2121 
2123  const ExplodedNode *N) {
2124  const auto *ME = dyn_cast<ObjCMessageExpr>(S);
2125  if (!ME)
2126  return nullptr;
2127  if (const Expr *Receiver = ME->getInstanceReceiver()) {
2129  SVal V = N->getSVal(Receiver);
2130  if (state->isNull(V).isConstrainedTrue())
2131  return Receiver;
2132  }
2133  return nullptr;
2134 }
2135 
2138  PathSensitiveBugReport &BR) {
2140  if (!P)
2141  return nullptr;
2142 
2143  const Stmt *S = P->getStmt();
2144  const Expr *Receiver = getNilReceiver(S, N);
2145  if (!Receiver)
2146  return nullptr;
2147 
2149  llvm::raw_svector_ostream OS(Buf);
2150 
2151  if (const auto *ME = dyn_cast<ObjCMessageExpr>(S)) {
2152  OS << "'";
2153  ME->getSelector().print(OS);
2154  OS << "' not called";
2155  }
2156  else {
2157  OS << "No method is called";
2158  }
2159  OS << " because the receiver is nil";
2160 
2161  // The receiver was nil, and hence the method was skipped.
2162  // Register a BugReporterVisitor to issue a message telling us how
2163  // the receiver was null.
2165  N, Receiver, BR, bugreporter::TrackingKind::Thorough,
2166  /*EnableNullFPSuppression*/ false);
2167  // Issue a message saying that the method was skipped.
2168  PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
2169  N->getLocationContext());
2170  return std::make_shared<PathDiagnosticEventPiece>(L, OS.str());
2171 }
2172 
2173 //===----------------------------------------------------------------------===//
2174 // Visitor that tries to report interesting diagnostics from conditions.
2175 //===----------------------------------------------------------------------===//
2176 
2177 /// Return the tag associated with this visitor. This tag will be used
2178 /// to make all PathDiagnosticPieces created by this visitor.
2179 const char *ConditionBRVisitor::getTag() { return "ConditionBRVisitor"; }
2180 
2183  PathSensitiveBugReport &BR) {
2184  auto piece = VisitNodeImpl(N, BRC, BR);
2185  if (piece) {
2186  piece->setTag(getTag());
2187  if (auto *ev = dyn_cast<PathDiagnosticEventPiece>(piece.get()))
2188  ev->setPrunable(true, /* override */ false);
2189  }
2190  return piece;
2191 }
2192 
2195  BugReporterContext &BRC,
2196  PathSensitiveBugReport &BR) {
2197  ProgramPoint ProgPoint = N->getLocation();
2198  const std::pair<const ProgramPointTag *, const ProgramPointTag *> &Tags =
2200 
2201  // If an assumption was made on a branch, it should be caught
2202  // here by looking at the state transition.
2203  if (Optional<BlockEdge> BE = ProgPoint.getAs<BlockEdge>()) {
2204  const CFGBlock *SrcBlock = BE->getSrc();
2205  if (const Stmt *Term = SrcBlock->getTerminatorStmt()) {
2206  // If the tag of the previous node is 'Eagerly Assume...' the current
2207  // 'BlockEdge' has the same constraint information. We do not want to
2208  // report the value as it is just an assumption on the predecessor node
2209  // which will be caught in the next VisitNode() iteration as a 'PostStmt'.
2210  const ProgramPointTag *PreviousNodeTag =
2211  N->getFirstPred()->getLocation().getTag();
2212  if (PreviousNodeTag == Tags.first || PreviousNodeTag == Tags.second)
2213  return nullptr;
2214 
2215  return VisitTerminator(Term, N, SrcBlock, BE->getDst(), BR, BRC);
2216  }
2217  return nullptr;
2218  }
2219 
2220  if (Optional<PostStmt> PS = ProgPoint.getAs<PostStmt>()) {
2221  const ProgramPointTag *CurrentNodeTag = PS->getTag();
2222  if (CurrentNodeTag != Tags.first && CurrentNodeTag != Tags.second)
2223  return nullptr;
2224 
2225  bool TookTrue = CurrentNodeTag == Tags.first;
2226  return VisitTrueTest(cast<Expr>(PS->getStmt()), BRC, BR, N, TookTrue);
2227  }
2228 
2229  return nullptr;
2230 }
2231 
2233  const Stmt *Term, const ExplodedNode *N, const CFGBlock *srcBlk,
2234  const CFGBlock *dstBlk, PathSensitiveBugReport &R,
2235  BugReporterContext &BRC) {
2236  const Expr *Cond = nullptr;
2237 
2238  // In the code below, Term is a CFG terminator and Cond is a branch condition
2239  // expression upon which the decision is made on this terminator.
2240  //
2241  // For example, in "if (x == 0)", the "if (x == 0)" statement is a terminator,
2242  // and "x == 0" is the respective condition.
2243  //
2244  // Another example: in "if (x && y)", we've got two terminators and two
2245  // conditions due to short-circuit nature of operator "&&":
2246  // 1. The "if (x && y)" statement is a terminator,
2247  // and "y" is the respective condition.
2248  // 2. Also "x && ..." is another terminator,
2249  // and "x" is its condition.
2250 
2251  switch (Term->getStmtClass()) {
2252  // FIXME: Stmt::SwitchStmtClass is worth handling, however it is a bit
2253  // more tricky because there are more than two branches to account for.
2254  default:
2255  return nullptr;
2256  case Stmt::IfStmtClass:
2257  Cond = cast<IfStmt>(Term)->getCond();
2258  break;
2259  case Stmt::ConditionalOperatorClass:
2260  Cond = cast<ConditionalOperator>(Term)->getCond();
2261  break;
2262  case Stmt::BinaryOperatorClass:
2263  // When we encounter a logical operator (&& or ||) as a CFG terminator,
2264  // then the condition is actually its LHS; otherwise, we'd encounter
2265  // the parent, such as if-statement, as a terminator.
2266  const auto *BO = cast<BinaryOperator>(Term);
2267  assert(BO->isLogicalOp() &&
2268  "CFG terminator is not a short-circuit operator!");
2269  Cond = BO->getLHS();
2270  break;
2271  }
2272 
2273  Cond = Cond->IgnoreParens();
2274 
2275  // However, when we encounter a logical operator as a branch condition,
2276  // then the condition is actually its RHS, because LHS would be
2277  // the condition for the logical operator terminator.
2278  while (const auto *InnerBO = dyn_cast<BinaryOperator>(Cond)) {
2279  if (!InnerBO->isLogicalOp())
2280  break;
2281  Cond = InnerBO->getRHS()->IgnoreParens();
2282  }
2283 
2284  assert(Cond);
2285  assert(srcBlk->succ_size() == 2);
2286  const bool TookTrue = *(srcBlk->succ_begin()) == dstBlk;
2287  return VisitTrueTest(Cond, BRC, R, N, TookTrue);
2288 }
2289 
2293  const ExplodedNode *N, bool TookTrue) {
2294  ProgramStateRef CurrentState = N->getState();
2295  ProgramStateRef PrevState = N->getFirstPred()->getState();
2296  const LocationContext *LCtx = N->getLocationContext();
2297 
2298  // If the constraint information is changed between the current and the
2299  // previous program state we assuming the newly seen constraint information.
2300  // If we cannot evaluate the condition (and the constraints are the same)
2301  // the analyzer has no information about the value and just assuming it.
2302  bool IsAssuming =
2303  !BRC.getStateManager().haveEqualConstraints(CurrentState, PrevState) ||
2304  CurrentState->getSVal(Cond, LCtx).isUnknownOrUndef();
2305 
2306  // These will be modified in code below, but we need to preserve the original
2307  // values in case we want to throw the generic message.
2308  const Expr *CondTmp = Cond;
2309  bool TookTrueTmp = TookTrue;
2310 
2311  while (true) {
2312  CondTmp = CondTmp->IgnoreParenCasts();
2313  switch (CondTmp->getStmtClass()) {
2314  default:
2315  break;
2316  case Stmt::BinaryOperatorClass:
2317  if (auto P = VisitTrueTest(Cond, cast<BinaryOperator>(CondTmp),
2318  BRC, R, N, TookTrueTmp, IsAssuming))
2319  return P;
2320  break;
2321  case Stmt::DeclRefExprClass:
2322  if (auto P = VisitTrueTest(Cond, cast<DeclRefExpr>(CondTmp),
2323  BRC, R, N, TookTrueTmp, IsAssuming))
2324  return P;
2325  break;
2326  case Stmt::MemberExprClass:
2327  if (auto P = VisitTrueTest(Cond, cast<MemberExpr>(CondTmp),
2328  BRC, R, N, TookTrueTmp, IsAssuming))
2329  return P;
2330  break;
2331  case Stmt::UnaryOperatorClass: {
2332  const auto *UO = cast<UnaryOperator>(CondTmp);
2333  if (UO->getOpcode() == UO_LNot) {
2334  TookTrueTmp = !TookTrueTmp;
2335  CondTmp = UO->getSubExpr();
2336  continue;
2337  }
2338  break;
2339  }
2340  }
2341  break;
2342  }
2343 
2344  // Condition too complex to explain? Just say something so that the user
2345  // knew we've made some path decision at this point.
2346  // If it is too complex and we know the evaluation of the condition do not
2347  // repeat the note from 'BugReporter.cpp'
2348  if (!IsAssuming)
2349  return nullptr;
2350 
2351  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
2352  if (!Loc.isValid() || !Loc.asLocation().isValid())
2353  return nullptr;
2354 
2355  return std::make_shared<PathDiagnosticEventPiece>(
2356  Loc, TookTrue ? GenericTrueMessage : GenericFalseMessage);
2357 }
2358 
2360  const Expr *ParentEx,
2361  raw_ostream &Out,
2362  BugReporterContext &BRC,
2363  PathSensitiveBugReport &report,
2364  const ExplodedNode *N,
2365  Optional<bool> &prunable,
2366  bool IsSameFieldName) {
2367  const Expr *OriginalExpr = Ex;
2368  Ex = Ex->IgnoreParenCasts();
2369 
2370  if (isa<GNUNullExpr>(Ex) || isa<ObjCBoolLiteralExpr>(Ex) ||
2371  isa<CXXBoolLiteralExpr>(Ex) || isa<IntegerLiteral>(Ex) ||
2372  isa<FloatingLiteral>(Ex)) {
2373  // Use heuristics to determine if the expression is a macro
2374  // expanding to a literal and if so, use the macro's name.
2375  SourceLocation BeginLoc = OriginalExpr->getBeginLoc();
2376  SourceLocation EndLoc = OriginalExpr->getEndLoc();
2377  if (BeginLoc.isMacroID() && EndLoc.isMacroID()) {
2378  const SourceManager &SM = BRC.getSourceManager();
2379  const LangOptions &LO = BRC.getASTContext().getLangOpts();
2380  if (Lexer::isAtStartOfMacroExpansion(BeginLoc, SM, LO) &&
2381  Lexer::isAtEndOfMacroExpansion(EndLoc, SM, LO)) {
2382  CharSourceRange R = Lexer::getAsCharRange({BeginLoc, EndLoc}, SM, LO);
2383  Out << Lexer::getSourceText(R, SM, LO);
2384  return false;
2385  }
2386  }
2387  }
2388 
2389  if (const auto *DR = dyn_cast<DeclRefExpr>(Ex)) {
2390  const bool quotes = isa<VarDecl>(DR->getDecl());
2391  if (quotes) {
2392  Out << '\'';
2393  const LocationContext *LCtx = N->getLocationContext();
2394  const ProgramState *state = N->getState().get();
2395  if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()),
2396  LCtx).getAsRegion()) {
2397  if (report.isInteresting(R))
2398  prunable = false;
2399  else {
2400  const ProgramState *state = N->getState().get();
2401  SVal V = state->getSVal(R);
2402  if (report.isInteresting(V))
2403  prunable = false;
2404  }
2405  }
2406  }
2407  Out << DR->getDecl()->getDeclName().getAsString();
2408  if (quotes)
2409  Out << '\'';
2410  return quotes;
2411  }
2412 
2413  if (const auto *IL = dyn_cast<IntegerLiteral>(Ex)) {
2414  QualType OriginalTy = OriginalExpr->getType();
2415  if (OriginalTy->isPointerType()) {
2416  if (IL->getValue() == 0) {
2417  Out << "null";
2418  return false;
2419  }
2420  }
2421  else if (OriginalTy->isObjCObjectPointerType()) {
2422  if (IL->getValue() == 0) {
2423  Out << "nil";
2424  return false;
2425  }
2426  }
2427 
2428  Out << IL->getValue();
2429  return false;
2430  }
2431 
2432  if (const auto *ME = dyn_cast<MemberExpr>(Ex)) {
2433  if (!IsSameFieldName)
2434  Out << "field '" << ME->getMemberDecl()->getName() << '\'';
2435  else
2436  Out << '\''
2439  BRC.getSourceManager(), BRC.getASTContext().getLangOpts(), 0)
2440  << '\'';
2441  }
2442 
2443  return false;
2444 }
2445 
2447  const Expr *Cond, const BinaryOperator *BExpr, BugReporterContext &BRC,
2448  PathSensitiveBugReport &R, const ExplodedNode *N, bool TookTrue,
2449  bool IsAssuming) {
2450  bool shouldInvert = false;
2451  Optional<bool> shouldPrune;
2452 
2453  // Check if the field name of the MemberExprs is ambiguous. Example:
2454  // " 'a.d' is equal to 'h.d' " in 'test/Analysis/null-deref-path-notes.cpp'.
2455  bool IsSameFieldName = false;
2456  const auto *LhsME = dyn_cast<MemberExpr>(BExpr->getLHS()->IgnoreParenCasts());
2457  const auto *RhsME = dyn_cast<MemberExpr>(BExpr->getRHS()->IgnoreParenCasts());
2458 
2459  if (LhsME && RhsME)
2460  IsSameFieldName =
2461  LhsME->getMemberDecl()->getName() == RhsME->getMemberDecl()->getName();
2462 
2463  SmallString<128> LhsString, RhsString;
2464  {
2465  llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
2466  const bool isVarLHS = patternMatch(BExpr->getLHS(), BExpr, OutLHS, BRC, R,
2467  N, shouldPrune, IsSameFieldName);
2468  const bool isVarRHS = patternMatch(BExpr->getRHS(), BExpr, OutRHS, BRC, R,
2469  N, shouldPrune, IsSameFieldName);
2470 
2471  shouldInvert = !isVarLHS && isVarRHS;
2472  }
2473 
2474  BinaryOperator::Opcode Op = BExpr->getOpcode();
2475 
2477  // For assignment operators, all that we care about is that the LHS
2478  // evaluates to "true" or "false".
2479  return VisitConditionVariable(LhsString, BExpr->getLHS(), BRC, R, N,
2480  TookTrue);
2481  }
2482 
2483  // For non-assignment operations, we require that we can understand
2484  // both the LHS and RHS.
2485  if (LhsString.empty() || RhsString.empty() ||
2486  !BinaryOperator::isComparisonOp(Op) || Op == BO_Cmp)
2487  return nullptr;
2488 
2489  // Should we invert the strings if the LHS is not a variable name?
2490  SmallString<256> buf;
2491  llvm::raw_svector_ostream Out(buf);
2492  Out << (IsAssuming ? "Assuming " : "")
2493  << (shouldInvert ? RhsString : LhsString) << " is ";
2494 
2495  // Do we need to invert the opcode?
2496  if (shouldInvert)
2497  switch (Op) {
2498  default: break;
2499  case BO_LT: Op = BO_GT; break;
2500  case BO_GT: Op = BO_LT; break;
2501  case BO_LE: Op = BO_GE; break;
2502  case BO_GE: Op = BO_LE; break;
2503  }
2504 
2505  if (!TookTrue)
2506  switch (Op) {
2507  case BO_EQ: Op = BO_NE; break;
2508  case BO_NE: Op = BO_EQ; break;
2509  case BO_LT: Op = BO_GE; break;
2510  case BO_GT: Op = BO_LE; break;
2511  case BO_LE: Op = BO_GT; break;
2512  case BO_GE: Op = BO_LT; break;
2513  default:
2514  return nullptr;
2515  }
2516 
2517  switch (Op) {
2518  case BO_EQ:
2519  Out << "equal to ";
2520  break;
2521  case BO_NE:
2522  Out << "not equal to ";
2523  break;
2524  default:
2525  Out << BinaryOperator::getOpcodeStr(Op) << ' ';
2526  break;
2527  }
2528 
2529  Out << (shouldInvert ? LhsString : RhsString);
2530  const LocationContext *LCtx = N->getLocationContext();
2531  const SourceManager &SM = BRC.getSourceManager();
2532 
2533  if (isVarAnInterestingCondition(BExpr->getLHS(), N, &R) ||
2534  isVarAnInterestingCondition(BExpr->getRHS(), N, &R))
2535  Out << WillBeUsedForACondition;
2536 
2537  // Convert 'field ...' to 'Field ...' if it is a MemberExpr.
2538  std::string Message = std::string(Out.str());
2539  Message[0] = toupper(Message[0]);
2540 
2541  // If we know the value create a pop-up note to the value part of 'BExpr'.
2542  if (!IsAssuming) {
2544  if (!shouldInvert) {
2545  if (LhsME && LhsME->getMemberLoc().isValid())
2546  Loc = PathDiagnosticLocation(LhsME->getMemberLoc(), SM);
2547  else
2548  Loc = PathDiagnosticLocation(BExpr->getLHS(), SM, LCtx);
2549  } else {
2550  if (RhsME && RhsME->getMemberLoc().isValid())
2551  Loc = PathDiagnosticLocation(RhsME->getMemberLoc(), SM);
2552  else
2553  Loc = PathDiagnosticLocation(BExpr->getRHS(), SM, LCtx);
2554  }
2555 
2556  return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Message);
2557  }
2558 
2559  PathDiagnosticLocation Loc(Cond, SM, LCtx);
2560  auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Message);
2561  if (shouldPrune.hasValue())
2562  event->setPrunable(shouldPrune.getValue());
2563  return event;
2564 }
2565 
2567  StringRef LhsString, const Expr *CondVarExpr, BugReporterContext &BRC,
2568  PathSensitiveBugReport &report, const ExplodedNode *N, bool TookTrue) {
2569  // FIXME: If there's already a constraint tracker for this variable,
2570  // we shouldn't emit anything here (c.f. the double note in
2571  // test/Analysis/inlining/path-notes.c)
2572  SmallString<256> buf;
2573  llvm::raw_svector_ostream Out(buf);
2574  Out << "Assuming " << LhsString << " is ";
2575 
2576  if (!printValue(CondVarExpr, Out, N, TookTrue, /*IsAssuming=*/true))
2577  return nullptr;
2578 
2579  const LocationContext *LCtx = N->getLocationContext();
2580  PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
2581 
2582  if (isVarAnInterestingCondition(CondVarExpr, N, &report))
2583  Out << WillBeUsedForACondition;
2584 
2585  auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2586 
2587  if (isInterestingExpr(CondVarExpr, N, &report))
2588  event->setPrunable(false);
2589 
2590  return event;
2591 }
2592 
2594  const Expr *Cond, const DeclRefExpr *DRE, BugReporterContext &BRC,
2595  PathSensitiveBugReport &report, const ExplodedNode *N, bool TookTrue,
2596  bool IsAssuming) {
2597  const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
2598  if (!VD)
2599  return nullptr;
2600 
2601  SmallString<256> Buf;
2602  llvm::raw_svector_ostream Out(Buf);
2603 
2604  Out << (IsAssuming ? "Assuming '" : "'") << VD->getDeclName() << "' is ";
2605 
2606  if (!printValue(DRE, Out, N, TookTrue, IsAssuming))
2607  return nullptr;
2608 
2609  const LocationContext *LCtx = N->getLocationContext();
2610 
2611  if (isVarAnInterestingCondition(DRE, N, &report))
2612  Out << WillBeUsedForACondition;
2613 
2614  // If we know the value create a pop-up note to the 'DRE'.
2615  if (!IsAssuming) {
2616  PathDiagnosticLocation Loc(DRE, BRC.getSourceManager(), LCtx);
2617  return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Out.str());
2618  }
2619 
2620  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
2621  auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2622 
2623  if (isInterestingExpr(DRE, N, &report))
2624  event->setPrunable(false);
2625 
2626  return std::move(event);
2627 }
2628 
2630  const Expr *Cond, const MemberExpr *ME, BugReporterContext &BRC,
2631  PathSensitiveBugReport &report, const ExplodedNode *N, bool TookTrue,
2632  bool IsAssuming) {
2633  SmallString<256> Buf;
2634  llvm::raw_svector_ostream Out(Buf);
2635 
2636  Out << (IsAssuming ? "Assuming field '" : "Field '")
2637  << ME->getMemberDecl()->getName() << "' is ";
2638 
2639  if (!printValue(ME, Out, N, TookTrue, IsAssuming))
2640  return nullptr;
2641 
2642  const LocationContext *LCtx = N->getLocationContext();
2643  PathDiagnosticLocation Loc;
2644 
2645  // If we know the value create a pop-up note to the member of the MemberExpr.
2646  if (!IsAssuming && ME->getMemberLoc().isValid())
2647  Loc = PathDiagnosticLocation(ME->getMemberLoc(), BRC.getSourceManager());
2648  else
2649  Loc = PathDiagnosticLocation(Cond, BRC.getSourceManager(), LCtx);
2650 
2651  if (!Loc.isValid() || !Loc.asLocation().isValid())
2652  return nullptr;
2653 
2654  if (isVarAnInterestingCondition(ME, N, &report))
2655  Out << WillBeUsedForACondition;
2656 
2657  // If we know the value create a pop-up note.
2658  if (!IsAssuming)
2659  return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Out.str());
2660 
2661  auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2662  if (isInterestingExpr(ME, N, &report))
2663  event->setPrunable(false);
2664  return event;
2665 }
2666 
2667 bool ConditionBRVisitor::printValue(const Expr *CondVarExpr, raw_ostream &Out,
2668  const ExplodedNode *N, bool TookTrue,
2669  bool IsAssuming) {
2670  QualType Ty = CondVarExpr->getType();
2671 
2672  if (Ty->isPointerType()) {
2673  Out << (TookTrue ? "non-null" : "null");
2674  return true;
2675  }
2676 
2677  if (Ty->isObjCObjectPointerType()) {
2678  Out << (TookTrue ? "non-nil" : "nil");
2679  return true;
2680  }
2681 
2682  if (!Ty->isIntegralOrEnumerationType())
2683  return false;
2684 
2686  if (!IsAssuming)
2687  IntValue = getConcreteIntegerValue(CondVarExpr, N);
2688 
2689  if (IsAssuming || !IntValue.hasValue()) {
2690  if (Ty->isBooleanType())
2691  Out << (TookTrue ? "true" : "false");
2692  else
2693  Out << (TookTrue ? "not equal to 0" : "0");
2694  } else {
2695  if (Ty->isBooleanType())
2696  Out << (IntValue.getValue()->getBoolValue() ? "true" : "false");
2697  else
2698  Out << *IntValue.getValue();
2699  }
2700 
2701  return true;
2702 }
2703 
2704 constexpr llvm::StringLiteral ConditionBRVisitor::GenericTrueMessage;
2705 constexpr llvm::StringLiteral ConditionBRVisitor::GenericFalseMessage;
2706 
2708  const PathDiagnosticPiece *Piece) {
2709  return Piece->getString() == GenericTrueMessage ||
2710  Piece->getString() == GenericFalseMessage;
2711 }
2712 
2713 //===----------------------------------------------------------------------===//
2714 // Implementation of LikelyFalsePositiveSuppressionBRVisitor.
2715 //===----------------------------------------------------------------------===//
2716 
2718  BugReporterContext &BRC, const ExplodedNode *N,
2719  PathSensitiveBugReport &BR) {
2720  // Here we suppress false positives coming from system headers. This list is
2721  // based on known issues.
2722  const AnalyzerOptions &Options = BRC.getAnalyzerOptions();
2723  const Decl *D = N->getLocationContext()->getDecl();
2724 
2726  // Skip reports within the 'std' namespace. Although these can sometimes be
2727  // the user's fault, we currently don't report them very well, and
2728  // Note that this will not help for any other data structure libraries, like
2729  // TR1, Boost, or llvm/ADT.
2730  if (Options.ShouldSuppressFromCXXStandardLibrary) {
2731  BR.markInvalid(getTag(), nullptr);
2732  return;
2733  } else {
2734  // If the complete 'std' suppression is not enabled, suppress reports
2735  // from the 'std' namespace that are known to produce false positives.
2736 
2737  // The analyzer issues a false use-after-free when std::list::pop_front
2738  // or std::list::pop_back are called multiple times because we cannot
2739  // reason about the internal invariants of the data structure.
2740  if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
2741  const CXXRecordDecl *CD = MD->getParent();
2742  if (CD->getName() == "list") {
2743  BR.markInvalid(getTag(), nullptr);
2744  return;
2745  }
2746  }
2747 
2748  // The analyzer issues a false positive when the constructor of
2749  // std::__independent_bits_engine from algorithms is used.
2750  if (const auto *MD = dyn_cast<CXXConstructorDecl>(D)) {
2751  const CXXRecordDecl *CD = MD->getParent();
2752  if (CD->getName() == "__independent_bits_engine") {
2753  BR.markInvalid(getTag(), nullptr);
2754  return;
2755  }
2756  }
2757 
2758  for (const LocationContext *LCtx = N->getLocationContext(); LCtx;
2759  LCtx = LCtx->getParent()) {
2760  const auto *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
2761  if (!MD)
2762  continue;
2763 
2764  const CXXRecordDecl *CD = MD->getParent();
2765  // The analyzer issues a false positive on
2766  // std::basic_string<uint8_t> v; v.push_back(1);
2767  // and
2768  // std::u16string s; s += u'a';
2769  // because we cannot reason about the internal invariants of the
2770  // data structure.
2771  if (CD->getName() == "basic_string") {
2772  BR.markInvalid(getTag(), nullptr);
2773  return;
2774  }
2775 
2776  // The analyzer issues a false positive on
2777  // std::shared_ptr<int> p(new int(1)); p = nullptr;
2778  // because it does not reason properly about temporary destructors.
2779  if (CD->getName() == "shared_ptr") {
2780  BR.markInvalid(getTag(), nullptr);
2781  return;
2782  }
2783  }
2784  }
2785  }
2786 
2787  // Skip reports within the sys/queue.h macros as we do not have the ability to
2788  // reason about data structure shapes.
2789  const SourceManager &SM = BRC.getSourceManager();
2791  while (Loc.isMacroID()) {
2792  Loc = Loc.getSpellingLoc();
2793  if (SM.getFilename(Loc).endswith("sys/queue.h")) {
2794  BR.markInvalid(getTag(), nullptr);
2795  return;
2796  }
2797  }
2798 }
2799 
2800 //===----------------------------------------------------------------------===//
2801 // Implementation of UndefOrNullArgVisitor.
2802 //===----------------------------------------------------------------------===//
2803 
2806  PathSensitiveBugReport &BR) {
2808  ProgramPoint ProgLoc = N->getLocation();
2809 
2810  // We are only interested in visiting CallEnter nodes.
2811  Optional<CallEnter> CEnter = ProgLoc.getAs<CallEnter>();
2812  if (!CEnter)
2813  return nullptr;
2814 
2815  // Check if one of the arguments is the region the visitor is tracking.
2817  CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State);
2818  unsigned Idx = 0;
2819  ArrayRef<ParmVarDecl *> parms = Call->parameters();
2820 
2821  for (const auto ParamDecl : parms) {
2822  const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion();
2823  ++Idx;
2824 
2825  // Are we tracking the argument or its subregion?
2826  if ( !ArgReg || !R->isSubRegionOf(ArgReg->StripCasts()))
2827  continue;
2828 
2829  // Check the function parameter type.
2830  assert(ParamDecl && "Formal parameter has no decl?");
2831  QualType T = ParamDecl->getType();
2832 
2833  if (!(T->isAnyPointerType() || T->isReferenceType())) {
2834  // Function can only change the value passed in by address.
2835  continue;
2836  }
2837 
2838  // If it is a const pointer value, the function does not intend to
2839  // change the value.
2840  if (T->getPointeeType().isConstQualified())
2841  continue;
2842 
2843  // Mark the call site (LocationContext) as interesting if the value of the
2844  // argument is undefined or '0'/'NULL'.
2845  SVal BoundVal = State->getSVal(R);
2846  if (BoundVal.isUndef() || BoundVal.isZeroConstant()) {
2847  BR.markInteresting(CEnter->getCalleeContext());
2848  return nullptr;
2849  }
2850  }
2851  return nullptr;
2852 }
2853 
2854 //===----------------------------------------------------------------------===//
2855 // Implementation of FalsePositiveRefutationBRVisitor.
2856 //===----------------------------------------------------------------------===//
2857 
2859  : Constraints(ConstraintMap::Factory().getEmptyMap()) {}
2860 
2862  BugReporterContext &BRC, const ExplodedNode *EndPathNode,
2863  PathSensitiveBugReport &BR) {
2864  // Collect new constraints
2865  addConstraints(EndPathNode, /*OverwriteConstraintsOnExistingSyms=*/true);
2866 
2867  // Create a refutation manager
2868  llvm::SMTSolverRef RefutationSolver = llvm::CreateZ3Solver();
2869  ASTContext &Ctx = BRC.getASTContext();
2870 
2871  // Add constraints to the solver
2872  for (const auto &I : Constraints) {
2873  const SymbolRef Sym = I.first;
2874  auto RangeIt = I.second.begin();
2875 
2876  llvm::SMTExprRef SMTConstraints = SMTConv::getRangeExpr(
2877  RefutationSolver, Ctx, Sym, RangeIt->From(), RangeIt->To(),
2878  /*InRange=*/true);
2879  while ((++RangeIt) != I.second.end()) {
2880  SMTConstraints = RefutationSolver->mkOr(
2881  SMTConstraints, SMTConv::getRangeExpr(RefutationSolver, Ctx, Sym,
2882  RangeIt->From(), RangeIt->To(),
2883  /*InRange=*/true));
2884  }
2885 
2886  RefutationSolver->addConstraint(SMTConstraints);
2887  }
2888 
2889  // And check for satisfiability
2890  Optional<bool> IsSAT = RefutationSolver->check();
2891  if (!IsSAT.hasValue())
2892  return;
2893 
2894  if (!IsSAT.getValue())
2895  BR.markInvalid("Infeasible constraints", EndPathNode->getLocationContext());
2896 }
2897 
2899  const ExplodedNode *N, bool OverwriteConstraintsOnExistingSyms) {
2900  // Collect new constraints
2901  ConstraintMap NewCs = getConstraintMap(N->getState());
2902  ConstraintMap::Factory &CF = N->getState()->get_context<ConstraintMap>();
2903 
2904  // Add constraints if we don't have them yet
2905  for (auto const &C : NewCs) {
2906  const SymbolRef &Sym = C.first;
2907  if (!Constraints.contains(Sym)) {
2908  // This symbol is new, just add the constraint.
2909  Constraints = CF.add(Constraints, Sym, C.second);
2910  } else if (OverwriteConstraintsOnExistingSyms) {
2911  // Overwrite the associated constraint of the Symbol.
2912  Constraints = CF.remove(Constraints, Sym);
2913  Constraints = CF.add(Constraints, Sym, C.second);
2914  }
2915  }
2916 }
2917 
2920  addConstraints(N, /*OverwriteConstraintsOnExistingSyms=*/false);
2921  return nullptr;
2922 }
2923 
2925  llvm::FoldingSetNodeID &ID) const {
2926  static int Tag = 0;
2927  ID.AddPointer(&Tag);
2928 }
2929 
2930 //===----------------------------------------------------------------------===//
2931 // Implementation of TagVisitor.
2932 //===----------------------------------------------------------------------===//
2933 
2934 int NoteTag::Kind = 0;
2935 
2936 void TagVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
2937  static int Tag = 0;
2938  ID.AddPointer(&Tag);
2939 }
2940 
2942  BugReporterContext &BRC,
2944  ProgramPoint PP = N->getLocation();
2945  const NoteTag *T = dyn_cast_or_null<NoteTag>(PP.getTag());
2946  if (!T)
2947  return nullptr;
2948 
2949  if (Optional<std::string> Msg = T->generateMessage(BRC, R)) {
2952  auto Piece = std::make_shared<PathDiagnosticEventPiece>(Loc, *Msg);
2953  Piece->setPrunable(T->isPrunable());
2954  return Piece;
2955  }
2956 
2957  return nullptr;
2958 }
clang::AnalysisDeclContext::getCFGStmtMap
CFGStmtMap * getCFGStmtMap()
Definition: AnalysisDeclContext.cpp:251
clang::CallExitBegin
Represents a point when we start the call exit sequence (for inlined call).
Definition: ProgramPoint.h:668
clang::ento::bugreporter::trackExpressionValue
bool trackExpressionValue(const ExplodedNode *N, const Expr *E, PathSensitiveBugReport &R, TrackingKind TKind=TrackingKind::Thorough, bool EnableNullFPSuppression=true)
Attempts to add visitors to track expression value back to its point of origin.
clang::Lexer::isAtEndOfMacroExpansion
static bool isAtEndOfMacroExpansion(SourceLocation loc, const SourceManager &SM, const LangOptions &LangOpts, SourceLocation *MacroEnd=nullptr)
Returns true if the given MacroID location points at the last token of the macro expansion.
Definition: Lexer.cpp:825
clang::ento::ProgramStateManager::haveEqualConstraints
bool haveEqualConstraints(ProgramStateRef S1, ProgramStateRef S2) const
Definition: ProgramState.h:568
AnalyzerOptions.h
clang::ento::PathSensitiveBugReport::addVisitor
void addVisitor(std::unique_ptr< BugReporterVisitor > visitor)
Add custom or predefined bug report visitors to this report.
Definition: BugReporter.cpp:2157
clang::ast_matchers::StatementMatcher
internal::Matcher< Stmt > StatementMatcher
Definition: ASTMatchers.h:142
clang::ento::PathDiagnosticLocation
Definition: PathDiagnostic.h:196
clang::ento::ObjKind::CF
@ CF
Indicates that the tracked object is a CF object.
getSValForVar
static Optional< SVal > getSValForVar(const Expr *CondVarExpr, const ExplodedNode *N)
Definition: BugReporterVisitors.cpp:182
clang::ento::ExplodedNode::getLocationContext
const LocationContext * getLocationContext() const
Definition: ExplodedGraph.h:146
hasVisibleUpdate
static bool hasVisibleUpdate(const ExplodedNode *LeftNode, SVal LeftVal, const ExplodedNode *RightNode, SVal RightVal)
Comparing internal representations of symbolic values (via SVal::operator==()) is a valid way to chec...
Definition: BugReporterVisitors.cpp:164
getConcreteIntegerValue
static Optional< const llvm::APSInt * > getConcreteIntegerValue(const Expr *CondVarExpr, const ExplodedNode *N)
Definition: BugReporterVisitors.cpp:207
clang::ento::CallEventRef
Definition: CallEvent.h:82
clang::LocationContext
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
Definition: AnalysisDeclContext.h:213
clang::LocationContext::getStackFrame
const StackFrameContext * getStackFrame() const
Definition: AnalysisDeclContext.cpp:410
SVals.h
clang::FullSourceLoc
A SourceLocation and its associated SourceManager.
Definition: SourceLocation.h:366
clang::ento::TrackConstraintBRVisitor::VisitNode
PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
Definition: BugReporterVisitors.cpp:1545
clang::SourceRange
A trivial tuple used to represent a source range.
Definition: SourceLocation.h:212
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
Ret
static bool Ret(InterpState &S, CodePtr &PC, APValue &Result)
Definition: Interp.cpp:34
clang::ento::NoteTag::isPrunable
bool isPrunable() const
Definition: BugReporter.h:762
clang::ast_matchers::stmt
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
Definition: ASTMatchersInternal.cpp:796
clang::ento::TagVisitor::VisitNode
PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &R) override
Return a diagnostic piece which should be associated with the given node.
Definition: BugReporterVisitors.cpp:2941
clang::ento::PathDiagnosticPieceRef
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
Definition: PathDiagnostic.h:493
isInterestingExpr
static bool isInterestingExpr(const Expr *E, const ExplodedNode *N, const PathSensitiveBugReport *B)
Definition: BugReporterVisitors.cpp:231
clang::ento::SVal::isUndef
bool isUndef() const
Definition: SVals.h:140
clang::QualType::isConstQualified
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition: Type.h:6479
clang::CFGBlock::succ_size
unsigned succ_size() const
Definition: CFG.h:973
clang::ProgramPointTag
ProgramPoints can be "tagged" as representing points specific to a given analysis entity.
Definition: ProgramPoint.h:39
clang::CFGBlock::succ_begin
succ_iterator succ_begin()
Definition: CFG.h:955
clang::ento::NilReceiverBRVisitor::getNilReceiver
static const Expr * getNilReceiver(const Stmt *S, const ExplodedNode *N)
If the statement is a message send expression with nil receiver, returns the receiver expression.
Definition: BugReporterVisitors.cpp:2122
AnalysisDeclContext.h
llvm::SmallVector
Definition: LLVM.h:38
clang::ento::MemRegion::StripCasts
const MemRegion * StripCasts(bool StripBaseAndDerivedCasts=true) const
Definition: MemRegion.cpp:1303
clang::SourceLocation
Encodes a location in the source.
Definition: SourceLocation.h:89
clang::Stmt::getSourceRange
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:324
clang::ento::ProgramStateRef
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
Definition: ProgramState_Fwd.h:37
clang::QualType
A (possibly-)qualified type.
Definition: Type.h:661
clang::SrcMgr::ExpansionInfo::isFunctionMacroExpansion
bool isFunctionMacroExpansion() const
Definition: SourceManager.h:395
clang::ento::SVal::isZeroConstant
bool isZeroConstant() const
Definition: SVals.cpp:212
clang::ento::ExplodedNode::getStackFrame
const StackFrameContext * getStackFrame() const
Definition: ExplodedGraph.h:150
clang::QualType::getCanonicalType
QualType getCanonicalType() const
Definition: Type.h:6459
clang::FieldDecl
Represents a member of a struct/union/class.
Definition: Decl.h:2792
getCallParameters
static ArrayRef< ParmVarDecl * > getCallParameters(CallEventRef<> Call)
Get parameters associated with runtime definition in order to get the correct parameter name.
Definition: BugReporterVisitors.cpp:468
clang::ento::ExplodedNode
Definition: ExplodedGraph.h:65
clang::ParmVarDecl
Represents a parameter to a function.
Definition: Decl.h:1630
DeclCXX.h
ProgramState_Fwd.h
clang::BinaryOperator::isAssignmentOp
bool isAssignmentOp() const
Definition: Expr.h:3865
clang::BinaryOperator::getOpcodeStr
StringRef getOpcodeStr() const
Definition: Expr.h:3792
clang::ento::ConditionBRVisitor::getTag
static const char * getTag()
Return the tag associated with this visitor.
Definition: BugReporterVisitors.cpp:2179
clang::ento::BugReporterVisitor::getEndPath
virtual PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC, const ExplodedNode *N, PathSensitiveBugReport &BR)
Provide custom definition for the final diagnostic piece on the path - the piece, which is displayed ...
Definition: BugReporterVisitors.cpp:296
clang::ento::ConditionBRVisitor::VisitNode
PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
Definition: BugReporterVisitors.cpp:2182
llvm::Optional
Definition: LLVM.h:40
clang::ento::bugreporter::TrackingKind
TrackingKind
Specifies the type of tracking for an expression.
Definition: BugReporterVisitors.h:91
llvm::SmallPtrSet
Definition: ASTContext.h:81
clang::Lexer::getSourceText
static StringRef getSourceText(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, bool *Invalid=nullptr)
Returns a string for the source that the range encompasses.
Definition: Lexer.cpp:942
clang::StackFrameContext
It represents a stack frame of the call stack (based on CallEvent).
Definition: AnalysisDeclContext.h:293
SourceManager.h
clang::Type::isVoidType
bool isVoidType() const
Definition: Type.h:6951
clang::ento::ConditionBRVisitor::printValue
bool printValue(const Expr *CondVarExpr, raw_ostream &Out, const ExplodedNode *N, bool TookTrue, bool IsAssuming)
Tries to print the value of the given expression.
Definition: BugReporterVisitors.cpp:2667
clang::tooling::X
static ToolExecutorPluginRegistry::Add< AllTUsToolExecutorPlugin > X("all-TUs", "Runs FrontendActions on all TUs in the compilation database. " "Tool results are stored in memory.")
clang::ento::BugReporterVisitor
BugReporterVisitors are used to add custom diagnostics along a path.
Definition: BugReporterVisitors.h:44
ASTMatchFinder.h
clang::PrintingPolicy
Describes how types, statements, expressions, and declarations should be printed.
Definition: PrettyPrinter.h:59
peelOffOuterExpr
static const Expr * peelOffOuterExpr(const Expr *Ex, const ExplodedNode *N)
Definition: BugReporterVisitors.cpp:1851
clang::ento::FalsePositiveRefutationBRVisitor::FalsePositiveRefutationBRVisitor
FalsePositiveRefutationBRVisitor()
Definition: BugReporterVisitors.cpp:2858
clang::index::SymbolRole::Call
@ Call
clang::BinaryOperator::getOpcode
Opcode getOpcode() const
Definition: Expr.h:3771
showBRDefaultDiagnostics
static void showBRDefaultDiagnostics(llvm::raw_svector_ostream &os, const MemRegion *R, SVal V)
Show default diagnostics for storing bad region.
Definition: BugReporterVisitors.cpp:1315
clang::ento::SMTConv::getRangeExpr
static llvm::SMTExprRef getRangeExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, const llvm::APSInt &From, const llvm::APSInt &To, bool InRange)
Definition: SMTConv.h:508
clang::ento::CallEvent::isCallStmt
static bool isCallStmt(const Stmt *S)
Returns true if this is a statement is a function or method call of some kind.
Definition: CallEvent.cpp:421
clang::ento::ProgramState
Definition: ProgramState.h:72
clang::Expr::IgnoreImpCasts
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:2763
b
__device__ __2f16 b
Definition: __clang_hip_libdevice_declares.h:302
clang::Expr::isGLValue
bool isGLValue() const
Definition: Expr.h:275
clang::SourceManager
This class handles loading and caching of source files into memory.
Definition: SourceManager.h:624
clang::ento::PathSensitiveBugReport::markInvalid
void markInvalid(const void *Tag, const void *Data)
Marks the current report as invalid, meaning that it is probably a false positive and should not be r...
Definition: BugReporter.h:479
clang::ento::SVal::getAs
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type.
Definition: SVals.h:111
Decl.h
CallEvent.h
clang::ento::MemRegion
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:94
wasRegionOfInterestModifiedAt
static bool wasRegionOfInterestModifiedAt(const SubRegion *RegionOfInterest, const ExplodedNode *N, SVal ValueAfter)
Definition: BugReporterVisitors.cpp:264
clang::CFGBlock
Represents a single basic block in a source-level CFG.
Definition: CFG.h:576
clang::ento::NoteTag::generateMessage
Optional< std::string > generateMessage(BugReporterContext &BRC, PathSensitiveBugReport &R) const
Definition: BugReporter.h:746
U
clang::StackFrameContext::inTopFrame
bool inTopFrame() const override
Definition: AnalysisDeclContext.h:323
clang::ento::MemRegionManager::getFieldRegion
const FieldRegion * getFieldRegion(const FieldDecl *fd, const SubRegion *superRegion)
getFieldRegion - Retrieve or create the memory region associated with a specified FieldDecl.
Definition: MemRegion.cpp:1139
clang::ento::TrackConstraintBRVisitor::getTag
static const char * getTag()
Return the tag associated with this visitor.
Definition: BugReporterVisitors.cpp:1535
clang::Type::isReferenceType
bool isReferenceType() const
Definition: Type.h:6680
V
#define V(N, I)
Definition: ASTContext.h:3026
clang::ento::ExplodedNode::getState
const ProgramStateRef & getState() const
Definition: ExplodedGraph.h:169
clang::ento::DefinedSVal
Definition: SVals.h:256
ProgramPoint.h
clang::ento::TrackConstraintBRVisitor::Profile
void Profile(llvm::FoldingSetNodeID &ID) const override
Definition: BugReporterVisitors.cpp:1526
clang::ast_matchers::objcIvarRefExpr
const internal::VariadicDynCastAllOfMatcher< Stmt, ObjCIvarRefExpr > objcIvarRefExpr
Matches a reference to an ObjCIvar.
Definition: ASTMatchersInternal.cpp:877
clang::ento::Range
A Range represents the closed range [from, to].
Definition: RangedConstraintManager.h:29
clang::ento::ConstraintMap
llvm::ImmutableMap< SymbolRef, RangeSet > ConstraintMap
Definition: RangedConstraintManager.h:310
isVarAnInterestingCondition
static bool isVarAnInterestingCondition(const Expr *CondVarExpr, const ExplodedNode *N, const PathSensitiveBugReport *B)
Definition: BugReporterVisitors.cpp:215
clang::StmtPoint
Definition: ProgramPoint.h:271
Node
DynTypedNode Node
Definition: ASTMatchFinder.cpp:67
clang::LocationContext::getAnalysisDeclContext
AnalysisDeclContext * getAnalysisDeclContext() const
Definition: AnalysisDeclContext.h:239
clang::BinaryOperator
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3727
clang::SrcMgr::ExpansionInfo
Each ExpansionInfo encodes the expansion location - where the token was ultimately expanded,...
Definition: SourceManager.h:347
DeclBase.h
clang::ento::PathDiagnosticLocation::create
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
Definition: PathDiagnostic.h:249
clang::XRayInstrKind::None
constexpr XRayInstrMask None
Definition: XRayInstr.h:38
clang::ento::SuppressInlineDefensiveChecksVisitor::SuppressInlineDefensiveChecksVisitor
SuppressInlineDefensiveChecksVisitor(DefinedSVal Val, const ExplodedNode *N)
Definition: BugReporterVisitors.cpp:1602
clang::ento::BugReporterContext::getSourceManager
const SourceManager & getSourceManager() const
Definition: BugReporter.h:714
BugReporter.h
clang::ASTContext
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:187
showBRDiagnostics
static void showBRDiagnostics(const char *action, llvm::raw_svector_ostream &os, const MemRegion *R, SVal V, const DeclStmt *DS)
Show diagnostics for initializing or declaring a region R with a bad value.
Definition: BugReporterVisitors.cpp:1243
clang::ProgramPoint::getAs
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
Definition: ProgramPoint.h:151
getLocationRegionIfReference
static const MemRegion * getLocationRegionIfReference(const Expr *E, const ExplodedNode *N)
Definition: BugReporterVisitors.cpp:1828
clang::ento::SymExpr
Symbolic value.
Definition: SymExpr.h:29
clang::ProgramPoint::getTag
const ProgramPointTag * getTag() const
Definition: ProgramPoint.h:177
clang::ento::PathDiagnosticLocation::isValid
bool isValid() const
Definition: PathDiagnostic.h:336
trackRValueExpression
static void trackRValueExpression(const ExplodedNode *InputNode, const Expr *E, PathSensitiveBugReport &report, bugreporter::TrackingKind TKind, bool EnableNullFPSuppression)
Attempts to add visitors to track an RValue expression back to its point of origin.
Definition: BugReporterVisitors.cpp:1929
clang::CallExitEnd
Represents a point when we finish the call exit sequence (for inlined call).
Definition: ProgramPoint.h:688
clang::ento::PathSensitiveBugReport::getErrorNode
const ExplodedNode * getErrorNode() const
Definition: BugReporter.h:404
clang::ento::FalsePositiveRefutationBRVisitor::finalizeVisitor
void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *EndPathNode, PathSensitiveBugReport &BR) override
Last function called on the visitor, no further calls to VisitNode would follow.
Definition: BugReporterVisitors.cpp:2861
clang::ento::ConditionBRVisitor::VisitTerminator
PathDiagnosticPieceRef VisitTerminator(const Stmt *Term, const ExplodedNode *N, const CFGBlock *SrcBlk, const CFGBlock *DstBlk, PathSensitiveBugReport &R, BugReporterContext &BRC)
Definition: BugReporterVisitors.cpp:2232
clang::ento::bugreporter::TrackingKind::Condition
@ Condition
Specifies that a more moderate tracking should be used for the expression value.
clang::LocationContext::isParentOf
bool isParentOf(const LocationContext *LC) const
Definition: AnalysisDeclContext.cpp:424
SMTConv.h
clang::ento::BugReporterContext::getAnalyzerOptions
const AnalyzerOptions & getAnalyzerOptions() const
Definition: BugReporter.h:718
clang::CFGBlock::getLastCondition
const Expr * getLastCondition() const
Definition: CFG.cpp:5927
clang::PostStore
Represents a program point after a store evaluation.
Definition: ProgramPoint.h:431
clang::ento::MemRegion::isSubRegionOf
virtual bool isSubRegionOf(const MemRegion *R) const
Check if the region is a subregion of the given region.
Definition: MemRegion.cpp:1295
clang::CFGStmtMap::getBlock
CFGBlock * getBlock(Stmt *S)
Returns the CFGBlock the specified Stmt* appears in.
Definition: CFGStmtMap.cpp:26
clang::ento::BugReporterVisitor::finalizeVisitor
virtual void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *EndPathNode, PathSensitiveBugReport &BR)
Last function called on the visitor, no further calls to VisitNode would follow.
Definition: BugReporterVisitors.cpp:302
clang::Stmt::getEndLoc
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Stmt.cpp:348
IdentifierTable.h
clang::ento::VarRegion
Definition: MemRegion.h:906
clang::ento::TagVisitor::Profile
void Profile(llvm::FoldingSetNodeID &ID) const override
Definition: BugReporterVisitors.cpp:2936
clang::DeclRefExpr::getDecl
ValueDecl * getDecl()
Definition: Expr.h:1285
clang::ento::SuppressInlineDefensiveChecksVisitor::Profile
void Profile(llvm::FoldingSetNodeID &ID) const override
Definition: BugReporterVisitors.cpp:1610
Type.h
clang::PD_NONE
@ PD_NONE
Definition: AnalyzerOptions.h:62
Expr.h
llvm::SmallString
Definition: LLVM.h:37
ASTContext.h
clang::Type::getPointeeType
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:625
clang::ento::bugreporter::TrackingKind::Thorough
@ Thorough
Default tracking kind – specifies that as much information should be gathered about the tracked expre...
clang::PostInitializer
Definition: ProgramPoint.h:527
clang::MemberExpr::getMemberLoc
SourceLocation getMemberLoc() const
getMemberLoc - Return the location of the "member", in X->F, it is the location of 'F'.
Definition: Expr.h:3275
clang::ento::ExplodedNode::getLocationAs
Optional< T > getLocationAs() const LLVM_LVALUE_FUNCTION
Definition: ExplodedGraph.h:172
clang::ento::BugReporterContext
Definition: BugReporter.h:694
clang::ast_matchers::binaryOperator
const internal::VariadicDynCastAllOfMatcher< Stmt, BinaryOperator > binaryOperator
Matches binary operator expressions.
Definition: ASTMatchersInternal.cpp:932
WillBeUsedForACondition
static llvm::StringLiteral WillBeUsedForACondition
Definition: BugReporterVisitors.cpp:653
isInitializationOfVar
static bool isInitializationOfVar(const ExplodedNode *N, const VarRegion *VR)
Returns true if N represents the DeclStmt declaring and initializing VR.
Definition: BugReporterVisitors.cpp:1215
PathDiagnostic.h
clang::AnalysisDeclContext::isInStdNamespace
static bool isInStdNamespace(const Decl *D)
Definition: AnalysisDeclContext.cpp:325
clang::ento::FalsePositiveRefutationBRVisitor::Profile
void Profile(llvm::FoldingSetNodeID &ID) const override
Definition: BugReporterVisitors.cpp:2924
ExprObjC.h
clang::Lexer::getImmediateMacroName
static StringRef getImmediateMacroName(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Retrieve the name of the immediate macro expansion.
Definition: Lexer.cpp:978
ExprCXX.h
Base
clang::ento::SuppressInlineDefensiveChecksVisitor::getTag
static const char * getTag()
Return the tag associated with this visitor.
Definition: BugReporterVisitors.cpp:1617
clang::CFGBlock::getTerminatorCondition
Stmt * getTerminatorCondition(bool StripParens=true)
Definition: CFG.cpp:5955
clang::ento::PathDiagnosticPiece::getString
StringRef getString() const
Definition: PathDiagnostic.h:437
clang::CFGStmtMap
Definition: CFGStmtMap.h:24
clang::ento::CallEventManager::getCaller
CallEventRef getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State)
Gets an outside caller given a callee context.
Definition: CallEvent.cpp:1391
clang::ento::KnownSVal
Represents an SVal that is guaranteed to not be UnknownVal.
Definition: SVals.h:278
x
IRgen optimization opportunities The common pattern of short x
Definition: README.txt:7
ExplodedGraph.h
clang::MemberExpr::getMemberDecl
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition: Expr.h:3169
showBRParamDiagnostics
static void showBRParamDiagnostics(llvm::raw_svector_ostream &os, const VarRegion *VR, SVal V)
Display diagnostics for passing bad region as a parameter.
Definition: BugReporterVisitors.cpp:1285
state
and static some checkers Checker The latter are built on top of the former via the Checker and CheckerVisitor and attempts to isolate them from much of the gore of the internal analysis the analyzer is basically a source code simulator that traces out possible paths of execution The state of the and the combination of state and program point is a node in an exploded which has the entry program point and initial state
Definition: README.txt:30
CFGStmtMap.h
clang::ento::Loc
Definition: SVals.h:314
getMacroName
static StringRef getMacroName(SourceLocation Loc, BugReporterContext &BRC)
Definition: BugReporterVisitors.cpp:239
clang::ento::ExprEngine::geteagerlyAssumeBinOpBifurcationTags
static std::pair< const ProgramPointTag *, const ProgramPointTag * > geteagerlyAssumeBinOpBifurcationTags()
Definition: ExprEngine.cpp:3031
clang::Type::isObjCObjectPointerType
bool isObjCObjectPointerType() const
Definition: Type.h:6790
clang::ento::NilReceiverBRVisitor::VisitNode
PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
Definition: BugReporterVisitors.cpp:2137
constructDebugPieceForTrackedCondition
static std::shared_ptr< PathDiagnosticEventPiece > constructDebugPieceForTrackedCondition(const Expr *Cond, const ExplodedNode *N, BugReporterContext &BRC)
Definition: BugReporterVisitors.cpp:1729
clang::LocationContext::getParent
const LocationContext * getParent() const
Definition: AnalysisDeclContext.h:241
clang::ento::ExplodedGraph::isInterestingLValueExpr
static bool isInterestingLValueExpr(const Expr *Ex)
Returns true if nodes for the given expression kind are always kept around.
Definition: ExplodedGraph.cpp:50
clang::Expr::IgnoreParenCasts
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition: Expr.cpp:2788
clang::CXXRecordDecl
Represents a C++ struct/union/class.
Definition: DeclCXX.h:254
clang::PostStmt
Definition: ProgramPoint.h:311
clang::SrcMgr::SLocEntry::getExpansion
const ExpansionInfo & getExpansion() const
Definition: SourceManager.h:488
clang::ento::bugreporter::getDerefExpr
const Expr * getDerefExpr(const Stmt *S)
SourceLocation.h
clang::DeclStmt::getSingleDecl
const Decl * getSingleDecl() const
Definition: Stmt.h:1306
P
StringRef P
Definition: ASTMatchersInternal.cpp:563
clang::PreStmt
Definition: ProgramPoint.h:295
clang::ento::CallEventManager
Manages the lifetime of CallEvent objects.
Definition: CallEvent.h:1328
clang::Stmt::getStmtClass
StmtClass getStmtClass() const
Definition: Stmt.h:1162
clang::Type::isPointerType
bool isPointerType() const
Definition: Type.h:6668
clang::ento::PathSensitiveBugReport::getRanges
ArrayRef< SourceRange > getRanges() const override
Get the SourceRanges associated with the report.
Definition: BugReporter.cpp:2377
clang::ento::ProgramStateManager
Definition: ProgramState.h:463
clang::ento::FalsePositiveRefutationBRVisitor::addConstraints
void addConstraints(const ExplodedNode *N, bool OverwriteConstraintsOnExistingSyms)
Definition: BugReporterVisitors.cpp:2898
clang::ento::DefinedSVal::isValid
bool isValid() const =delete
SValBuilder.h
clang::ento::ProgramStateManager::getCallEventManager
CallEventManager & getCallEventManager()
Definition: ProgramState.h:537
isPointerToConst
static bool isPointerToConst(QualType Ty)
Definition: BugReporterVisitors.cpp:480
clang::BinaryOperator::getLHS
Expr * getLHS() const
Definition: Expr.h:3776
clang::ento::ConditionBRVisitor::isPieceMessageGeneric
static bool isPieceMessageGeneric(const PathDiagnosticPiece *Piece)
Definition: BugReporterVisitors.cpp:2707
clang::CharSourceRange::getTokenRange
static CharSourceRange getTokenRange(SourceRange R)
Definition: SourceLocation.h:263
clang::DeclContext::getParent
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:1860
clang::RecordDecl::fields
field_range fields() const
Definition: Decl.h:4036
potentiallyWritesIntoIvar
static bool potentiallyWritesIntoIvar(const Decl *Parent, const ObjCIvarDecl *Ivar)
Definition: BugReporterVisitors.cpp:435
clang::ento::ExplodedNode::getFirstPred
ExplodedNode * getFirstPred()
Definition: ExplodedGraph.h:210
clang::QualType::isNull
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:726
llvm::ArrayRef
Definition: LLVM.h:34
Lexer.h
Value
Value
Definition: UninitializedValues.cpp:102
clang::Decl
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:89
clang::BinaryOperator::isComparisonOp
bool isComparisonOp() const
Definition: Expr.h:3827
BugReporterVisitors.h
clang::CFGBlock::isInevitablySinking
bool isInevitablySinking() const
Returns true if the block would eventually end with a sink (a noreturn node).
Definition: CFG.cpp:5889
clang::StackFrameContext::getCallSite
const Stmt * getCallSite() const
Definition: AnalysisDeclContext.h:319
clang::CharSourceRange
Represents a character-granular source range.
Definition: SourceLocation.h:255
clang::ento::PathDiagnosticLocation::asLocation
FullSourceLoc asLocation() const
Definition: PathDiagnostic.h:340
LLVM.h
clang::AnalyzerOptions
Stores options for the analyzer from the command line.
Definition: AnalyzerOptions.h:163
clang::Type::getAsRecordDecl
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition: Type.cpp:1757
State
LineState State
Definition: UnwrappedLineFormatter.cpp:959
clang::ento::ConditionBRVisitor::patternMatch
bool patternMatch(const Expr *Ex, const Expr *ParentEx, raw_ostream &Out, BugReporterContext &BRC, PathSensitiveBugReport &R, const ExplodedNode *N, Optional< bool > &prunable, bool IsSameFieldName)
Definition: BugReporterVisitors.cpp:2359
clang::ast_matchers::hasDescendant
const internal::ArgumentAdaptingMatcherFunc< internal::HasDescendantMatcher > hasDescendant
Matches AST nodes that have descendant AST nodes that match the provided matcher.
Definition: ASTMatchersInternal.cpp:995
clang::ImplicitParamDecl::ObjCSelf
@ ObjCSelf
Parameter for Objective-C 'self' argument.
Definition: Decl.h:1575
clang::BinaryOperatorKind
BinaryOperatorKind
Definition: OperationKinds.h:25
clang::ento::ConditionBRVisitor::VisitTrueTest
PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond, BugReporterContext &BRC, PathSensitiveBugReport &R, const ExplodedNode *N, bool TookTrue)
Definition: BugReporterVisitors.cpp:2291
clang::SourceLocation::isMacroID
bool isMacroID() const
Definition: SourceLocation.h:103
clang::NamedDecl::getNameAsString
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Definition: Decl.h:266
clang::LangOptions
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:58
clang::Type::isBooleanType
bool isBooleanType() const
Definition: Type.h:7063
isAssertlikeBlock
static bool isAssertlikeBlock(const CFGBlock *B, ASTContext &Context)
Definition: BugReporterVisitors.cpp:1747
clang::DeclStmt
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1291
ProgramState.h
clang::ento::BugReport::getDescription
StringRef getDescription() const
A verbose warning message that is appropriate for displaying next to the source code that introduces ...
Definition: BugReporter.h:159
clang::ento::MemRegionManager
Definition: MemRegion.h:1302
clang::ento::PathSensitiveBugReport
Definition: BugReporter.h:291
clang::ento::UndefOrNullArgVisitor::VisitNode
PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
Definition: BugReporterVisitors.cpp:2805
ExprEngine.h
findNodeForExpression
static const ExplodedNode * findNodeForExpression(const ExplodedNode *N, const Expr *Inner)
Find the ExplodedNode where the lvalue (the value of 'Ex') was computed.
Definition: BugReporterVisitors.cpp:1917
clang::Builtin::ID
ID
Definition: Builtins.h:47
clang::Expr::IgnoreParens
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:2779
clang::ento::BugReporterVisitor::getDefaultEndPath
static PathDiagnosticPieceRef getDefaultEndPath(const BugReporterContext &BRC, const ExplodedNode *N, const PathSensitiveBugReport &BR)
Generates the default final diagnostic piece.
Definition: BugReporterVisitors.cpp:307
clang
Dataflow Directional Tag Classes.
Definition: CalledOnceCheck.h:17
clang::Type::isAnyPointerType
bool isAnyPointerType() const
Definition: Type.h:6672
clang::Lexer::isAtStartOfMacroExpansion
static bool isAtStartOfMacroExpansion(SourceLocation loc, const SourceManager &SM, const LangOptions &LangOpts, SourceLocation *MacroBegin=nullptr)
Returns true if the given MacroID location points at the first token of the macro expansion.
Definition: Lexer.cpp:803
clang::ento::ExplodedNode::getLocation
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
Definition: ExplodedGraph.h:144
CFG.h
clang::Stmt
Stmt - This represents one statement.
Definition: Stmt.h:68
clang::ObjCIvarDecl
ObjCIvarDecl - Represents an ObjC instance variable.
Definition: DeclObjC.h:1921
clang::BinaryOperator::getRHS
Expr * getRHS() const
Definition: Expr.h:3778
clang::ast_matchers::match
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
Definition: ASTMatchFinder.h:310
clang::ento::PathDiagnosticPiece
Definition: PathDiagnostic.h:404
clang::CFGBlock::getTerminatorStmt
Stmt * getTerminatorStmt()
Definition: CFG.h:1050
clang::ento::ConditionBRVisitor::VisitConditionVariable
PathDiagnosticPieceRef VisitConditionVariable(StringRef LhsString, const Expr *CondVarExpr, BugReporterContext &BRC, PathSensitiveBugReport &R, const ExplodedNode *N, bool TookTrue)
Definition: BugReporterVisitors.cpp:2566
MemRegion.h
clang::ento::FindLastStoreBRVisitor::Profile
void Profile(llvm::FoldingSetNodeID &ID) const override
Definition: BugReporterVisitors.cpp:1204
clang::Expr::getType
QualType getType() const
Definition: Expr.h:141
clang::SourceLocation::isValid
bool isValid() const
Return true if this is a valid SourceLocation object.
Definition: SourceLocation.h:110
clang::ento::PathDiagnosticLocation::createBegin
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
Definition: PathDiagnostic.cpp:580
clang::ento::ExplodedNode::getSVal
SVal getSVal(const Stmt *S) const
Get the value of an arbitrary expression at this node.
Definition: ExplodedGraph.h:177
clang::ControlDependencyCalculator
Definition: Dominators.h:215
clang::ento::PathSensitiveBugReport::markInteresting
void markInteresting(SymbolRef sym, bugreporter::TrackingKind TKind=bugreporter::TrackingKind::Thorough)
Marks a symbol as interesting.
clang::Stmt::getBeginLoc
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:336
peelOffPointerArithmetic
static const Expr * peelOffPointerArithmetic(const BinaryOperator *B)
Definition: BugReporterVisitors.cpp:73
isFunctionMacroExpansion
static bool isFunctionMacroExpansion(SourceLocation Loc, const SourceManager &SM)
Definition: BugReporterVisitors.cpp:249
clang::CallEnter
Represents a point when we begin processing an inlined call.
Definition: ProgramPoint.h:630
Dominators.h
clang::MemberExpr
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3086
clang::BlockEdge
Definition: ProgramPoint.h:503
clang::ast_matchers::BoundNodes
Maps string IDs to AST nodes matched by parts of a matcher.
Definition: ASTMatchers.h:107
clang::ento::PathSensitiveBugReport::isInteresting
bool isInteresting(SymbolRef sym) const
Definition: BugReporter.cpp:2344
clang::ento::SVal
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition: SVals.h:75
clang::ento::ConditionBRVisitor::VisitNodeImpl
PathDiagnosticPieceRef VisitNodeImpl(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR)
Definition: BugReporterVisitors.cpp:2194
Parent
NodeId Parent
Definition: ASTDiff.cpp:192
Stmt.h
clang::ento::SubRegion
SubRegion - A region that subsets another larger region.
Definition: MemRegion.h:435
clang::BinaryOperator::isAdditiveOp
static bool isAdditiveOp(Opcode Opc)
Definition: Expr.h:3812
clang::ValueDecl::getType
QualType getType() const
Definition: Decl.h:655
clang::Expr
This represents one expression.
Definition: Expr.h:109
SM
#define SM(sm)
Definition: Cuda.cpp:68
clang::ento::SuppressInlineDefensiveChecksVisitor::VisitNode
PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ, BugReporterContext &BRC, PathSensitiveBugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
Definition: BugReporterVisitors.cpp:1622
clang::ento::BugReporterContext::getASTContext
ASTContext & getASTContext() const
Definition: BugReporter.h:710
clang::ast_matchers::hasDeclaration
internal::PolymorphicMatcher< internal::HasDeclarationMatcher, void(internal::HasDeclarationSupportedTypes), internal::Matcher< Decl > > hasDeclaration(const internal::Matcher< Decl > &InnerMatcher)
Matches a node if the declaration associated with that node matches the given matcher.
Definition: ASTMatchers.h:3549
AnalysisManager.h
clang::Expr::isRValue
bool isRValue() const
Definition: Expr.h:273
clang::ento::NoteTag
The tag upon which the TagVisitor reacts.
Definition: BugReporter.h:726
clang::ento::PathSensitiveBugReport::getLocation
PathDiagnosticLocation getLocation() const override
The primary location of the bug report that points at the undesirable behavior in the code.
Definition: BugReporter.cpp:2387
clang::ento::BugReporterContext::getStateManager
ProgramStateManager & getStateManager() const
Definition: BugReporter.h:706
clang::DeclRefExpr
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1213
clang::LocationContext::getDecl
const Decl * getDecl() const
Definition: AnalysisDeclContext.h:245
clang::RecordDecl
Represents a struct/union/class.
Definition: Decl.h:3816
clang::ProgramPoint
Definition: ProgramPoint.h:59
clang::ento::LikelyFalsePositiveSuppressionBRVisitor::getTag
static void * getTag()
Definition: BugReporterVisitors.h:300
clang::ObjCIvarRefExpr
ObjCIvarRefExpr - A reference to an ObjC instance variable.
Definition: ExprObjC.h:548
clang::ento::getConstraintMap
ConstraintMap getConstraintMap(ProgramStateRef State)
Definition: RangeConstraintManager.cpp:1567
clang::ASTContext::getLangOpts
const LangOptions & getLangOpts() const
Definition: ASTContext.h:709
llvm::IntrusiveRefCntPtr< const ProgramState >
clang::Type::isIntegralOrEnumerationType
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:7050
clang::ento::ObjKind::OS
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
clang::ento::FindLastStoreBRVisitor::VisitNode
PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
Definition: BugReporterVisitors.cpp:1360
clang::ento::LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor
void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *N, PathSensitiveBugReport &BR) override
Last function called on the visitor, no further calls to VisitNode would follow.
Definition: BugReporterVisitors.cpp:2717
clang::ento::FalsePositiveRefutationBRVisitor::VisitNode
PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
Definition: BugReporterVisitors.cpp:2918
clang::SrcMgr::SLocEntry
This is a discriminated union of FileInfo and ExpansionInfo.
Definition: SourceManager.h:467
clang::Lexer::getAsCharRange
static CharSourceRange getAsCharRange(SourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
Given a token range, produce a corresponding CharSourceRange that is not a token range.
Definition: Lexer.h:398
clang::NamedDecl::getName
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:250