clang  3.8.0
NullabilityChecker.cpp
Go to the documentation of this file.
1 //== Nullabilityhecker.cpp - Nullability checker ----------------*- C++ -*--==//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This checker tries to find nullability violations. There are several kinds of
11 // possible violations:
12 // * Null pointer is passed to a pointer which has a _Nonnull type.
13 // * Null pointer is returned from a function which has a _Nonnull return type.
14 // * Nullable pointer is passed to a pointer which has a _Nonnull type.
15 // * Nullable pointer is returned from a function which has a _Nonnull return
16 // type.
17 // * Nullable pointer is dereferenced.
18 //
19 // This checker propagates the nullability information of the pointers and looks
20 // for the patterns that are described above. Explicit casts are trusted and are
21 // considered a way to suppress false positives for this checker. The other way
22 // to suppress warnings would be to add asserts or guarding if statements to the
23 // code. In addition to the nullability propagation this checker also uses some
24 // heuristics to suppress potential false positives.
25 //
26 //===----------------------------------------------------------------------===//
27 
28 #include "ClangSACheckers.h"
29 #include "llvm/Support/Path.h"
35 
36 using namespace clang;
37 using namespace ento;
38 
39 namespace {
40 // Do not reorder! The getMostNullable method relies on the order.
41 // Optimization: Most pointers expected to be unspecified. When a symbol has an
42 // unspecified or nonnull type non of the rules would indicate any problem for
43 // that symbol. For this reason only nullable and contradicted nullability are
44 // stored for a symbol. When a symbol is already contradicted, it can not be
45 // casted back to nullable.
46 enum class Nullability : char {
47  Contradicted, // Tracked nullability is contradicted by an explicit cast. Do
48  // not report any nullability related issue for this symbol.
49  // This nullability is propagated agressively to avoid false
50  // positive results. See the comment on getMostNullable method.
51  Nullable,
53  Nonnull
54 };
55 
56 /// Returns the most nullable nullability. This is used for message expressions
57 /// like [reciever method], where the nullability of this expression is either
58 /// the nullability of the receiver or the nullability of the return type of the
59 /// method, depending on which is more nullable. Contradicted is considered to
60 /// be the most nullable, to avoid false positive results.
61 Nullability getMostNullable(Nullability Lhs, Nullability Rhs) {
62  return static_cast<Nullability>(
63  std::min(static_cast<char>(Lhs), static_cast<char>(Rhs)));
64 }
65 
66 const char *getNullabilityString(Nullability Nullab) {
67  switch (Nullab) {
68  case Nullability::Contradicted:
69  return "contradicted";
71  return "nullable";
73  return "unspecified";
74  case Nullability::Nonnull:
75  return "nonnull";
76  }
77  llvm_unreachable("Unexpected enumeration.");
78  return "";
79 }
80 
81 // These enums are used as an index to ErrorMessages array.
82 enum class ErrorKind : int {
83  NilAssignedToNonnull,
84  NilPassedToNonnull,
85  NilReturnedToNonnull,
86  NullableAssignedToNonnull,
87  NullableReturnedToNonnull,
88  NullableDereferenced,
89  NullablePassedToNonnull
90 };
91 
92 const char *const ErrorMessages[] = {
93  "Null is assigned to a pointer which is expected to have non-null value",
94  "Null passed to a callee that requires a non-null argument",
95  "Null is returned from a function that is expected to return a non-null "
96  "value",
97  "Nullable pointer is assigned to a pointer which is expected to have "
98  "non-null value",
99  "Nullable pointer is returned from a function that is expected to return a "
100  "non-null value",
101  "Nullable pointer is dereferenced",
102  "Nullable pointer is passed to a callee that requires a non-null argument"};
103 
104 class NullabilityChecker
105  : public Checker<check::Bind, check::PreCall, check::PreStmt<ReturnStmt>,
106  check::PostCall, check::PostStmt<ExplicitCastExpr>,
107  check::PostObjCMessage, check::DeadSymbols,
108  check::Event<ImplicitNullDerefEvent>> {
109  mutable std::unique_ptr<BugType> BT;
110 
111 public:
112  void checkBind(SVal L, SVal V, const Stmt *S, CheckerContext &C) const;
113  void checkPostStmt(const ExplicitCastExpr *CE, CheckerContext &C) const;
114  void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
115  void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
116  void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
117  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
118  void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
119  void checkEvent(ImplicitNullDerefEvent Event) const;
120 
121  void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
122  const char *Sep) const override;
123 
124  struct NullabilityChecksFilter {
125  DefaultBool CheckNullPassedToNonnull;
126  DefaultBool CheckNullReturnedFromNonnull;
127  DefaultBool CheckNullableDereferenced;
128  DefaultBool CheckNullablePassedToNonnull;
129  DefaultBool CheckNullableReturnedFromNonnull;
130 
131  CheckName CheckNameNullPassedToNonnull;
132  CheckName CheckNameNullReturnedFromNonnull;
133  CheckName CheckNameNullableDereferenced;
134  CheckName CheckNameNullablePassedToNonnull;
135  CheckName CheckNameNullableReturnedFromNonnull;
136  };
137 
138  NullabilityChecksFilter Filter;
139  // When set to false no nullability information will be tracked in
140  // NullabilityMap. It is possible to catch errors like passing a null pointer
141  // to a callee that expects nonnull argument without the information that is
142  // stroed in the NullabilityMap. This is an optimization.
143  DefaultBool NeedTracking;
144 
145 private:
146  class NullabilityBugVisitor
147  : public BugReporterVisitorImpl<NullabilityBugVisitor> {
148  public:
149  NullabilityBugVisitor(const MemRegion *M) : Region(M) {}
150 
151  void Profile(llvm::FoldingSetNodeID &ID) const override {
152  static int X = 0;
153  ID.AddPointer(&X);
154  ID.AddPointer(Region);
155  }
156 
157  PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
158  const ExplodedNode *PrevN,
159  BugReporterContext &BRC,
160  BugReport &BR) override;
161 
162  private:
163  // The tracked region.
164  const MemRegion *Region;
165  };
166 
167  /// When any of the nonnull arguments of the analyzed function is null, do not
168  /// report anything and turn off the check.
169  ///
170  /// When \p SuppressPath is set to true, no more bugs will be reported on this
171  /// path by this checker.
172  void reportBugIfPreconditionHolds(ErrorKind Error, ExplodedNode *N,
173  const MemRegion *Region, CheckerContext &C,
174  const Stmt *ValueExpr = nullptr,
175  bool SuppressPath = false) const;
176 
177  void reportBug(ErrorKind Error, ExplodedNode *N, const MemRegion *Region,
178  BugReporter &BR, const Stmt *ValueExpr = nullptr) const {
179  if (!BT)
180  BT.reset(new BugType(this, "Nullability", "Memory error"));
181  const char *Msg = ErrorMessages[static_cast<int>(Error)];
182  std::unique_ptr<BugReport> R(new BugReport(*BT, Msg, N));
183  if (Region) {
184  R->markInteresting(Region);
185  R->addVisitor(llvm::make_unique<NullabilityBugVisitor>(Region));
186  }
187  if (ValueExpr) {
188  R->addRange(ValueExpr->getSourceRange());
189  if (Error == ErrorKind::NilAssignedToNonnull ||
190  Error == ErrorKind::NilPassedToNonnull ||
191  Error == ErrorKind::NilReturnedToNonnull)
192  bugreporter::trackNullOrUndefValue(N, ValueExpr, *R);
193  }
194  BR.emitReport(std::move(R));
195  }
196 
197  /// If an SVal wraps a region that should be tracked, it will return a pointer
198  /// to the wrapped region. Otherwise it will return a nullptr.
199  const SymbolicRegion *getTrackRegion(SVal Val,
200  bool CheckSuperRegion = false) const;
201 };
202 
203 class NullabilityState {
204 public:
205  NullabilityState(Nullability Nullab, const Stmt *Source = nullptr)
206  : Nullab(Nullab), Source(Source) {}
207 
208  const Stmt *getNullabilitySource() const { return Source; }
209 
210  Nullability getValue() const { return Nullab; }
211 
212  void Profile(llvm::FoldingSetNodeID &ID) const {
213  ID.AddInteger(static_cast<char>(Nullab));
214  ID.AddPointer(Source);
215  }
216 
217  void print(raw_ostream &Out) const {
218  Out << getNullabilityString(Nullab) << "\n";
219  }
220 
221 private:
222  Nullability Nullab;
223  // Source is the expression which determined the nullability. For example in a
224  // message like [nullable nonnull_returning] has nullable nullability, because
225  // the receiver is nullable. Here the receiver will be the source of the
226  // nullability. This is useful information when the diagnostics are generated.
227  const Stmt *Source;
228 };
229 
230 bool operator==(NullabilityState Lhs, NullabilityState Rhs) {
231  return Lhs.getValue() == Rhs.getValue() &&
232  Lhs.getNullabilitySource() == Rhs.getNullabilitySource();
233 }
234 
235 } // end anonymous namespace
236 
238  NullabilityState)
239 
240 // If the nullability precondition of a function is violated, we should not
241 // report nullability related issues on that path. For this reason once a
242 // precondition is not met on a path, this checker will be esentially turned off
243 // for the rest of the analysis. We do not want to generate a sink node however,
244 // so this checker would not lead to reduced coverage.
245 REGISTER_TRAIT_WITH_PROGRAMSTATE(PreconditionViolated, bool)
246 
247 enum class NullConstraint { IsNull, IsNotNull, Unknown };
248 
249 static NullConstraint getNullConstraint(DefinedOrUnknownSVal Val,
251  ConditionTruthVal Nullness = State->isNull(Val);
252  if (Nullness.isConstrainedFalse())
253  return NullConstraint::IsNotNull;
254  if (Nullness.isConstrainedTrue())
255  return NullConstraint::IsNull;
257 }
258 
259 const SymbolicRegion *
260 NullabilityChecker::getTrackRegion(SVal Val, bool CheckSuperRegion) const {
261  if (!NeedTracking)
262  return nullptr;
263 
264  auto RegionSVal = Val.getAs<loc::MemRegionVal>();
265  if (!RegionSVal)
266  return nullptr;
267 
268  const MemRegion *Region = RegionSVal->getRegion();
269 
270  if (CheckSuperRegion) {
271  if (auto FieldReg = Region->getAs<FieldRegion>())
272  return dyn_cast<SymbolicRegion>(FieldReg->getSuperRegion());
273  if (auto ElementReg = Region->getAs<ElementRegion>())
274  return dyn_cast<SymbolicRegion>(ElementReg->getSuperRegion());
275  }
276 
277  return dyn_cast<SymbolicRegion>(Region);
278 }
279 
280 PathDiagnosticPiece *NullabilityChecker::NullabilityBugVisitor::VisitNode(
281  const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
282  BugReport &BR) {
284  ProgramStateRef StatePrev = PrevN->getState();
285 
286  const NullabilityState *TrackedNullab = State->get<NullabilityMap>(Region);
287  const NullabilityState *TrackedNullabPrev =
288  StatePrev->get<NullabilityMap>(Region);
289  if (!TrackedNullab)
290  return nullptr;
291 
292  if (TrackedNullabPrev &&
293  TrackedNullabPrev->getValue() == TrackedNullab->getValue())
294  return nullptr;
295 
296  // Retrieve the associated statement.
297  const Stmt *S = TrackedNullab->getNullabilitySource();
298  if (!S) {
299  ProgramPoint ProgLoc = N->getLocation();
300  if (Optional<StmtPoint> SP = ProgLoc.getAs<StmtPoint>()) {
301  S = SP->getStmt();
302  }
303  }
304 
305  if (!S)
306  return nullptr;
307 
308  std::string InfoText =
309  (llvm::Twine("Nullability '") +
310  getNullabilityString(TrackedNullab->getValue()) + "' is infered")
311  .str();
312 
313  // Generate the extra diagnostic.
315  N->getLocationContext());
316  return new PathDiagnosticEventPiece(Pos, InfoText, true, nullptr);
317 }
318 
320  const auto *AttrType = Type->getAs<AttributedType>();
321  if (!AttrType)
323  if (AttrType->getAttrKind() == AttributedType::attr_nullable)
324  return Nullability::Nullable;
325  else if (AttrType->getAttrKind() == AttributedType::attr_nonnull)
326  return Nullability::Nonnull;
328 }
329 
330 template <typename ParamVarDeclRange>
331 static bool
332 checkParamsForPreconditionViolation(const ParamVarDeclRange &Params,
333  ProgramStateRef State,
334  const LocationContext *LocCtxt) {
335  for (const auto *ParamDecl : Params) {
336  if (ParamDecl->isParameterPack())
337  break;
338 
339  if (getNullabilityAnnotation(ParamDecl->getType()) != Nullability::Nonnull)
340  continue;
341 
342  auto RegVal = State->getLValue(ParamDecl, LocCtxt)
343  .template getAs<loc::MemRegionVal>();
344  if (!RegVal)
345  continue;
346 
347  auto ParamValue = State->getSVal(RegVal->getRegion())
348  .template getAs<DefinedOrUnknownSVal>();
349  if (!ParamValue)
350  continue;
351 
352  if (getNullConstraint(*ParamValue, State) == NullConstraint::IsNull) {
353  return true;
354  }
355  }
356  return false;
357 }
358 
360  CheckerContext &C) {
361  if (State->get<PreconditionViolated>())
362  return true;
363 
364  const LocationContext *LocCtxt = C.getLocationContext();
365  const Decl *D = LocCtxt->getDecl();
366  if (!D)
367  return false;
368 
369  if (const auto *BlockD = dyn_cast<BlockDecl>(D)) {
370  if (checkParamsForPreconditionViolation(BlockD->parameters(), State,
371  LocCtxt)) {
372  if (!N->isSink())
373  C.addTransition(State->set<PreconditionViolated>(true), N);
374  return true;
375  }
376  return false;
377  }
378 
379  if (const auto *FuncDecl = dyn_cast<FunctionDecl>(D)) {
380  if (checkParamsForPreconditionViolation(FuncDecl->parameters(), State,
381  LocCtxt)) {
382  if (!N->isSink())
383  C.addTransition(State->set<PreconditionViolated>(true), N);
384  return true;
385  }
386  return false;
387  }
388  return false;
389 }
390 
391 void NullabilityChecker::reportBugIfPreconditionHolds(
392  ErrorKind Error, ExplodedNode *N, const MemRegion *Region,
393  CheckerContext &C, const Stmt *ValueExpr, bool SuppressPath) const {
394  ProgramStateRef OriginalState = N->getState();
395 
396  if (checkPreconditionViolation(OriginalState, N, C))
397  return;
398  if (SuppressPath) {
399  OriginalState = OriginalState->set<PreconditionViolated>(true);
400  N = C.addTransition(OriginalState, N);
401  }
402 
403  reportBug(Error, N, Region, C.getBugReporter(), ValueExpr);
404 }
405 
406 /// Cleaning up the program state.
407 void NullabilityChecker::checkDeadSymbols(SymbolReaper &SR,
408  CheckerContext &C) const {
409  if (!SR.hasDeadSymbols())
410  return;
411 
412  ProgramStateRef State = C.getState();
413  NullabilityMapTy Nullabilities = State->get<NullabilityMap>();
414  for (NullabilityMapTy::iterator I = Nullabilities.begin(),
415  E = Nullabilities.end();
416  I != E; ++I) {
417  const auto *Region = I->first->getAs<SymbolicRegion>();
418  assert(Region && "Non-symbolic region is tracked.");
419  if (SR.isDead(Region->getSymbol())) {
420  State = State->remove<NullabilityMap>(I->first);
421  }
422  }
423  // When one of the nonnull arguments are constrained to be null, nullability
424  // preconditions are violated. It is not enough to check this only when we
425  // actually report an error, because at that time interesting symbols might be
426  // reaped.
428  return;
429  C.addTransition(State);
430 }
431 
432 /// This callback triggers when a pointer is dereferenced and the analyzer does
433 /// not know anything about the value of that pointer. When that pointer is
434 /// nullable, this code emits a warning.
435 void NullabilityChecker::checkEvent(ImplicitNullDerefEvent Event) const {
436  if (Event.SinkNode->getState()->get<PreconditionViolated>())
437  return;
438 
439  const MemRegion *Region =
440  getTrackRegion(Event.Location, /*CheckSuperregion=*/true);
441  if (!Region)
442  return;
443 
444  ProgramStateRef State = Event.SinkNode->getState();
445  const NullabilityState *TrackedNullability =
446  State->get<NullabilityMap>(Region);
447 
448  if (!TrackedNullability)
449  return;
450 
451  if (Filter.CheckNullableDereferenced &&
452  TrackedNullability->getValue() == Nullability::Nullable) {
453  BugReporter &BR = *Event.BR;
454  // Do not suppress errors on defensive code paths, because dereferencing
455  // a nullable pointer is always an error.
456  if (Event.IsDirectDereference)
457  reportBug(ErrorKind::NullableDereferenced, Event.SinkNode, Region, BR);
458  else
459  reportBug(ErrorKind::NullablePassedToNonnull, Event.SinkNode, Region, BR);
460  }
461 }
462 
463 /// This method check when nullable pointer or null value is returned from a
464 /// function that has nonnull return type.
465 ///
466 /// TODO: when nullability preconditons are violated, it is ok to violate the
467 /// nullability postconditons (i.e.: when one of the nonnull parameters are null
468 /// this check should not report any nullability related issue).
469 void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
470  CheckerContext &C) const {
471  auto RetExpr = S->getRetValue();
472  if (!RetExpr)
473  return;
474 
475  if (!RetExpr->getType()->isAnyPointerType())
476  return;
477 
478  ProgramStateRef State = C.getState();
479  if (State->get<PreconditionViolated>())
480  return;
481 
482  auto RetSVal =
483  State->getSVal(S, C.getLocationContext()).getAs<DefinedOrUnknownSVal>();
484  if (!RetSVal)
485  return;
486 
487  AnalysisDeclContext *DeclCtxt =
489  const FunctionType *FuncType = DeclCtxt->getDecl()->getFunctionType();
490  if (!FuncType)
491  return;
492 
493  NullConstraint Nullness = getNullConstraint(*RetSVal, State);
494 
495  Nullability RequiredNullability =
497 
498  // If the returned value is null but the type of the expression
499  // generating it is nonnull then we will suppress the diagnostic.
500  // This enables explicit suppression when returning a nil literal in a
501  // function with a _Nonnull return type:
502  // return (NSString * _Nonnull)0;
503  Nullability RetExprTypeLevelNullability =
504  getNullabilityAnnotation(RetExpr->getType());
505 
506  if (Filter.CheckNullReturnedFromNonnull &&
507  Nullness == NullConstraint::IsNull &&
508  RetExprTypeLevelNullability != Nullability::Nonnull &&
509  RequiredNullability == Nullability::Nonnull) {
510  static CheckerProgramPointTag Tag(this, "NullReturnedFromNonnull");
511  ExplodedNode *N = C.generateErrorNode(State, &Tag);
512  if (!N)
513  return;
514  reportBugIfPreconditionHolds(ErrorKind::NilReturnedToNonnull, N, nullptr, C,
515  RetExpr);
516  return;
517  }
518 
519  const MemRegion *Region = getTrackRegion(*RetSVal);
520  if (!Region)
521  return;
522 
523  const NullabilityState *TrackedNullability =
524  State->get<NullabilityMap>(Region);
525  if (TrackedNullability) {
526  Nullability TrackedNullabValue = TrackedNullability->getValue();
527  if (Filter.CheckNullableReturnedFromNonnull &&
528  Nullness != NullConstraint::IsNotNull &&
529  TrackedNullabValue == Nullability::Nullable &&
530  RequiredNullability == Nullability::Nonnull) {
531  static CheckerProgramPointTag Tag(this, "NullableReturnedFromNonnull");
532  ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &Tag);
533  reportBugIfPreconditionHolds(ErrorKind::NullableReturnedToNonnull, N,
534  Region, C);
535  }
536  return;
537  }
538  if (RequiredNullability == Nullability::Nullable) {
539  State = State->set<NullabilityMap>(Region,
540  NullabilityState(RequiredNullability,
541  S));
542  C.addTransition(State);
543  }
544 }
545 
546 /// This callback warns when a nullable pointer or a null value is passed to a
547 /// function that expects its argument to be nonnull.
548 void NullabilityChecker::checkPreCall(const CallEvent &Call,
549  CheckerContext &C) const {
550  if (!Call.getDecl())
551  return;
552 
553  ProgramStateRef State = C.getState();
554  if (State->get<PreconditionViolated>())
555  return;
556 
557  ProgramStateRef OrigState = State;
558 
559  unsigned Idx = 0;
560  for (const ParmVarDecl *Param : Call.parameters()) {
561  if (Param->isParameterPack())
562  break;
563 
564  const Expr *ArgExpr = nullptr;
565  if (Idx < Call.getNumArgs())
566  ArgExpr = Call.getArgExpr(Idx);
567  auto ArgSVal = Call.getArgSVal(Idx++).getAs<DefinedOrUnknownSVal>();
568  if (!ArgSVal)
569  continue;
570 
571  if (!Param->getType()->isAnyPointerType() &&
572  !Param->getType()->isReferenceType())
573  continue;
574 
575  NullConstraint Nullness = getNullConstraint(*ArgSVal, State);
576 
577  Nullability RequiredNullability =
578  getNullabilityAnnotation(Param->getType());
579  Nullability ArgExprTypeLevelNullability =
580  getNullabilityAnnotation(ArgExpr->getType());
581 
582  if (Filter.CheckNullPassedToNonnull && Nullness == NullConstraint::IsNull &&
583  ArgExprTypeLevelNullability != Nullability::Nonnull &&
584  RequiredNullability == Nullability::Nonnull) {
585  ExplodedNode *N = C.generateErrorNode(State);
586  if (!N)
587  return;
588  reportBugIfPreconditionHolds(ErrorKind::NilPassedToNonnull, N, nullptr, C,
589  ArgExpr);
590  return;
591  }
592 
593  const MemRegion *Region = getTrackRegion(*ArgSVal);
594  if (!Region)
595  continue;
596 
597  const NullabilityState *TrackedNullability =
598  State->get<NullabilityMap>(Region);
599 
600  if (TrackedNullability) {
601  if (Nullness == NullConstraint::IsNotNull ||
602  TrackedNullability->getValue() != Nullability::Nullable)
603  continue;
604 
605  if (Filter.CheckNullablePassedToNonnull &&
606  RequiredNullability == Nullability::Nonnull) {
607  ExplodedNode *N = C.addTransition(State);
608  reportBugIfPreconditionHolds(ErrorKind::NullablePassedToNonnull, N,
609  Region, C, ArgExpr, /*SuppressPath=*/true);
610  return;
611  }
612  if (Filter.CheckNullableDereferenced &&
613  Param->getType()->isReferenceType()) {
614  ExplodedNode *N = C.addTransition(State);
615  reportBugIfPreconditionHolds(ErrorKind::NullableDereferenced, N, Region,
616  C, ArgExpr, /*SuppressPath=*/true);
617  return;
618  }
619  continue;
620  }
621  // No tracked nullability yet.
622  if (ArgExprTypeLevelNullability != Nullability::Nullable)
623  continue;
624  State = State->set<NullabilityMap>(
625  Region, NullabilityState(ArgExprTypeLevelNullability, ArgExpr));
626  }
627  if (State != OrigState)
628  C.addTransition(State);
629 }
630 
631 /// Suppress the nullability warnings for some functions.
632 void NullabilityChecker::checkPostCall(const CallEvent &Call,
633  CheckerContext &C) const {
634  auto Decl = Call.getDecl();
635  if (!Decl)
636  return;
637  // ObjC Messages handles in a different callback.
638  if (Call.getKind() == CE_ObjCMessage)
639  return;
640  const FunctionType *FuncType = Decl->getFunctionType();
641  if (!FuncType)
642  return;
643  QualType ReturnType = FuncType->getReturnType();
644  if (!ReturnType->isAnyPointerType())
645  return;
646  ProgramStateRef State = C.getState();
647  if (State->get<PreconditionViolated>())
648  return;
649 
650  const MemRegion *Region = getTrackRegion(Call.getReturnValue());
651  if (!Region)
652  return;
653 
654  // CG headers are misannotated. Do not warn for symbols that are the results
655  // of CG calls.
656  const SourceManager &SM = C.getSourceManager();
657  StringRef FilePath = SM.getFilename(SM.getSpellingLoc(Decl->getLocStart()));
658  if (llvm::sys::path::filename(FilePath).startswith("CG")) {
659  State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
660  C.addTransition(State);
661  return;
662  }
663 
664  const NullabilityState *TrackedNullability =
665  State->get<NullabilityMap>(Region);
666 
667  if (!TrackedNullability &&
669  State = State->set<NullabilityMap>(Region, Nullability::Nullable);
670  C.addTransition(State);
671  }
672 }
673 
675  ProgramStateRef State) {
676  if (M.isReceiverSelfOrSuper()) {
677  // For super and super class receivers we assume that the receiver is
678  // nonnull.
679  return Nullability::Nonnull;
680  }
681  // Otherwise look up nullability in the state.
682  SVal Receiver = M.getReceiverSVal();
683  if (auto DefOrUnknown = Receiver.getAs<DefinedOrUnknownSVal>()) {
684  // If the receiver is constrained to be nonnull, assume that it is nonnull
685  // regardless of its type.
686  NullConstraint Nullness = getNullConstraint(*DefOrUnknown, State);
687  if (Nullness == NullConstraint::IsNotNull)
688  return Nullability::Nonnull;
689  }
690  auto ValueRegionSVal = Receiver.getAs<loc::MemRegionVal>();
691  if (ValueRegionSVal) {
692  const MemRegion *SelfRegion = ValueRegionSVal->getRegion();
693  assert(SelfRegion);
694 
695  const NullabilityState *TrackedSelfNullability =
696  State->get<NullabilityMap>(SelfRegion);
697  if (TrackedSelfNullability)
698  return TrackedSelfNullability->getValue();
699  }
701 }
702 
703 /// Calculate the nullability of the result of a message expr based on the
704 /// nullability of the receiver, the nullability of the return value, and the
705 /// constraints.
706 void NullabilityChecker::checkPostObjCMessage(const ObjCMethodCall &M,
707  CheckerContext &C) const {
708  auto Decl = M.getDecl();
709  if (!Decl)
710  return;
711  QualType RetType = Decl->getReturnType();
712  if (!RetType->isAnyPointerType())
713  return;
714 
715  ProgramStateRef State = C.getState();
716  if (State->get<PreconditionViolated>())
717  return;
718 
719  const MemRegion *ReturnRegion = getTrackRegion(M.getReturnValue());
720  if (!ReturnRegion)
721  return;
722 
723  auto Interface = Decl->getClassInterface();
724  auto Name = Interface ? Interface->getName() : "";
725  // In order to reduce the noise in the diagnostics generated by this checker,
726  // some framework and programming style based heuristics are used. These
727  // heuristics are for Cocoa APIs which have NS prefix.
728  if (Name.startswith("NS")) {
729  // Developers rely on dynamic invariants such as an item should be available
730  // in a collection, or a collection is not empty often. Those invariants can
731  // not be inferred by any static analysis tool. To not to bother the users
732  // with too many false positives, every item retrieval function should be
733  // ignored for collections. The instance methods of dictionaries in Cocoa
734  // are either item retrieval related or not interesting nullability wise.
735  // Using this fact, to keep the code easier to read just ignore the return
736  // value of every instance method of dictionaries.
737  if (M.isInstanceMessage() && Name.find("Dictionary") != StringRef::npos) {
738  State =
739  State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
740  C.addTransition(State);
741  return;
742  }
743  // For similar reasons ignore some methods of Cocoa arrays.
744  StringRef FirstSelectorSlot = M.getSelector().getNameForSlot(0);
745  if (Name.find("Array") != StringRef::npos &&
746  (FirstSelectorSlot == "firstObject" ||
747  FirstSelectorSlot == "lastObject")) {
748  State =
749  State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
750  C.addTransition(State);
751  return;
752  }
753 
754  // Encoding related methods of string should not fail when lossless
755  // encodings are used. Using lossless encodings is so frequent that ignoring
756  // this class of methods reduced the emitted diagnostics by about 30% on
757  // some projects (and all of that was false positives).
758  if (Name.find("String") != StringRef::npos) {
759  for (auto Param : M.parameters()) {
760  if (Param->getName() == "encoding") {
761  State = State->set<NullabilityMap>(ReturnRegion,
762  Nullability::Contradicted);
763  C.addTransition(State);
764  return;
765  }
766  }
767  }
768  }
769 
770  const ObjCMessageExpr *Message = M.getOriginExpr();
771  Nullability SelfNullability = getReceiverNullability(M, State);
772 
773  const NullabilityState *NullabilityOfReturn =
774  State->get<NullabilityMap>(ReturnRegion);
775 
776  if (NullabilityOfReturn) {
777  // When we have a nullability tracked for the return value, the nullability
778  // of the expression will be the most nullable of the receiver and the
779  // return value.
780  Nullability RetValTracked = NullabilityOfReturn->getValue();
781  Nullability ComputedNullab =
782  getMostNullable(RetValTracked, SelfNullability);
783  if (ComputedNullab != RetValTracked &&
784  ComputedNullab != Nullability::Unspecified) {
785  const Stmt *NullabilitySource =
786  ComputedNullab == RetValTracked
787  ? NullabilityOfReturn->getNullabilitySource()
788  : Message->getInstanceReceiver();
789  State = State->set<NullabilityMap>(
790  ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
791  C.addTransition(State);
792  }
793  return;
794  }
795 
796  // No tracked information. Use static type information for return value.
797  Nullability RetNullability = getNullabilityAnnotation(RetType);
798 
799  // Properties might be computed. For this reason the static analyzer creates a
800  // new symbol each time an unknown property is read. To avoid false pozitives
801  // do not treat unknown properties as nullable, even when they explicitly
802  // marked nullable.
804  RetNullability = Nullability::Nonnull;
805 
806  Nullability ComputedNullab = getMostNullable(RetNullability, SelfNullability);
807  if (ComputedNullab == Nullability::Nullable) {
808  const Stmt *NullabilitySource = ComputedNullab == RetNullability
809  ? Message
810  : Message->getInstanceReceiver();
811  State = State->set<NullabilityMap>(
812  ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
813  C.addTransition(State);
814  }
815 }
816 
817 /// Explicit casts are trusted. If there is a disagreement in the nullability
818 /// annotations in the destination and the source or '0' is casted to nonnull
819 /// track the value as having contraditory nullability. This will allow users to
820 /// suppress warnings.
821 void NullabilityChecker::checkPostStmt(const ExplicitCastExpr *CE,
822  CheckerContext &C) const {
823  QualType OriginType = CE->getSubExpr()->getType();
824  QualType DestType = CE->getType();
825  if (!OriginType->isAnyPointerType())
826  return;
827  if (!DestType->isAnyPointerType())
828  return;
829 
830  ProgramStateRef State = C.getState();
831  if (State->get<PreconditionViolated>())
832  return;
833 
834  Nullability DestNullability = getNullabilityAnnotation(DestType);
835 
836  // No explicit nullability in the destination type, so this cast does not
837  // change the nullability.
838  if (DestNullability == Nullability::Unspecified)
839  return;
840 
841  auto RegionSVal =
842  State->getSVal(CE, C.getLocationContext()).getAs<DefinedOrUnknownSVal>();
843  const MemRegion *Region = getTrackRegion(*RegionSVal);
844  if (!Region)
845  return;
846 
847  // When 0 is converted to nonnull mark it as contradicted.
848  if (DestNullability == Nullability::Nonnull) {
849  NullConstraint Nullness = getNullConstraint(*RegionSVal, State);
850  if (Nullness == NullConstraint::IsNull) {
851  State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
852  C.addTransition(State);
853  return;
854  }
855  }
856 
857  const NullabilityState *TrackedNullability =
858  State->get<NullabilityMap>(Region);
859 
860  if (!TrackedNullability) {
861  if (DestNullability != Nullability::Nullable)
862  return;
863  State = State->set<NullabilityMap>(Region,
864  NullabilityState(DestNullability, CE));
865  C.addTransition(State);
866  return;
867  }
868 
869  if (TrackedNullability->getValue() != DestNullability &&
870  TrackedNullability->getValue() != Nullability::Contradicted) {
871  State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
872  C.addTransition(State);
873  }
874 }
875 
876 /// For a given statement performing a bind, attempt to syntactically
877 /// match the expression resulting in the bound value.
878 static const Expr * matchValueExprForBind(const Stmt *S) {
879  // For `x = e` the value expression is the right-hand side.
880  if (auto *BinOp = dyn_cast<BinaryOperator>(S)) {
881  if (BinOp->getOpcode() == BO_Assign)
882  return BinOp->getRHS();
883  }
884 
885  // For `int x = e` the value expression is the initializer.
886  if (auto *DS = dyn_cast<DeclStmt>(S)) {
887  if (DS->isSingleDecl()) {
888  auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
889  if (!VD)
890  return nullptr;
891 
892  if (const Expr *Init = VD->getInit())
893  return Init;
894  }
895  }
896 
897  return nullptr;
898 }
899 
900 /// Returns true if \param S is a DeclStmt for a local variable that
901 /// ObjC automated reference counting initialized with zero.
902 static bool isARCNilInitializedLocal(CheckerContext &C, const Stmt *S) {
903  // We suppress diagnostics for ARC zero-initialized _Nonnull locals. This
904  // prevents false positives when a _Nonnull local variable cannot be
905  // initialized with an initialization expression:
906  // NSString * _Nonnull s; // no-warning
907  // @autoreleasepool {
908  // s = ...
909  // }
910  //
911  // FIXME: We should treat implicitly zero-initialized _Nonnull locals as
912  // uninitialized in Sema's UninitializedValues analysis to warn when a use of
913  // the zero-initialized definition will unexpectedly yield nil.
914 
915  // Locals are only zero-initialized when automated reference counting
916  // is turned on.
917  if (!C.getASTContext().getLangOpts().ObjCAutoRefCount)
918  return false;
919 
920  auto *DS = dyn_cast<DeclStmt>(S);
921  if (!DS || !DS->isSingleDecl())
922  return false;
923 
924  auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
925  if (!VD)
926  return false;
927 
928  // Sema only zero-initializes locals with ObjCLifetimes.
929  if(!VD->getType().getQualifiers().hasObjCLifetime())
930  return false;
931 
932  const Expr *Init = VD->getInit();
933  assert(Init && "ObjC local under ARC without initializer");
934 
935  // Return false if the local is explicitly initialized (e.g., with '= nil').
936  if (!isa<ImplicitValueInitExpr>(Init))
937  return false;
938 
939  return true;
940 }
941 
942 /// Propagate the nullability information through binds and warn when nullable
943 /// pointer or null symbol is assigned to a pointer with a nonnull type.
944 void NullabilityChecker::checkBind(SVal L, SVal V, const Stmt *S,
945  CheckerContext &C) const {
946  const TypedValueRegion *TVR =
947  dyn_cast_or_null<TypedValueRegion>(L.getAsRegion());
948  if (!TVR)
949  return;
950 
951  QualType LocType = TVR->getValueType();
952  if (!LocType->isAnyPointerType())
953  return;
954 
955  ProgramStateRef State = C.getState();
956  if (State->get<PreconditionViolated>())
957  return;
958 
959  auto ValDefOrUnknown = V.getAs<DefinedOrUnknownSVal>();
960  if (!ValDefOrUnknown)
961  return;
962 
963  NullConstraint RhsNullness = getNullConstraint(*ValDefOrUnknown, State);
964 
965  Nullability ValNullability = Nullability::Unspecified;
966  if (SymbolRef Sym = ValDefOrUnknown->getAsSymbol())
967  ValNullability = getNullabilityAnnotation(Sym->getType());
968 
969  Nullability LocNullability = getNullabilityAnnotation(LocType);
970  if (Filter.CheckNullPassedToNonnull &&
971  RhsNullness == NullConstraint::IsNull &&
972  ValNullability != Nullability::Nonnull &&
973  LocNullability == Nullability::Nonnull &&
974  !isARCNilInitializedLocal(C, S)) {
975  static CheckerProgramPointTag Tag(this, "NullPassedToNonnull");
976  ExplodedNode *N = C.generateErrorNode(State, &Tag);
977  if (!N)
978  return;
979 
980  const Stmt *ValueExpr = matchValueExprForBind(S);
981  if (!ValueExpr)
982  ValueExpr = S;
983 
984  reportBugIfPreconditionHolds(ErrorKind::NilAssignedToNonnull, N, nullptr, C,
985  ValueExpr);
986  return;
987  }
988  // Intentionally missing case: '0' is bound to a reference. It is handled by
989  // the DereferenceChecker.
990 
991  const MemRegion *ValueRegion = getTrackRegion(*ValDefOrUnknown);
992  if (!ValueRegion)
993  return;
994 
995  const NullabilityState *TrackedNullability =
996  State->get<NullabilityMap>(ValueRegion);
997 
998  if (TrackedNullability) {
999  if (RhsNullness == NullConstraint::IsNotNull ||
1000  TrackedNullability->getValue() != Nullability::Nullable)
1001  return;
1002  if (Filter.CheckNullablePassedToNonnull &&
1003  LocNullability == Nullability::Nonnull) {
1004  static CheckerProgramPointTag Tag(this, "NullablePassedToNonnull");
1005  ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &Tag);
1006  reportBugIfPreconditionHolds(ErrorKind::NullableAssignedToNonnull, N,
1007  ValueRegion, C);
1008  }
1009  return;
1010  }
1011 
1012  const auto *BinOp = dyn_cast<BinaryOperator>(S);
1013 
1014  if (ValNullability == Nullability::Nullable) {
1015  // Trust the static information of the value more than the static
1016  // information on the location.
1017  const Stmt *NullabilitySource = BinOp ? BinOp->getRHS() : S;
1018  State = State->set<NullabilityMap>(
1019  ValueRegion, NullabilityState(ValNullability, NullabilitySource));
1020  C.addTransition(State);
1021  return;
1022  }
1023 
1024  if (LocNullability == Nullability::Nullable) {
1025  const Stmt *NullabilitySource = BinOp ? BinOp->getLHS() : S;
1026  State = State->set<NullabilityMap>(
1027  ValueRegion, NullabilityState(LocNullability, NullabilitySource));
1028  C.addTransition(State);
1029  }
1030 }
1031 
1032 void NullabilityChecker::printState(raw_ostream &Out, ProgramStateRef State,
1033  const char *NL, const char *Sep) const {
1034 
1035  NullabilityMapTy B = State->get<NullabilityMap>();
1036 
1037  if (B.isEmpty())
1038  return;
1039 
1040  Out << Sep << NL;
1041 
1042  for (NullabilityMapTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1043  Out << I->first << " : ";
1044  I->second.print(Out);
1045  Out << NL;
1046  }
1047 }
1048 
1049 #define REGISTER_CHECKER(name, trackingRequired) \
1050  void ento::register##name##Checker(CheckerManager &mgr) { \
1051  NullabilityChecker *checker = mgr.registerChecker<NullabilityChecker>(); \
1052  checker->Filter.Check##name = true; \
1053  checker->Filter.CheckName##name = mgr.getCurrentCheckName(); \
1054  checker->NeedTracking = checker->NeedTracking || trackingRequired; \
1055  }
1056 
1057 // The checks are likely to be turned on by default and it is possible to do
1058 // them without tracking any nullability related information. As an optimization
1059 // no nullability information will be tracked when only these two checks are
1060 // enables.
1061 REGISTER_CHECKER(NullPassedToNonnull, false)
1062 REGISTER_CHECKER(NullReturnedFromNonnull, false)
1063 
1064 REGISTER_CHECKER(NullableDereferenced, true)
1065 REGISTER_CHECKER(NullablePassedToNonnull, true)
1066 REGISTER_CHECKER(NullableReturnedFromNonnull, true)
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
Definition: CallEvent.cpp:213
TypedValueRegion - An abstract class representing regions having a typed value.
Definition: MemRegion.h:510
bool isConstrainedFalse() const
Return true if the constraint is perfectly constrained to 'false'.
A (possibly-)qualified type.
Definition: Type.h:575
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:78
ExplodedNode * generateErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
bool hasDeadSymbols() const
bool isInstanceMessage() const
Definition: CallEvent.h:885
bool operator==(CanQual< T > x, CanQual< U > y)
SourceLocation getSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID. ...
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition: Type.h:2847
A helper class which wraps a boolean value set to false by default.
Definition: Checker.h:542
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
virtual QualType getValueType() const =0
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:77
const RegionTy * getAs() const
Definition: MemRegion.h:1122
The base class of the type hierarchy.
Definition: Type.h:1249
static Nullability getReceiverNullability(const ObjCMethodCall &M, ProgramStateRef State)
VarDecl - An instance of this class is created to represent a variable declaration or definition...
Definition: Decl.h:699
bool isReceiverSelfOrSuper() const
Checks if the receiver refers to 'self' or 'super'.
Definition: CallEvent.cpp:701
ExplodedNode * getPredecessor()
Returns the previous node in the exploded graph, which includes the state of the program before the c...
ParmVarDecl - Represents a parameter to a function.
Definition: Decl.h:1299
const bool wasInlined
If we are post visiting a call, this flag will be set if the call was inlined.
Symbolic value.
Definition: SymbolManager.h:42
static NullConstraint getNullConstraint(DefinedOrUnknownSVal Val, ProgramStateRef State)
const StringRef FilePath
class LLVM_ALIGNAS(8) DependentTemplateSpecializationType const IdentifierInfo * Name
Represents a template specialization type whose template cannot be resolved, e.g. ...
Definition: Type.h:4381
LineState State
AnalysisDeclContext contains the context data for the function or method under analysis.
bool isAnyPointerType() const
Definition: Type.h:5308
This class provides a convenience implementation for clone() using the Curiously-Recurring Template P...
AnalysisDeclContext * getAnalysisDeclContext() const
Expr * getSubExpr()
Definition: Expr.h:2662
BugReporter & getBugReporter()
Values of this type can be null.
Represents any expression that calls an Objective-C method.
Definition: CallEvent.h:849
virtual Kind getKind() const =0
Returns the kind of call this is.
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
Definition: CallEvent.cpp:685
const LangOptions & getLangOpts() const
Definition: ASTContext.h:596
QualType getReturnType() const
Definition: Type.h:2977
Whether values of this type can be null is (explicitly) unspecified.
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:2875
const Decl * getDecl() const
detail::InMemoryDirectory::const_iterator I
We dereferenced a location that may be null.
Definition: Checker.h:527
const LocationContext * getLocationContext() const
ArrayRef< ParmVarDecl * > parameters() const override
Definition: CallEvent.cpp:664
StringRef getFilename(SourceLocation SpellingLoc) const
Return the filename of the file containing a SourceLocation.
ID
Defines the set of possible language-specific address spaces.
Definition: AddressSpaces.h:27
SourceManager & SM
SymbolicRegion - A special, "non-concrete" region.
Definition: MemRegion.h:723
bool isDead(SymbolRef sym) const
Returns whether or not a symbol has been confirmed dead.
virtual const Expr * getArgExpr(unsigned Index) const
Returns the expression associated with a given argument.
Definition: CallEvent.h:241
Expr - This represents one expression.
Definition: Expr.h:104
const ProgramStateRef & getState() const
StringRef getName() const
Return the actual identifier string.
virtual ArrayRef< ParmVarDecl * > parameters() const =0
Return call's formal parameters.
const ProgramStateRef & getState() const
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:86
static SVal getValue(SVal val, SValBuilder &svalBuilder)
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
Definition: Stmt.h:1344
An expression that sends a message to the given Objective-C object or class.
Definition: ExprObjC.h:860
#define REGISTER_CHECKER(name, trackingRequired)
REGISTER_MAP_WITH_PROGRAMSTATE(NullabilityMap, const MemRegion *, NullabilityState) enum class NullConstraint
BugReporter is a utility class for generating PathDiagnostics for analysis.
Definition: BugReporter.h:388
SourceLocation getLocStart() const LLVM_READONLY
Definition: DeclBase.h:377
#define false
Definition: stdbool.h:33
#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type)
Declares a program state trait for type Type called Name, and introduce a typedef named NameTy...
const TemplateArgument * iterator
Definition: Type.h:4070
static bool isARCNilInitializedLocal(CheckerContext &C, const Stmt *S)
Returns true if.
void emitReport(std::unique_ptr< BugReport > R)
Add the given report to the set of reports tracked by BugReporter.
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Definition: Stmt.h:431
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:44
Selector getSelector() const
Definition: CallEvent.h:891
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx)
Definition: Type.h:4095
const Decl * getDecl() const
A class responsible for cleaning up unused symbols.
static const Expr * matchValueExprForBind(const Stmt *S)
For a given statement performing a bind, attempt to syntactically match the expression resulting in t...
const ObjCMethodDecl * getDecl() const override
Definition: CallEvent.h:875
virtual const Decl * getDecl() const
Returns the declaration of the function or method that will be called.
Definition: CallEvent.h:178
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
Definition: ExprObjC.h:1155
QualType getType() const
Definition: Expr.h:125
const FunctionType * getFunctionType(bool BlocksToo=true) const
Looks through the Decl's underlying type to extract a FunctionType when possible. ...
Definition: DeclBase.cpp:775
detail::InMemoryDirectory::const_iterator E
const MemRegion * getAsRegion() const
Definition: SVals.cpp:135
const Expr * getRetValue() const
Definition: Stmt.cpp:888
bool isConstrainedTrue() const
Return true if the constraint is perfectly constrained to 'true'.
Represents an abstract call to a function or method along a particular path.
Definition: CallEvent.h:113
ExplicitCastExpr - An explicit cast written in the source code.
Definition: Expr.h:2778
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
Definition: ProgramPoint.h:150
ObjCMessageKind getMessageKind() const
Returns how the message was written in the source (property access, subscript, or explicit message se...
Definition: CallEvent.cpp:733
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:5675
static bool checkParamsForPreconditionViolation(const ParamVarDeclRange &Params, ProgramStateRef State, const LocationContext *LocCtxt)
static Nullability getNullabilityAnnotation(QualType Type)
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
Definition: SemaDecl.cpp:11761
An attributed type is a type to which a type attribute has been applied.
Definition: Type.h:3598
static bool checkPreconditionViolation(ProgramStateRef State, ExplodedNode *N, CheckerContext &C)
bool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R, bool IsArg=false, bool EnableNullFPSuppression=true)
Attempts to add visitors to trace a null or undefined value back to its point of origin, whether it is a symbol constrained to null or an explicit assignment.
SourceManager & getSourceManager()
virtual unsigned getNumArgs() const =0
Returns the number of arguments (explicit and implicit).
ElementRegin is used to represent both array elements and casts.
Definition: MemRegion.h:1020
#define true
Definition: stdbool.h:32
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
Definition: Checker.h:484
This class provides an interface through which checkers can create individual bug reports...
Definition: BugReporter.h:55
virtual const ObjCMessageExpr * getOriginExpr() const
Definition: CallEvent.h:872
SVal getReturnValue() const
Returns the return value of the call.
Definition: CallEvent.cpp:227
This class handles loading and caching of source files into memory.
SourceManager & getSourceManager()
Definition: BugReporter.h:550
const LocationContext * getLocationContext() const