clang  10.0.0svn
BasicObjCFoundationChecks.cpp
Go to the documentation of this file.
1 //== BasicObjCFoundationChecks.cpp - Simple Apple-Foundation checks -*- C++ -*--
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 BasicObjCFoundationChecks, a class that encapsulates
10 // a set of simple checks to run on Objective-C code using Apple's Foundation
11 // classes.
12 //
13 //===----------------------------------------------------------------------===//
14 
16 #include "clang/AST/ASTContext.h"
17 #include "clang/AST/DeclObjC.h"
18 #include "clang/AST/Expr.h"
19 #include "clang/AST/ExprObjC.h"
20 #include "clang/AST/StmtObjC.h"
32 #include "llvm/ADT/SmallString.h"
33 #include "llvm/ADT/StringMap.h"
34 #include "llvm/Support/raw_ostream.h"
35 
36 using namespace clang;
37 using namespace ento;
38 using namespace llvm;
39 
40 namespace {
41 class APIMisuse : public BugType {
42 public:
43  APIMisuse(const CheckerBase *checker, const char *name)
44  : BugType(checker, name, "API Misuse (Apple)") {}
45 };
46 } // end anonymous namespace
47 
48 //===----------------------------------------------------------------------===//
49 // Utility functions.
50 //===----------------------------------------------------------------------===//
51 
52 static StringRef GetReceiverInterfaceName(const ObjCMethodCall &msg) {
53  if (const ObjCInterfaceDecl *ID = msg.getReceiverInterface())
54  return ID->getIdentifier()->getName();
55  return StringRef();
56 }
57 
67 };
68 
70  bool IncludeSuperclasses = true) {
71  static llvm::StringMap<FoundationClass> Classes;
72  if (Classes.empty()) {
73  Classes["NSArray"] = FC_NSArray;
74  Classes["NSDictionary"] = FC_NSDictionary;
75  Classes["NSEnumerator"] = FC_NSEnumerator;
76  Classes["NSNull"] = FC_NSNull;
77  Classes["NSOrderedSet"] = FC_NSOrderedSet;
78  Classes["NSSet"] = FC_NSSet;
79  Classes["NSString"] = FC_NSString;
80  }
81 
82  // FIXME: Should we cache this at all?
83  FoundationClass result = Classes.lookup(ID->getIdentifier()->getName());
84  if (result == FC_None && IncludeSuperclasses)
85  if (const ObjCInterfaceDecl *Super = ID->getSuperClass())
86  return findKnownClass(Super);
87 
88  return result;
89 }
90 
91 //===----------------------------------------------------------------------===//
92 // NilArgChecker - Check for prohibited nil arguments to ObjC method calls.
93 //===----------------------------------------------------------------------===//
94 
95 namespace {
96  class NilArgChecker : public Checker<check::PreObjCMessage,
97  check::PostStmt<ObjCDictionaryLiteral>,
98  check::PostStmt<ObjCArrayLiteral> > {
99  mutable std::unique_ptr<APIMisuse> BT;
100 
101  mutable llvm::SmallDenseMap<Selector, unsigned, 16> StringSelectors;
102  mutable Selector ArrayWithObjectSel;
103  mutable Selector AddObjectSel;
104  mutable Selector InsertObjectAtIndexSel;
105  mutable Selector ReplaceObjectAtIndexWithObjectSel;
106  mutable Selector SetObjectAtIndexedSubscriptSel;
107  mutable Selector ArrayByAddingObjectSel;
108  mutable Selector DictionaryWithObjectForKeySel;
109  mutable Selector SetObjectForKeySel;
110  mutable Selector SetObjectForKeyedSubscriptSel;
111  mutable Selector RemoveObjectForKeySel;
112 
113  void warnIfNilExpr(const Expr *E,
114  const char *Msg,
115  CheckerContext &C) const;
116 
117  void warnIfNilArg(CheckerContext &C,
118  const ObjCMethodCall &msg, unsigned Arg,
119  FoundationClass Class,
120  bool CanBeSubscript = false) const;
121 
122  void generateBugReport(ExplodedNode *N,
123  StringRef Msg,
124  SourceRange Range,
125  const Expr *Expr,
126  CheckerContext &C) const;
127 
128  public:
129  void checkPreObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
130  void checkPostStmt(const ObjCDictionaryLiteral *DL,
131  CheckerContext &C) const;
132  void checkPostStmt(const ObjCArrayLiteral *AL,
133  CheckerContext &C) const;
134  };
135 } // end anonymous namespace
136 
137 void NilArgChecker::warnIfNilExpr(const Expr *E,
138  const char *Msg,
139  CheckerContext &C) const {
140  ProgramStateRef State = C.getState();
141  if (State->isNull(C.getSVal(E)).isConstrainedTrue()) {
142 
143  if (ExplodedNode *N = C.generateErrorNode()) {
144  generateBugReport(N, Msg, E->getSourceRange(), E, C);
145  }
146  }
147 }
148 
149 void NilArgChecker::warnIfNilArg(CheckerContext &C,
150  const ObjCMethodCall &msg,
151  unsigned int Arg,
152  FoundationClass Class,
153  bool CanBeSubscript) const {
154  // Check if the argument is nil.
155  ProgramStateRef State = C.getState();
156  if (!State->isNull(msg.getArgSVal(Arg)).isConstrainedTrue())
157  return;
158 
159  // NOTE: We cannot throw non-fatal errors from warnIfNilExpr,
160  // because it's called multiple times from some callers, so it'd cause
161  // an unwanted state split if two or more non-fatal errors are thrown
162  // within the same checker callback. For now we don't want to, but
163  // it'll need to be fixed if we ever want to.
164  if (ExplodedNode *N = C.generateErrorNode()) {
165  SmallString<128> sbuf;
166  llvm::raw_svector_ostream os(sbuf);
167 
168  if (CanBeSubscript && msg.getMessageKind() == OCM_Subscript) {
169 
170  if (Class == FC_NSArray) {
171  os << "Array element cannot be nil";
172  } else if (Class == FC_NSDictionary) {
173  if (Arg == 0) {
174  os << "Value stored into '";
175  os << GetReceiverInterfaceName(msg) << "' cannot be nil";
176  } else {
177  assert(Arg == 1);
178  os << "'"<< GetReceiverInterfaceName(msg) << "' key cannot be nil";
179  }
180  } else
181  llvm_unreachable("Missing foundation class for the subscript expr");
182 
183  } else {
184  if (Class == FC_NSDictionary) {
185  if (Arg == 0)
186  os << "Value argument ";
187  else {
188  assert(Arg == 1);
189  os << "Key argument ";
190  }
191  os << "to '";
192  msg.getSelector().print(os);
193  os << "' cannot be nil";
194  } else {
195  os << "Argument to '" << GetReceiverInterfaceName(msg) << "' method '";
196  msg.getSelector().print(os);
197  os << "' cannot be nil";
198  }
199  }
200 
201  generateBugReport(N, os.str(), msg.getArgSourceRange(Arg),
202  msg.getArgExpr(Arg), C);
203  }
204 }
205 
206 void NilArgChecker::generateBugReport(ExplodedNode *N,
207  StringRef Msg,
208  SourceRange Range,
209  const Expr *E,
210  CheckerContext &C) const {
211  if (!BT)
212  BT.reset(new APIMisuse(this, "nil argument"));
213 
214  auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
215  R->addRange(Range);
216  bugreporter::trackExpressionValue(N, E, *R);
217  C.emitReport(std::move(R));
218 }
219 
220 void NilArgChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
221  CheckerContext &C) const {
223  if (!ID)
224  return;
225 
226  FoundationClass Class = findKnownClass(ID);
227 
228  static const unsigned InvalidArgIndex = UINT_MAX;
229  unsigned Arg = InvalidArgIndex;
230  bool CanBeSubscript = false;
231 
232  if (Class == FC_NSString) {
233  Selector S = msg.getSelector();
234 
235  if (S.isUnarySelector())
236  return;
237 
238  if (StringSelectors.empty()) {
239  ASTContext &Ctx = C.getASTContext();
240  Selector Sels[] = {
241  getKeywordSelector(Ctx, "caseInsensitiveCompare"),
242  getKeywordSelector(Ctx, "compare"),
243  getKeywordSelector(Ctx, "compare", "options"),
244  getKeywordSelector(Ctx, "compare", "options", "range"),
245  getKeywordSelector(Ctx, "compare", "options", "range", "locale"),
246  getKeywordSelector(Ctx, "componentsSeparatedByCharactersInSet"),
247  getKeywordSelector(Ctx, "initWithFormat"),
248  getKeywordSelector(Ctx, "localizedCaseInsensitiveCompare"),
249  getKeywordSelector(Ctx, "localizedCompare"),
250  getKeywordSelector(Ctx, "localizedStandardCompare"),
251  };
252  for (Selector KnownSel : Sels)
253  StringSelectors[KnownSel] = 0;
254  }
255  auto I = StringSelectors.find(S);
256  if (I == StringSelectors.end())
257  return;
258  Arg = I->second;
259  } else if (Class == FC_NSArray) {
260  Selector S = msg.getSelector();
261 
262  if (S.isUnarySelector())
263  return;
264 
265  if (ArrayWithObjectSel.isNull()) {
266  ASTContext &Ctx = C.getASTContext();
267  ArrayWithObjectSel = getKeywordSelector(Ctx, "arrayWithObject");
268  AddObjectSel = getKeywordSelector(Ctx, "addObject");
269  InsertObjectAtIndexSel =
270  getKeywordSelector(Ctx, "insertObject", "atIndex");
271  ReplaceObjectAtIndexWithObjectSel =
272  getKeywordSelector(Ctx, "replaceObjectAtIndex", "withObject");
273  SetObjectAtIndexedSubscriptSel =
274  getKeywordSelector(Ctx, "setObject", "atIndexedSubscript");
275  ArrayByAddingObjectSel = getKeywordSelector(Ctx, "arrayByAddingObject");
276  }
277 
278  if (S == ArrayWithObjectSel || S == AddObjectSel ||
279  S == InsertObjectAtIndexSel || S == ArrayByAddingObjectSel) {
280  Arg = 0;
281  } else if (S == SetObjectAtIndexedSubscriptSel) {
282  Arg = 0;
283  CanBeSubscript = true;
284  } else if (S == ReplaceObjectAtIndexWithObjectSel) {
285  Arg = 1;
286  }
287  } else if (Class == FC_NSDictionary) {
288  Selector S = msg.getSelector();
289 
290  if (S.isUnarySelector())
291  return;
292 
293  if (DictionaryWithObjectForKeySel.isNull()) {
294  ASTContext &Ctx = C.getASTContext();
295  DictionaryWithObjectForKeySel =
296  getKeywordSelector(Ctx, "dictionaryWithObject", "forKey");
297  SetObjectForKeySel = getKeywordSelector(Ctx, "setObject", "forKey");
298  SetObjectForKeyedSubscriptSel =
299  getKeywordSelector(Ctx, "setObject", "forKeyedSubscript");
300  RemoveObjectForKeySel = getKeywordSelector(Ctx, "removeObjectForKey");
301  }
302 
303  if (S == DictionaryWithObjectForKeySel || S == SetObjectForKeySel) {
304  Arg = 0;
305  warnIfNilArg(C, msg, /* Arg */1, Class);
306  } else if (S == SetObjectForKeyedSubscriptSel) {
307  CanBeSubscript = true;
308  Arg = 1;
309  } else if (S == RemoveObjectForKeySel) {
310  Arg = 0;
311  }
312  }
313 
314  // If argument is '0', report a warning.
315  if ((Arg != InvalidArgIndex))
316  warnIfNilArg(C, msg, Arg, Class, CanBeSubscript);
317 }
318 
319 void NilArgChecker::checkPostStmt(const ObjCArrayLiteral *AL,
320  CheckerContext &C) const {
321  unsigned NumOfElements = AL->getNumElements();
322  for (unsigned i = 0; i < NumOfElements; ++i) {
323  warnIfNilExpr(AL->getElement(i), "Array element cannot be nil", C);
324  }
325 }
326 
327 void NilArgChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
328  CheckerContext &C) const {
329  unsigned NumOfElements = DL->getNumElements();
330  for (unsigned i = 0; i < NumOfElements; ++i) {
331  ObjCDictionaryElement Element = DL->getKeyValueElement(i);
332  warnIfNilExpr(Element.Key, "Dictionary key cannot be nil", C);
333  warnIfNilExpr(Element.Value, "Dictionary value cannot be nil", C);
334  }
335 }
336 
337 //===----------------------------------------------------------------------===//
338 // Checking for mismatched types passed to CFNumberCreate/CFNumberGetValue.
339 //===----------------------------------------------------------------------===//
340 
341 namespace {
342 class CFNumberChecker : public Checker< check::PreStmt<CallExpr> > {
343  mutable std::unique_ptr<APIMisuse> BT;
344  mutable IdentifierInfo *ICreate, *IGetValue;
345 public:
346  CFNumberChecker() : ICreate(nullptr), IGetValue(nullptr) {}
347 
348  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
349 
350 private:
351  void EmitError(const TypedRegion* R, const Expr *Ex,
352  uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind);
353 };
354 } // end anonymous namespace
355 
373 };
374 
376  static const unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 };
377 
378  if (i < kCFNumberCharType)
379  return FixedSize[i-1];
380 
381  QualType T;
382 
383  switch (i) {
384  case kCFNumberCharType: T = Ctx.CharTy; break;
385  case kCFNumberShortType: T = Ctx.ShortTy; break;
386  case kCFNumberIntType: T = Ctx.IntTy; break;
387  case kCFNumberLongType: T = Ctx.LongTy; break;
388  case kCFNumberLongLongType: T = Ctx.LongLongTy; break;
389  case kCFNumberFloatType: T = Ctx.FloatTy; break;
390  case kCFNumberDoubleType: T = Ctx.DoubleTy; break;
394  // FIXME: We need a way to map from names to Type*.
395  default:
396  return None;
397  }
398 
399  return Ctx.getTypeSize(T);
400 }
401 
402 #if 0
403 static const char* GetCFNumberTypeStr(uint64_t i) {
404  static const char* Names[] = {
405  "kCFNumberSInt8Type",
406  "kCFNumberSInt16Type",
407  "kCFNumberSInt32Type",
408  "kCFNumberSInt64Type",
409  "kCFNumberFloat32Type",
410  "kCFNumberFloat64Type",
411  "kCFNumberCharType",
412  "kCFNumberShortType",
413  "kCFNumberIntType",
414  "kCFNumberLongType",
415  "kCFNumberLongLongType",
416  "kCFNumberFloatType",
417  "kCFNumberDoubleType",
418  "kCFNumberCFIndexType",
419  "kCFNumberNSIntegerType",
420  "kCFNumberCGFloatType"
421  };
422 
423  return i <= kCFNumberCGFloatType ? Names[i-1] : "Invalid CFNumberType";
424 }
425 #endif
426 
427 void CFNumberChecker::checkPreStmt(const CallExpr *CE,
428  CheckerContext &C) const {
429  ProgramStateRef state = C.getState();
430  const FunctionDecl *FD = C.getCalleeDecl(CE);
431  if (!FD)
432  return;
433 
434  ASTContext &Ctx = C.getASTContext();
435  if (!ICreate) {
436  ICreate = &Ctx.Idents.get("CFNumberCreate");
437  IGetValue = &Ctx.Idents.get("CFNumberGetValue");
438  }
439  if (!(FD->getIdentifier() == ICreate || FD->getIdentifier() == IGetValue) ||
440  CE->getNumArgs() != 3)
441  return;
442 
443  // Get the value of the "theType" argument.
444  SVal TheTypeVal = C.getSVal(CE->getArg(1));
445 
446  // FIXME: We really should allow ranges of valid theType values, and
447  // bifurcate the state appropriately.
448  Optional<nonloc::ConcreteInt> V = TheTypeVal.getAs<nonloc::ConcreteInt>();
449  if (!V)
450  return;
451 
452  uint64_t NumberKind = V->getValue().getLimitedValue();
453  Optional<uint64_t> OptCFNumberSize = GetCFNumberSize(Ctx, NumberKind);
454 
455  // FIXME: In some cases we can emit an error.
456  if (!OptCFNumberSize)
457  return;
458 
459  uint64_t CFNumberSize = *OptCFNumberSize;
460 
461  // Look at the value of the integer being passed by reference. Essentially
462  // we want to catch cases where the value passed in is not equal to the
463  // size of the type being created.
464  SVal TheValueExpr = C.getSVal(CE->getArg(2));
465 
466  // FIXME: Eventually we should handle arbitrary locations. We can do this
467  // by having an enhanced memory model that does low-level typing.
468  Optional<loc::MemRegionVal> LV = TheValueExpr.getAs<loc::MemRegionVal>();
469  if (!LV)
470  return;
471 
472  const TypedValueRegion* R = dyn_cast<TypedValueRegion>(LV->stripCasts());
473  if (!R)
474  return;
475 
476  QualType T = Ctx.getCanonicalType(R->getValueType());
477 
478  // FIXME: If the pointee isn't an integer type, should we flag a warning?
479  // People can do weird stuff with pointers.
480 
481  if (!T->isIntegralOrEnumerationType())
482  return;
483 
484  uint64_t PrimitiveTypeSize = Ctx.getTypeSize(T);
485 
486  if (PrimitiveTypeSize == CFNumberSize)
487  return;
488 
489  // FIXME: We can actually create an abstract "CFNumber" object that has
490  // the bits initialized to the provided values.
491  ExplodedNode *N = C.generateNonFatalErrorNode();
492  if (N) {
493  SmallString<128> sbuf;
494  llvm::raw_svector_ostream os(sbuf);
495  bool isCreate = (FD->getIdentifier() == ICreate);
496 
497  if (isCreate) {
498  os << (PrimitiveTypeSize == 8 ? "An " : "A ")
499  << PrimitiveTypeSize << "-bit integer is used to initialize a "
500  << "CFNumber object that represents "
501  << (CFNumberSize == 8 ? "an " : "a ")
502  << CFNumberSize << "-bit integer; ";
503  } else {
504  os << "A CFNumber object that represents "
505  << (CFNumberSize == 8 ? "an " : "a ")
506  << CFNumberSize << "-bit integer is used to initialize "
507  << (PrimitiveTypeSize == 8 ? "an " : "a ")
508  << PrimitiveTypeSize << "-bit integer; ";
509  }
510 
511  if (PrimitiveTypeSize < CFNumberSize)
512  os << (CFNumberSize - PrimitiveTypeSize)
513  << " bits of the CFNumber value will "
514  << (isCreate ? "be garbage." : "overwrite adjacent storage.");
515  else
516  os << (PrimitiveTypeSize - CFNumberSize)
517  << " bits of the integer value will be "
518  << (isCreate ? "lost." : "garbage.");
519 
520  if (!BT)
521  BT.reset(new APIMisuse(this, "Bad use of CFNumber APIs"));
522 
523  auto report = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
524  report->addRange(CE->getArg(2)->getSourceRange());
525  C.emitReport(std::move(report));
526  }
527 }
528 
529 //===----------------------------------------------------------------------===//
530 // CFRetain/CFRelease/CFMakeCollectable/CFAutorelease checking for null arguments.
531 //===----------------------------------------------------------------------===//
532 
533 namespace {
534 class CFRetainReleaseChecker : public Checker<check::PreCall> {
535  mutable APIMisuse BT{this, "null passed to CF memory management function"};
536  CallDescription CFRetain{"CFRetain", 1},
537  CFRelease{"CFRelease", 1},
538  CFMakeCollectable{"CFMakeCollectable", 1},
539  CFAutorelease{"CFAutorelease", 1};
540 
541 public:
542  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
543 };
544 } // end anonymous namespace
545 
546 void CFRetainReleaseChecker::checkPreCall(const CallEvent &Call,
547  CheckerContext &C) const {
548  // TODO: Make this check part of CallDescription.
549  if (!Call.isGlobalCFunction())
550  return;
551 
552  // Check if we called CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
553  if (!(Call.isCalled(CFRetain) || Call.isCalled(CFRelease) ||
554  Call.isCalled(CFMakeCollectable) || Call.isCalled(CFAutorelease)))
555  return;
556 
557  // Get the argument's value.
558  SVal ArgVal = Call.getArgSVal(0);
559  Optional<DefinedSVal> DefArgVal = ArgVal.getAs<DefinedSVal>();
560  if (!DefArgVal)
561  return;
562 
563  // Is it null?
564  ProgramStateRef state = C.getState();
565  ProgramStateRef stateNonNull, stateNull;
566  std::tie(stateNonNull, stateNull) = state->assume(*DefArgVal);
567 
568  if (!stateNonNull) {
569  ExplodedNode *N = C.generateErrorNode(stateNull);
570  if (!N)
571  return;
572 
573  SmallString<64> Str;
574  raw_svector_ostream OS(Str);
575  OS << "Null pointer argument in call to "
576  << cast<FunctionDecl>(Call.getDecl())->getName();
577 
578  auto report = std::make_unique<PathSensitiveBugReport>(BT, OS.str(), N);
579  report->addRange(Call.getArgSourceRange(0));
580  bugreporter::trackExpressionValue(N, Call.getArgExpr(0), *report);
581  C.emitReport(std::move(report));
582  return;
583  }
584 
585  // From here on, we know the argument is non-null.
586  C.addTransition(stateNonNull);
587 }
588 
589 //===----------------------------------------------------------------------===//
590 // Check for sending 'retain', 'release', or 'autorelease' directly to a Class.
591 //===----------------------------------------------------------------------===//
592 
593 namespace {
594 class ClassReleaseChecker : public Checker<check::PreObjCMessage> {
595  mutable Selector releaseS;
596  mutable Selector retainS;
597  mutable Selector autoreleaseS;
598  mutable Selector drainS;
599  mutable std::unique_ptr<BugType> BT;
600 
601 public:
602  void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
603 };
604 } // end anonymous namespace
605 
606 void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
607  CheckerContext &C) const {
608  if (!BT) {
609  BT.reset(new APIMisuse(
610  this, "message incorrectly sent to class instead of class instance"));
611 
612  ASTContext &Ctx = C.getASTContext();
613  releaseS = GetNullarySelector("release", Ctx);
614  retainS = GetNullarySelector("retain", Ctx);
615  autoreleaseS = GetNullarySelector("autorelease", Ctx);
616  drainS = GetNullarySelector("drain", Ctx);
617  }
618 
619  if (msg.isInstanceMessage())
620  return;
621  const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
622  assert(Class);
623 
624  Selector S = msg.getSelector();
625  if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
626  return;
627 
628  if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
629  SmallString<200> buf;
630  llvm::raw_svector_ostream os(buf);
631 
632  os << "The '";
633  S.print(os);
634  os << "' message should be sent to instances "
635  "of class '" << Class->getName()
636  << "' and not the class directly";
637 
638  auto report = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
639  report->addRange(msg.getSourceRange());
640  C.emitReport(std::move(report));
641  }
642 }
643 
644 //===----------------------------------------------------------------------===//
645 // Check for passing non-Objective-C types to variadic methods that expect
646 // only Objective-C types.
647 //===----------------------------------------------------------------------===//
648 
649 namespace {
650 class VariadicMethodTypeChecker : public Checker<check::PreObjCMessage> {
651  mutable Selector arrayWithObjectsS;
652  mutable Selector dictionaryWithObjectsAndKeysS;
653  mutable Selector setWithObjectsS;
654  mutable Selector orderedSetWithObjectsS;
655  mutable Selector initWithObjectsS;
656  mutable Selector initWithObjectsAndKeysS;
657  mutable std::unique_ptr<BugType> BT;
658 
659  bool isVariadicMessage(const ObjCMethodCall &msg) const;
660 
661 public:
662  void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
663 };
664 } // end anonymous namespace
665 
666 /// isVariadicMessage - Returns whether the given message is a variadic message,
667 /// where all arguments must be Objective-C types.
668 bool
669 VariadicMethodTypeChecker::isVariadicMessage(const ObjCMethodCall &msg) const {
670  const ObjCMethodDecl *MD = msg.getDecl();
671 
672  if (!MD || !MD->isVariadic() || isa<ObjCProtocolDecl>(MD->getDeclContext()))
673  return false;
674 
675  Selector S = msg.getSelector();
676 
677  if (msg.isInstanceMessage()) {
678  // FIXME: Ideally we'd look at the receiver interface here, but that's not
679  // useful for init, because alloc returns 'id'. In theory, this could lead
680  // to false positives, for example if there existed a class that had an
681  // initWithObjects: implementation that does accept non-Objective-C pointer
682  // types, but the chance of that happening is pretty small compared to the
683  // gains that this analysis gives.
684  const ObjCInterfaceDecl *Class = MD->getClassInterface();
685 
686  switch (findKnownClass(Class)) {
687  case FC_NSArray:
688  case FC_NSOrderedSet:
689  case FC_NSSet:
690  return S == initWithObjectsS;
691  case FC_NSDictionary:
692  return S == initWithObjectsAndKeysS;
693  default:
694  return false;
695  }
696  } else {
697  const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
698 
699  switch (findKnownClass(Class)) {
700  case FC_NSArray:
701  return S == arrayWithObjectsS;
702  case FC_NSOrderedSet:
703  return S == orderedSetWithObjectsS;
704  case FC_NSSet:
705  return S == setWithObjectsS;
706  case FC_NSDictionary:
707  return S == dictionaryWithObjectsAndKeysS;
708  default:
709  return false;
710  }
711  }
712 }
713 
714 void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
715  CheckerContext &C) const {
716  if (!BT) {
717  BT.reset(new APIMisuse(this,
718  "Arguments passed to variadic method aren't all "
719  "Objective-C pointer types"));
720 
721  ASTContext &Ctx = C.getASTContext();
722  arrayWithObjectsS = GetUnarySelector("arrayWithObjects", Ctx);
723  dictionaryWithObjectsAndKeysS =
724  GetUnarySelector("dictionaryWithObjectsAndKeys", Ctx);
725  setWithObjectsS = GetUnarySelector("setWithObjects", Ctx);
726  orderedSetWithObjectsS = GetUnarySelector("orderedSetWithObjects", Ctx);
727 
728  initWithObjectsS = GetUnarySelector("initWithObjects", Ctx);
729  initWithObjectsAndKeysS = GetUnarySelector("initWithObjectsAndKeys", Ctx);
730  }
731 
732  if (!isVariadicMessage(msg))
733  return;
734 
735  // We are not interested in the selector arguments since they have
736  // well-defined types, so the compiler will issue a warning for them.
737  unsigned variadicArgsBegin = msg.getSelector().getNumArgs();
738 
739  // We're not interested in the last argument since it has to be nil or the
740  // compiler would have issued a warning for it elsewhere.
741  unsigned variadicArgsEnd = msg.getNumArgs() - 1;
742 
743  if (variadicArgsEnd <= variadicArgsBegin)
744  return;
745 
746  // Verify that all arguments have Objective-C types.
747  Optional<ExplodedNode*> errorNode;
748 
749  for (unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) {
750  QualType ArgTy = msg.getArgExpr(I)->getType();
751  if (ArgTy->isObjCObjectPointerType())
752  continue;
753 
754  // Block pointers are treaded as Objective-C pointers.
755  if (ArgTy->isBlockPointerType())
756  continue;
757 
758  // Ignore pointer constants.
759  if (msg.getArgSVal(I).getAs<loc::ConcreteInt>())
760  continue;
761 
762  // Ignore pointer types annotated with 'NSObject' attribute.
763  if (C.getASTContext().isObjCNSObjectType(ArgTy))
764  continue;
765 
766  // Ignore CF references, which can be toll-free bridged.
768  continue;
769 
770  // Generate only one error node to use for all bug reports.
771  if (!errorNode.hasValue())
772  errorNode = C.generateNonFatalErrorNode();
773 
774  if (!errorNode.getValue())
775  continue;
776 
777  SmallString<128> sbuf;
778  llvm::raw_svector_ostream os(sbuf);
779 
780  StringRef TypeName = GetReceiverInterfaceName(msg);
781  if (!TypeName.empty())
782  os << "Argument to '" << TypeName << "' method '";
783  else
784  os << "Argument to method '";
785 
786  msg.getSelector().print(os);
787  os << "' should be an Objective-C pointer type, not '";
788  ArgTy.print(os, C.getLangOpts());
789  os << "'";
790 
791  auto R = std::make_unique<PathSensitiveBugReport>(*BT, os.str(),
792  errorNode.getValue());
793  R->addRange(msg.getArgSourceRange(I));
794  C.emitReport(std::move(R));
795  }
796 }
797 
798 //===----------------------------------------------------------------------===//
799 // Improves the modeling of loops over Cocoa collections.
800 //===----------------------------------------------------------------------===//
801 
802 // The map from container symbol to the container count symbol.
803 // We currently will remember the last container count symbol encountered.
805 REGISTER_MAP_WITH_PROGRAMSTATE(ContainerNonEmptyMap, SymbolRef, bool)
806 
807 namespace {
808 class ObjCLoopChecker
809  : public Checker<check::PostStmt<ObjCForCollectionStmt>,
810  check::PostObjCMessage,
811  check::DeadSymbols,
812  check::PointerEscape > {
813  mutable IdentifierInfo *CountSelectorII;
814 
815  bool isCollectionCountMethod(const ObjCMethodCall &M,
816  CheckerContext &C) const;
817 
818 public:
819  ObjCLoopChecker() : CountSelectorII(nullptr) {}
820  void checkPostStmt(const ObjCForCollectionStmt *FCS, CheckerContext &C) const;
821  void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
822  void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
823  ProgramStateRef checkPointerEscape(ProgramStateRef State,
824  const InvalidatedSymbols &Escaped,
825  const CallEvent *Call,
826  PointerEscapeKind Kind) const;
827 };
828 } // end anonymous namespace
829 
832  if (!PT)
833  return false;
834 
835  const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
836  if (!ID)
837  return false;
838 
839  switch (findKnownClass(ID)) {
840  case FC_NSArray:
841  case FC_NSDictionary:
842  case FC_NSEnumerator:
843  case FC_NSOrderedSet:
844  case FC_NSSet:
845  return true;
846  default:
847  return false;
848  }
849 }
850 
851 /// Assumes that the collection is non-nil.
852 ///
853 /// If the collection is known to be nil, returns NULL to indicate an infeasible
854 /// path.
855 static ProgramStateRef checkCollectionNonNil(CheckerContext &C,
857  const ObjCForCollectionStmt *FCS) {
858  if (!State)
859  return nullptr;
860 
861  SVal CollectionVal = C.getSVal(FCS->getCollection());
862  Optional<DefinedSVal> KnownCollection = CollectionVal.getAs<DefinedSVal>();
863  if (!KnownCollection)
864  return State;
865 
866  ProgramStateRef StNonNil, StNil;
867  std::tie(StNonNil, StNil) = State->assume(*KnownCollection);
868  if (StNil && !StNonNil) {
869  // The collection is nil. This path is infeasible.
870  return nullptr;
871  }
872 
873  return StNonNil;
874 }
875 
876 /// Assumes that the collection elements are non-nil.
877 ///
878 /// This only applies if the collection is one of those known not to contain
879 /// nil values.
880 static ProgramStateRef checkElementNonNil(CheckerContext &C,
882  const ObjCForCollectionStmt *FCS) {
883  if (!State)
884  return nullptr;
885 
886  // See if the collection is one where we /know/ the elements are non-nil.
888  return State;
889 
890  const LocationContext *LCtx = C.getLocationContext();
891  const Stmt *Element = FCS->getElement();
892 
893  // FIXME: Copied from ExprEngineObjC.
894  Optional<Loc> ElementLoc;
895  if (const DeclStmt *DS = dyn_cast<DeclStmt>(Element)) {
896  const VarDecl *ElemDecl = cast<VarDecl>(DS->getSingleDecl());
897  assert(ElemDecl->getInit() == nullptr);
898  ElementLoc = State->getLValue(ElemDecl, LCtx);
899  } else {
900  ElementLoc = State->getSVal(Element, LCtx).getAs<Loc>();
901  }
902 
903  if (!ElementLoc)
904  return State;
905 
906  // Go ahead and assume the value is non-nil.
907  SVal Val = State->getSVal(*ElementLoc);
908  return State->assume(Val.castAs<DefinedOrUnknownSVal>(), true);
909 }
910 
911 /// Returns NULL state if the collection is known to contain elements
912 /// (or is known not to contain elements if the Assumption parameter is false.)
913 static ProgramStateRef
915  SymbolRef CollectionS, bool Assumption) {
916  if (!State || !CollectionS)
917  return State;
918 
919  const SymbolRef *CountS = State->get<ContainerCountMap>(CollectionS);
920  if (!CountS) {
921  const bool *KnownNonEmpty = State->get<ContainerNonEmptyMap>(CollectionS);
922  if (!KnownNonEmpty)
923  return State->set<ContainerNonEmptyMap>(CollectionS, Assumption);
924  return (Assumption == *KnownNonEmpty) ? State : nullptr;
925  }
926 
927  SValBuilder &SvalBuilder = C.getSValBuilder();
928  SVal CountGreaterThanZeroVal =
929  SvalBuilder.evalBinOp(State, BO_GT,
930  nonloc::SymbolVal(*CountS),
931  SvalBuilder.makeIntVal(0, (*CountS)->getType()),
932  SvalBuilder.getConditionType());
933  Optional<DefinedSVal> CountGreaterThanZero =
934  CountGreaterThanZeroVal.getAs<DefinedSVal>();
935  if (!CountGreaterThanZero) {
936  // The SValBuilder cannot construct a valid SVal for this condition.
937  // This means we cannot properly reason about it.
938  return State;
939  }
940 
941  return State->assume(*CountGreaterThanZero, Assumption);
942 }
943 
944 static ProgramStateRef
946  const ObjCForCollectionStmt *FCS,
947  bool Assumption) {
948  if (!State)
949  return nullptr;
950 
951  SymbolRef CollectionS = C.getSVal(FCS->getCollection()).getAsSymbol();
952  return assumeCollectionNonEmpty(C, State, CollectionS, Assumption);
953 }
954 
955 /// If the fist block edge is a back edge, we are reentering the loop.
956 static bool alreadyExecutedAtLeastOneLoopIteration(const ExplodedNode *N,
957  const ObjCForCollectionStmt *FCS) {
958  if (!N)
959  return false;
960 
961  ProgramPoint P = N->getLocation();
962  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
963  return BE->getSrc()->getLoopTarget() == FCS;
964  }
965 
966  // Keep looking for a block edge.
968  E = N->pred_end(); I != E; ++I) {
970  return true;
971  }
972 
973  return false;
974 }
975 
976 void ObjCLoopChecker::checkPostStmt(const ObjCForCollectionStmt *FCS,
977  CheckerContext &C) const {
978  ProgramStateRef State = C.getState();
979 
980  // Check if this is the branch for the end of the loop.
981  SVal CollectionSentinel = C.getSVal(FCS);
982  if (CollectionSentinel.isZeroConstant()) {
983  if (!alreadyExecutedAtLeastOneLoopIteration(C.getPredecessor(), FCS))
984  State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/false);
985 
986  // Otherwise, this is a branch that goes through the loop body.
987  } else {
988  State = checkCollectionNonNil(C, State, FCS);
989  State = checkElementNonNil(C, State, FCS);
990  State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/true);
991  }
992 
993  if (!State)
994  C.generateSink(C.getState(), C.getPredecessor());
995  else if (State != C.getState())
996  C.addTransition(State);
997 }
998 
999 bool ObjCLoopChecker::isCollectionCountMethod(const ObjCMethodCall &M,
1000  CheckerContext &C) const {
1001  Selector S = M.getSelector();
1002  // Initialize the identifiers on first use.
1003  if (!CountSelectorII)
1004  CountSelectorII = &C.getASTContext().Idents.get("count");
1005 
1006  // If the method returns collection count, record the value.
1007  return S.isUnarySelector() &&
1008  (S.getIdentifierInfoForSlot(0) == CountSelectorII);
1009 }
1010 
1011 void ObjCLoopChecker::checkPostObjCMessage(const ObjCMethodCall &M,
1012  CheckerContext &C) const {
1013  if (!M.isInstanceMessage())
1014  return;
1015 
1016  const ObjCInterfaceDecl *ClassID = M.getReceiverInterface();
1017  if (!ClassID)
1018  return;
1019 
1020  FoundationClass Class = findKnownClass(ClassID);
1021  if (Class != FC_NSDictionary &&
1022  Class != FC_NSArray &&
1023  Class != FC_NSSet &&
1024  Class != FC_NSOrderedSet)
1025  return;
1026 
1027  SymbolRef ContainerS = M.getReceiverSVal().getAsSymbol();
1028  if (!ContainerS)
1029  return;
1030 
1031  // If we are processing a call to "count", get the symbolic value returned by
1032  // a call to "count" and add it to the map.
1033  if (!isCollectionCountMethod(M, C))
1034  return;
1035 
1036  const Expr *MsgExpr = M.getOriginExpr();
1037  SymbolRef CountS = C.getSVal(MsgExpr).getAsSymbol();
1038  if (CountS) {
1039  ProgramStateRef State = C.getState();
1040 
1041  C.getSymbolManager().addSymbolDependency(ContainerS, CountS);
1042  State = State->set<ContainerCountMap>(ContainerS, CountS);
1043 
1044  if (const bool *NonEmpty = State->get<ContainerNonEmptyMap>(ContainerS)) {
1045  State = State->remove<ContainerNonEmptyMap>(ContainerS);
1046  State = assumeCollectionNonEmpty(C, State, ContainerS, *NonEmpty);
1047  }
1048 
1049  C.addTransition(State);
1050  }
1051 }
1052 
1054  const ObjCMethodCall *Message = dyn_cast_or_null<ObjCMethodCall>(Call);
1055  if (!Message)
1056  return nullptr;
1057 
1058  const ObjCMethodDecl *MD = Message->getDecl();
1059  if (!MD)
1060  return nullptr;
1061 
1062  const ObjCInterfaceDecl *StaticClass;
1063  if (isa<ObjCProtocolDecl>(MD->getDeclContext())) {
1064  // We can't find out where the method was declared without doing more work.
1065  // Instead, see if the receiver is statically typed as a known immutable
1066  // collection.
1067  StaticClass = Message->getOriginExpr()->getReceiverInterface();
1068  } else {
1069  StaticClass = MD->getClassInterface();
1070  }
1071 
1072  if (!StaticClass)
1073  return nullptr;
1074 
1075  switch (findKnownClass(StaticClass, /*IncludeSuper=*/false)) {
1076  case FC_None:
1077  return nullptr;
1078  case FC_NSArray:
1079  case FC_NSDictionary:
1080  case FC_NSEnumerator:
1081  case FC_NSNull:
1082  case FC_NSOrderedSet:
1083  case FC_NSSet:
1084  case FC_NSString:
1085  break;
1086  }
1087 
1088  return Message->getReceiverSVal().getAsSymbol();
1089 }
1090 
1092 ObjCLoopChecker::checkPointerEscape(ProgramStateRef State,
1093  const InvalidatedSymbols &Escaped,
1094  const CallEvent *Call,
1095  PointerEscapeKind Kind) const {
1096  SymbolRef ImmutableReceiver = getMethodReceiverIfKnownImmutable(Call);
1097 
1098  // Remove the invalidated symbols form the collection count map.
1099  for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
1100  E = Escaped.end();
1101  I != E; ++I) {
1102  SymbolRef Sym = *I;
1103 
1104  // Don't invalidate this symbol's count if we know the method being called
1105  // is declared on an immutable class. This isn't completely correct if the
1106  // receiver is also passed as an argument, but in most uses of NSArray,
1107  // NSDictionary, etc. this isn't likely to happen in a dangerous way.
1108  if (Sym == ImmutableReceiver)
1109  continue;
1110 
1111  // The symbol escaped. Pessimistically, assume that the count could have
1112  // changed.
1113  State = State->remove<ContainerCountMap>(Sym);
1114  State = State->remove<ContainerNonEmptyMap>(Sym);
1115  }
1116  return State;
1117 }
1118 
1119 void ObjCLoopChecker::checkDeadSymbols(SymbolReaper &SymReaper,
1120  CheckerContext &C) const {
1121  ProgramStateRef State = C.getState();
1122 
1123  // Remove the dead symbols from the collection count map.
1124  ContainerCountMapTy Tracked = State->get<ContainerCountMap>();
1125  for (ContainerCountMapTy::iterator I = Tracked.begin(),
1126  E = Tracked.end(); I != E; ++I) {
1127  SymbolRef Sym = I->first;
1128  if (SymReaper.isDead(Sym)) {
1129  State = State->remove<ContainerCountMap>(Sym);
1130  State = State->remove<ContainerNonEmptyMap>(Sym);
1131  }
1132  }
1133 
1134  C.addTransition(State);
1135 }
1136 
1137 namespace {
1138 /// \class ObjCNonNilReturnValueChecker
1139 /// The checker restricts the return values of APIs known to
1140 /// never (or almost never) return 'nil'.
1141 class ObjCNonNilReturnValueChecker
1142  : public Checker<check::PostObjCMessage,
1143  check::PostStmt<ObjCArrayLiteral>,
1144  check::PostStmt<ObjCDictionaryLiteral>,
1145  check::PostStmt<ObjCBoxedExpr> > {
1146  mutable bool Initialized;
1147  mutable Selector ObjectAtIndex;
1148  mutable Selector ObjectAtIndexedSubscript;
1149  mutable Selector NullSelector;
1150 
1151 public:
1152  ObjCNonNilReturnValueChecker() : Initialized(false) {}
1153 
1154  ProgramStateRef assumeExprIsNonNull(const Expr *NonNullExpr,
1156  CheckerContext &C) const;
1157  void assumeExprIsNonNull(const Expr *E, CheckerContext &C) const {
1158  C.addTransition(assumeExprIsNonNull(E, C.getState(), C));
1159  }
1160 
1161  void checkPostStmt(const ObjCArrayLiteral *E, CheckerContext &C) const {
1162  assumeExprIsNonNull(E, C);
1163  }
1164  void checkPostStmt(const ObjCDictionaryLiteral *E, CheckerContext &C) const {
1165  assumeExprIsNonNull(E, C);
1166  }
1167  void checkPostStmt(const ObjCBoxedExpr *E, CheckerContext &C) const {
1168  assumeExprIsNonNull(E, C);
1169  }
1170 
1171  void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
1172 };
1173 } // end anonymous namespace
1174 
1176 ObjCNonNilReturnValueChecker::assumeExprIsNonNull(const Expr *NonNullExpr,
1178  CheckerContext &C) const {
1179  SVal Val = C.getSVal(NonNullExpr);
1180  if (Optional<DefinedOrUnknownSVal> DV = Val.getAs<DefinedOrUnknownSVal>())
1181  return State->assume(*DV, true);
1182  return State;
1183 }
1184 
1185 void ObjCNonNilReturnValueChecker::checkPostObjCMessage(const ObjCMethodCall &M,
1186  CheckerContext &C)
1187  const {
1188  ProgramStateRef State = C.getState();
1189 
1190  if (!Initialized) {
1191  ASTContext &Ctx = C.getASTContext();
1192  ObjectAtIndex = GetUnarySelector("objectAtIndex", Ctx);
1193  ObjectAtIndexedSubscript = GetUnarySelector("objectAtIndexedSubscript", Ctx);
1194  NullSelector = GetNullarySelector("null", Ctx);
1195  }
1196 
1197  // Check the receiver type.
1198  if (const ObjCInterfaceDecl *Interface = M.getReceiverInterface()) {
1199 
1200  // Assume that object returned from '[self init]' or '[super init]' is not
1201  // 'nil' if we are processing an inlined function/method.
1202  //
1203  // A defensive callee will (and should) check if the object returned by
1204  // '[super init]' is 'nil' before doing it's own initialization. However,
1205  // since 'nil' is rarely returned in practice, we should not warn when the
1206  // caller to the defensive constructor uses the object in contexts where
1207  // 'nil' is not accepted.
1208  if (!C.inTopFrame() && M.getDecl() &&
1209  M.getDecl()->getMethodFamily() == OMF_init &&
1210  M.isReceiverSelfOrSuper()) {
1211  State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1212  }
1213 
1214  FoundationClass Cl = findKnownClass(Interface);
1215 
1216  // Objects returned from
1217  // [NSArray|NSOrderedSet]::[ObjectAtIndex|ObjectAtIndexedSubscript]
1218  // are never 'nil'.
1219  if (Cl == FC_NSArray || Cl == FC_NSOrderedSet) {
1220  Selector Sel = M.getSelector();
1221  if (Sel == ObjectAtIndex || Sel == ObjectAtIndexedSubscript) {
1222  // Go ahead and assume the value is non-nil.
1223  State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1224  }
1225  }
1226 
1227  // Objects returned from [NSNull null] are not nil.
1228  if (Cl == FC_NSNull) {
1229  if (M.getSelector() == NullSelector) {
1230  // Go ahead and assume the value is non-nil.
1231  State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1232  }
1233  }
1234  }
1235  C.addTransition(State);
1236 }
1237 
1238 //===----------------------------------------------------------------------===//
1239 // Check registration.
1240 //===----------------------------------------------------------------------===//
1241 
1242 void ento::registerNilArgChecker(CheckerManager &mgr) {
1243  mgr.registerChecker<NilArgChecker>();
1244 }
1245 
1246 bool ento::shouldRegisterNilArgChecker(const LangOptions &LO) {
1247  return true;
1248 }
1249 
1250 void ento::registerCFNumberChecker(CheckerManager &mgr) {
1251  mgr.registerChecker<CFNumberChecker>();
1252 }
1253 
1254 bool ento::shouldRegisterCFNumberChecker(const LangOptions &LO) {
1255  return true;
1256 }
1257 
1258 void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
1259  mgr.registerChecker<CFRetainReleaseChecker>();
1260 }
1261 
1262 bool ento::shouldRegisterCFRetainReleaseChecker(const LangOptions &LO) {
1263  return true;
1264 }
1265 
1266 void ento::registerClassReleaseChecker(CheckerManager &mgr) {
1267  mgr.registerChecker<ClassReleaseChecker>();
1268 }
1269 
1270 bool ento::shouldRegisterClassReleaseChecker(const LangOptions &LO) {
1271  return true;
1272 }
1273 
1274 void ento::registerVariadicMethodTypeChecker(CheckerManager &mgr) {
1275  mgr.registerChecker<VariadicMethodTypeChecker>();
1276 }
1277 
1278 bool ento::shouldRegisterVariadicMethodTypeChecker(const LangOptions &LO) {
1279  return true;
1280 }
1281 
1282 void ento::registerObjCLoopChecker(CheckerManager &mgr) {
1283  mgr.registerChecker<ObjCLoopChecker>();
1284 }
1285 
1286 bool ento::shouldRegisterObjCLoopChecker(const LangOptions &LO) {
1287  return true;
1288 }
1289 
1290 void ento::registerObjCNonNilReturnValueChecker(CheckerManager &mgr) {
1291  mgr.registerChecker<ObjCNonNilReturnValueChecker>();
1292 }
1293 
1294 bool ento::shouldRegisterObjCNonNilReturnValueChecker(const LangOptions &LO) {
1295  return true;
1296 }
Defines the clang::ASTContext interface.
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
Definition: CallEvent.cpp:977
CanQualType LongLongTy
Definition: ASTContext.h:1024
Represents a function declaration or definition.
Definition: Decl.h:1784
ObjCDictionaryElement getKeyValueElement(unsigned Index) const
Definition: ExprObjC.h:360
Smart pointer class that efficiently represents Objective-C method names.
A (possibly-)qualified type.
Definition: Type.h:643
bool isBlockPointerType() const
Definition: Type.h:6399
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:2677
ObjCInterfaceDecl * getClassInterface()
Definition: DeclObjC.cpp:1143
llvm::DenseSet< SymbolRef > InvalidatedSymbols
Definition: Store.h:51
static ProgramStateRef assumeCollectionNonEmpty(CheckerContext &C, ProgramStateRef State, SymbolRef CollectionS, bool Assumption)
Returns NULL state if the collection is known to contain elements (or is known not to contain element...
Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be placed into a PointerUnion...
Definition: Dominators.h:30
Stmt - This represents one statement.
Definition: Stmt.h:66
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:2664
ObjCInterfaceDecl * getReceiverInterface() const
Retrieve the Objective-C interface to which this message is being directed, if known.
Definition: ExprObjC.cpp:358
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
StringRef P
static StringRef GetReceiverInterfaceName(const ObjCMethodCall &msg)
CanQualType LongTy
Definition: ASTContext.h:1024
SourceRange getSourceRange() const override
Definition: CallEvent.cpp:1006
static ProgramStateRef checkCollectionNonNil(CheckerContext &C, ProgramStateRef State, const ObjCForCollectionStmt *FCS)
Assumes that the collection is non-nil.
Represents a variable declaration or definition.
Definition: Decl.h:827
const T * getAs() const
Member-template getAs<specific type>&#39;.
Definition: Type.h:6858
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:138
Defines the Objective-C statement AST node classes.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:269
One of these records is kept for each identifier that is lexed.
const SymExpr * SymbolRef
Definition: SymExpr.h:110
An element in an Objective-C dictionary literal.
Definition: ExprObjC.h:261
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:160
LineState State
static ProgramStateRef checkElementNonNil(CheckerContext &C, ProgramStateRef State, const ObjCForCollectionStmt *FCS)
Assumes that the collection elements are non-nil.
const ObjCInterfaceDecl * getReceiverInterface() const
Get the interface for the receiver.
Definition: CallEvent.h:1002
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:49
ObjCArrayLiteral - used for objective-c array containers; as in: @["Hello", NSApp, [NSNumber numberWithInt:42]];.
Definition: ExprObjC.h:188
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:6754
IdentifierTable & Idents
Definition: ASTContext.h:579
bool isUnarySelector() const
This class represents a description of a function call using the number of arguments and the name of ...
Definition: CallEvent.h:1058
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
Definition: DeclObjC.cpp:985
Represents any expression that calls an Objective-C method.
Definition: CallEvent.h:938
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
Selector GetNullarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing a nullary selector.
Definition: ASTContext.h:3043
RangeSelector name(std::string ID)
Given a node with a "name", (like NamedDecl, DeclRefExpr or CxxCtorInitializer) selects the name&#39;s to...
Expr * Key
The key for the dictionary element.
Definition: ExprObjC.h:263
#define UINT_MAX
Definition: limits.h:56
Represents an ObjC class declaration.
Definition: DeclObjC.h:1171
static SymbolRef getMethodReceiverIfKnownImmutable(const CallEvent *Call)
static bool isKnownNonNilCollectionType(QualType T)
bool isReceiverSelfOrSuper() const
Checks if the receiver refers to &#39;self&#39; or &#39;super&#39;.
Definition: CallEvent.cpp:993
The return type of classify().
Definition: Expr.h:311
This represents one expression.
Definition: Expr.h:108
static FoundationClass findKnownClass(const ObjCInterfaceDecl *ID, bool IncludeSuperclasses=true)
#define V(N, I)
Definition: ASTContext.h:2921
ObjCDictionaryLiteral - AST node to represent objective-c dictionary literals; as in:"name" : NSUserN...
Definition: ExprObjC.h:304
DeclContext * getDeclContext()
Definition: DeclBase.h:438
ObjCInterfaceDecl * getSuperClass() const
Definition: DeclObjC.cpp:337
CanQualType ShortTy
Definition: ASTContext.h:1024
void print(llvm::raw_ostream &OS) const
Prints the full selector name (e.g. "foo:bar:").
QualType getType() const
Definition: Expr.h:137
Expr * getElement(unsigned Index)
getElement - Return the Element at the specified index.
Definition: ExprObjC.h:230
unsigned getNumArgs() const
Kind
IdentifierInfo * getIdentifierInfoForSlot(unsigned argIndex) const
Retrieve the identifier at a given position in the selector.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
unsigned getNumElements() const
getNumElements - Return number of elements of objective-c dictionary literal.
Definition: ExprObjC.h:358
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Definition: Stmt.h:1213
CanQualType FloatTy
Definition: ASTContext.h:1027
static Selector getKeywordSelector(ASTContext &Ctx, IdentifierInfos *... IIs)
bool isObjCObjectPointerType() const
Definition: Type.h:6495
ObjCBoxedExpr - used for generalized expression boxing.
Definition: ExprObjC.h:124
const ObjCMethodDecl * getDecl() const override
Definition: CallEvent.h:966
Expr * Value
The value of the dictionary element.
Definition: ExprObjC.h:266
StringRef getName() const
Return the actual identifier string.
virtual const ObjCMessageExpr * getOriginExpr() const
Definition: CallEvent.h:962
CanQualType CharTy
Definition: ASTContext.h:1017
Selector getSelector() const
Definition: CallEvent.h:986
Dataflow Directional Tag Classes.
static std::string getName(const CallEvent &Call)
static bool alreadyExecutedAtLeastOneLoopIteration(const ExplodedNode *N, const ObjCForCollectionStmt *FCS)
If the fist block edge is a back edge, we are reentering the loop.
const Expr * getInit() const
Definition: Decl.h:1234
ObjCMessageKind getMessageKind() const
Returns how the message was written in the source (property access, subscript, or explicit message se...
Definition: CallEvent.cpp:1037
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
Represents a pointer to an Objective C object.
Definition: Type.h:5870
bool isInstanceMessage() const
Definition: CallEvent.h:978
Indicates that the tracking object is a descendant of a referenced-counted OSObject, used in the Darwin kernel.
ObjCInterfaceDecl * getInterfaceDecl() const
If this pointer points to an Objective @interface type, gets the declaration for that interface...
Definition: Type.h:5926
unsigned getNumElements() const
getNumElements - Return number of elements of objective-c array literal.
Definition: ExprObjC.h:227
Represents Objective-C&#39;s collection statement.
Definition: StmtObjC.h:23
unsigned getNumArgs() const override
Definition: CallEvent.h:970
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2088
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2289
const Expr * getArgExpr(unsigned Index) const override
Definition: CallEvent.h:974
Selector GetUnarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing an unary selector.
Definition: ASTContext.h:3049
pred_iterator pred_begin()
bool isVariadic() const
Definition: DeclObjC.h:426
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:262
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2521
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:275
static Optional< uint64_t > GetCFNumberSize(ASTContext &Ctx, uint64_t i)
CanQualType IntTy
Definition: ASTContext.h:1024
const ExplodedNode *const * const_pred_iterator
A trivial tuple used to represent a source range.
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
Definition: ProgramPoint.h:151
CanQualType DoubleTy
Definition: ASTContext.h:1027