clang  9.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 = llvm::make_unique<BugReport>(*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) {
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 = llvm::make_unique<BugReport>(*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 = llvm::make_unique<BugReport>(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 = llvm::make_unique<BugReport>(*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 = llvm::make_unique<BugReport>(*BT, os.str(), errorNode.getValue());
792  R->addRange(msg.getArgSourceRange(I));
793  C.emitReport(std::move(R));
794  }
795 }
796 
797 //===----------------------------------------------------------------------===//
798 // Improves the modeling of loops over Cocoa collections.
799 //===----------------------------------------------------------------------===//
800 
801 // The map from container symbol to the container count symbol.
802 // We currently will remember the last container count symbol encountered.
804 REGISTER_MAP_WITH_PROGRAMSTATE(ContainerNonEmptyMap, SymbolRef, bool)
805 
806 namespace {
807 class ObjCLoopChecker
808  : public Checker<check::PostStmt<ObjCForCollectionStmt>,
809  check::PostObjCMessage,
810  check::DeadSymbols,
811  check::PointerEscape > {
812  mutable IdentifierInfo *CountSelectorII;
813 
814  bool isCollectionCountMethod(const ObjCMethodCall &M,
815  CheckerContext &C) const;
816 
817 public:
818  ObjCLoopChecker() : CountSelectorII(nullptr) {}
819  void checkPostStmt(const ObjCForCollectionStmt *FCS, CheckerContext &C) const;
820  void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
821  void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
822  ProgramStateRef checkPointerEscape(ProgramStateRef State,
823  const InvalidatedSymbols &Escaped,
824  const CallEvent *Call,
825  PointerEscapeKind Kind) const;
826 };
827 } // end anonymous namespace
828 
831  if (!PT)
832  return false;
833 
834  const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
835  if (!ID)
836  return false;
837 
838  switch (findKnownClass(ID)) {
839  case FC_NSArray:
840  case FC_NSDictionary:
841  case FC_NSEnumerator:
842  case FC_NSOrderedSet:
843  case FC_NSSet:
844  return true;
845  default:
846  return false;
847  }
848 }
849 
850 /// Assumes that the collection is non-nil.
851 ///
852 /// If the collection is known to be nil, returns NULL to indicate an infeasible
853 /// path.
854 static ProgramStateRef checkCollectionNonNil(CheckerContext &C,
856  const ObjCForCollectionStmt *FCS) {
857  if (!State)
858  return nullptr;
859 
860  SVal CollectionVal = C.getSVal(FCS->getCollection());
861  Optional<DefinedSVal> KnownCollection = CollectionVal.getAs<DefinedSVal>();
862  if (!KnownCollection)
863  return State;
864 
865  ProgramStateRef StNonNil, StNil;
866  std::tie(StNonNil, StNil) = State->assume(*KnownCollection);
867  if (StNil && !StNonNil) {
868  // The collection is nil. This path is infeasible.
869  return nullptr;
870  }
871 
872  return StNonNil;
873 }
874 
875 /// Assumes that the collection elements are non-nil.
876 ///
877 /// This only applies if the collection is one of those known not to contain
878 /// nil values.
879 static ProgramStateRef checkElementNonNil(CheckerContext &C,
881  const ObjCForCollectionStmt *FCS) {
882  if (!State)
883  return nullptr;
884 
885  // See if the collection is one where we /know/ the elements are non-nil.
887  return State;
888 
889  const LocationContext *LCtx = C.getLocationContext();
890  const Stmt *Element = FCS->getElement();
891 
892  // FIXME: Copied from ExprEngineObjC.
893  Optional<Loc> ElementLoc;
894  if (const DeclStmt *DS = dyn_cast<DeclStmt>(Element)) {
895  const VarDecl *ElemDecl = cast<VarDecl>(DS->getSingleDecl());
896  assert(ElemDecl->getInit() == nullptr);
897  ElementLoc = State->getLValue(ElemDecl, LCtx);
898  } else {
899  ElementLoc = State->getSVal(Element, LCtx).getAs<Loc>();
900  }
901 
902  if (!ElementLoc)
903  return State;
904 
905  // Go ahead and assume the value is non-nil.
906  SVal Val = State->getSVal(*ElementLoc);
907  return State->assume(Val.castAs<DefinedOrUnknownSVal>(), true);
908 }
909 
910 /// Returns NULL state if the collection is known to contain elements
911 /// (or is known not to contain elements if the Assumption parameter is false.)
912 static ProgramStateRef
914  SymbolRef CollectionS, bool Assumption) {
915  if (!State || !CollectionS)
916  return State;
917 
918  const SymbolRef *CountS = State->get<ContainerCountMap>(CollectionS);
919  if (!CountS) {
920  const bool *KnownNonEmpty = State->get<ContainerNonEmptyMap>(CollectionS);
921  if (!KnownNonEmpty)
922  return State->set<ContainerNonEmptyMap>(CollectionS, Assumption);
923  return (Assumption == *KnownNonEmpty) ? State : nullptr;
924  }
925 
926  SValBuilder &SvalBuilder = C.getSValBuilder();
927  SVal CountGreaterThanZeroVal =
928  SvalBuilder.evalBinOp(State, BO_GT,
929  nonloc::SymbolVal(*CountS),
930  SvalBuilder.makeIntVal(0, (*CountS)->getType()),
931  SvalBuilder.getConditionType());
932  Optional<DefinedSVal> CountGreaterThanZero =
933  CountGreaterThanZeroVal.getAs<DefinedSVal>();
934  if (!CountGreaterThanZero) {
935  // The SValBuilder cannot construct a valid SVal for this condition.
936  // This means we cannot properly reason about it.
937  return State;
938  }
939 
940  return State->assume(*CountGreaterThanZero, Assumption);
941 }
942 
943 static ProgramStateRef
945  const ObjCForCollectionStmt *FCS,
946  bool Assumption) {
947  if (!State)
948  return nullptr;
949 
950  SymbolRef CollectionS = C.getSVal(FCS->getCollection()).getAsSymbol();
951  return assumeCollectionNonEmpty(C, State, CollectionS, Assumption);
952 }
953 
954 /// If the fist block edge is a back edge, we are reentering the loop.
955 static bool alreadyExecutedAtLeastOneLoopIteration(const ExplodedNode *N,
956  const ObjCForCollectionStmt *FCS) {
957  if (!N)
958  return false;
959 
960  ProgramPoint P = N->getLocation();
961  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
962  return BE->getSrc()->getLoopTarget() == FCS;
963  }
964 
965  // Keep looking for a block edge.
967  E = N->pred_end(); I != E; ++I) {
969  return true;
970  }
971 
972  return false;
973 }
974 
975 void ObjCLoopChecker::checkPostStmt(const ObjCForCollectionStmt *FCS,
976  CheckerContext &C) const {
977  ProgramStateRef State = C.getState();
978 
979  // Check if this is the branch for the end of the loop.
980  SVal CollectionSentinel = C.getSVal(FCS);
981  if (CollectionSentinel.isZeroConstant()) {
982  if (!alreadyExecutedAtLeastOneLoopIteration(C.getPredecessor(), FCS))
983  State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/false);
984 
985  // Otherwise, this is a branch that goes through the loop body.
986  } else {
987  State = checkCollectionNonNil(C, State, FCS);
988  State = checkElementNonNil(C, State, FCS);
989  State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/true);
990  }
991 
992  if (!State)
993  C.generateSink(C.getState(), C.getPredecessor());
994  else if (State != C.getState())
995  C.addTransition(State);
996 }
997 
998 bool ObjCLoopChecker::isCollectionCountMethod(const ObjCMethodCall &M,
999  CheckerContext &C) const {
1000  Selector S = M.getSelector();
1001  // Initialize the identifiers on first use.
1002  if (!CountSelectorII)
1003  CountSelectorII = &C.getASTContext().Idents.get("count");
1004 
1005  // If the method returns collection count, record the value.
1006  return S.isUnarySelector() &&
1007  (S.getIdentifierInfoForSlot(0) == CountSelectorII);
1008 }
1009 
1010 void ObjCLoopChecker::checkPostObjCMessage(const ObjCMethodCall &M,
1011  CheckerContext &C) const {
1012  if (!M.isInstanceMessage())
1013  return;
1014 
1015  const ObjCInterfaceDecl *ClassID = M.getReceiverInterface();
1016  if (!ClassID)
1017  return;
1018 
1019  FoundationClass Class = findKnownClass(ClassID);
1020  if (Class != FC_NSDictionary &&
1021  Class != FC_NSArray &&
1022  Class != FC_NSSet &&
1023  Class != FC_NSOrderedSet)
1024  return;
1025 
1026  SymbolRef ContainerS = M.getReceiverSVal().getAsSymbol();
1027  if (!ContainerS)
1028  return;
1029 
1030  // If we are processing a call to "count", get the symbolic value returned by
1031  // a call to "count" and add it to the map.
1032  if (!isCollectionCountMethod(M, C))
1033  return;
1034 
1035  const Expr *MsgExpr = M.getOriginExpr();
1036  SymbolRef CountS = C.getSVal(MsgExpr).getAsSymbol();
1037  if (CountS) {
1038  ProgramStateRef State = C.getState();
1039 
1040  C.getSymbolManager().addSymbolDependency(ContainerS, CountS);
1041  State = State->set<ContainerCountMap>(ContainerS, CountS);
1042 
1043  if (const bool *NonEmpty = State->get<ContainerNonEmptyMap>(ContainerS)) {
1044  State = State->remove<ContainerNonEmptyMap>(ContainerS);
1045  State = assumeCollectionNonEmpty(C, State, ContainerS, *NonEmpty);
1046  }
1047 
1048  C.addTransition(State);
1049  }
1050 }
1051 
1053  const ObjCMethodCall *Message = dyn_cast_or_null<ObjCMethodCall>(Call);
1054  if (!Message)
1055  return nullptr;
1056 
1057  const ObjCMethodDecl *MD = Message->getDecl();
1058  if (!MD)
1059  return nullptr;
1060 
1061  const ObjCInterfaceDecl *StaticClass;
1062  if (isa<ObjCProtocolDecl>(MD->getDeclContext())) {
1063  // We can't find out where the method was declared without doing more work.
1064  // Instead, see if the receiver is statically typed as a known immutable
1065  // collection.
1066  StaticClass = Message->getOriginExpr()->getReceiverInterface();
1067  } else {
1068  StaticClass = MD->getClassInterface();
1069  }
1070 
1071  if (!StaticClass)
1072  return nullptr;
1073 
1074  switch (findKnownClass(StaticClass, /*IncludeSuper=*/false)) {
1075  case FC_None:
1076  return nullptr;
1077  case FC_NSArray:
1078  case FC_NSDictionary:
1079  case FC_NSEnumerator:
1080  case FC_NSNull:
1081  case FC_NSOrderedSet:
1082  case FC_NSSet:
1083  case FC_NSString:
1084  break;
1085  }
1086 
1087  return Message->getReceiverSVal().getAsSymbol();
1088 }
1089 
1091 ObjCLoopChecker::checkPointerEscape(ProgramStateRef State,
1092  const InvalidatedSymbols &Escaped,
1093  const CallEvent *Call,
1094  PointerEscapeKind Kind) const {
1095  SymbolRef ImmutableReceiver = getMethodReceiverIfKnownImmutable(Call);
1096 
1097  // Remove the invalidated symbols form the collection count map.
1098  for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
1099  E = Escaped.end();
1100  I != E; ++I) {
1101  SymbolRef Sym = *I;
1102 
1103  // Don't invalidate this symbol's count if we know the method being called
1104  // is declared on an immutable class. This isn't completely correct if the
1105  // receiver is also passed as an argument, but in most uses of NSArray,
1106  // NSDictionary, etc. this isn't likely to happen in a dangerous way.
1107  if (Sym == ImmutableReceiver)
1108  continue;
1109 
1110  // The symbol escaped. Pessimistically, assume that the count could have
1111  // changed.
1112  State = State->remove<ContainerCountMap>(Sym);
1113  State = State->remove<ContainerNonEmptyMap>(Sym);
1114  }
1115  return State;
1116 }
1117 
1118 void ObjCLoopChecker::checkDeadSymbols(SymbolReaper &SymReaper,
1119  CheckerContext &C) const {
1120  ProgramStateRef State = C.getState();
1121 
1122  // Remove the dead symbols from the collection count map.
1123  ContainerCountMapTy Tracked = State->get<ContainerCountMap>();
1124  for (ContainerCountMapTy::iterator I = Tracked.begin(),
1125  E = Tracked.end(); I != E; ++I) {
1126  SymbolRef Sym = I->first;
1127  if (SymReaper.isDead(Sym)) {
1128  State = State->remove<ContainerCountMap>(Sym);
1129  State = State->remove<ContainerNonEmptyMap>(Sym);
1130  }
1131  }
1132 
1133  C.addTransition(State);
1134 }
1135 
1136 namespace {
1137 /// \class ObjCNonNilReturnValueChecker
1138 /// The checker restricts the return values of APIs known to
1139 /// never (or almost never) return 'nil'.
1140 class ObjCNonNilReturnValueChecker
1141  : public Checker<check::PostObjCMessage,
1142  check::PostStmt<ObjCArrayLiteral>,
1143  check::PostStmt<ObjCDictionaryLiteral>,
1144  check::PostStmt<ObjCBoxedExpr> > {
1145  mutable bool Initialized;
1146  mutable Selector ObjectAtIndex;
1147  mutable Selector ObjectAtIndexedSubscript;
1148  mutable Selector NullSelector;
1149 
1150 public:
1151  ObjCNonNilReturnValueChecker() : Initialized(false) {}
1152 
1153  ProgramStateRef assumeExprIsNonNull(const Expr *NonNullExpr,
1155  CheckerContext &C) const;
1156  void assumeExprIsNonNull(const Expr *E, CheckerContext &C) const {
1157  C.addTransition(assumeExprIsNonNull(E, C.getState(), C));
1158  }
1159 
1160  void checkPostStmt(const ObjCArrayLiteral *E, CheckerContext &C) const {
1161  assumeExprIsNonNull(E, C);
1162  }
1163  void checkPostStmt(const ObjCDictionaryLiteral *E, CheckerContext &C) const {
1164  assumeExprIsNonNull(E, C);
1165  }
1166  void checkPostStmt(const ObjCBoxedExpr *E, CheckerContext &C) const {
1167  assumeExprIsNonNull(E, C);
1168  }
1169 
1170  void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
1171 };
1172 } // end anonymous namespace
1173 
1175 ObjCNonNilReturnValueChecker::assumeExprIsNonNull(const Expr *NonNullExpr,
1177  CheckerContext &C) const {
1178  SVal Val = C.getSVal(NonNullExpr);
1179  if (Optional<DefinedOrUnknownSVal> DV = Val.getAs<DefinedOrUnknownSVal>())
1180  return State->assume(*DV, true);
1181  return State;
1182 }
1183 
1184 void ObjCNonNilReturnValueChecker::checkPostObjCMessage(const ObjCMethodCall &M,
1185  CheckerContext &C)
1186  const {
1187  ProgramStateRef State = C.getState();
1188 
1189  if (!Initialized) {
1190  ASTContext &Ctx = C.getASTContext();
1191  ObjectAtIndex = GetUnarySelector("objectAtIndex", Ctx);
1192  ObjectAtIndexedSubscript = GetUnarySelector("objectAtIndexedSubscript", Ctx);
1193  NullSelector = GetNullarySelector("null", Ctx);
1194  }
1195 
1196  // Check the receiver type.
1197  if (const ObjCInterfaceDecl *Interface = M.getReceiverInterface()) {
1198 
1199  // Assume that object returned from '[self init]' or '[super init]' is not
1200  // 'nil' if we are processing an inlined function/method.
1201  //
1202  // A defensive callee will (and should) check if the object returned by
1203  // '[super init]' is 'nil' before doing it's own initialization. However,
1204  // since 'nil' is rarely returned in practice, we should not warn when the
1205  // caller to the defensive constructor uses the object in contexts where
1206  // 'nil' is not accepted.
1207  if (!C.inTopFrame() && M.getDecl() &&
1208  M.getDecl()->getMethodFamily() == OMF_init &&
1209  M.isReceiverSelfOrSuper()) {
1210  State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1211  }
1212 
1213  FoundationClass Cl = findKnownClass(Interface);
1214 
1215  // Objects returned from
1216  // [NSArray|NSOrderedSet]::[ObjectAtIndex|ObjectAtIndexedSubscript]
1217  // are never 'nil'.
1218  if (Cl == FC_NSArray || Cl == FC_NSOrderedSet) {
1219  Selector Sel = M.getSelector();
1220  if (Sel == ObjectAtIndex || Sel == ObjectAtIndexedSubscript) {
1221  // Go ahead and assume the value is non-nil.
1222  State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1223  }
1224  }
1225 
1226  // Objects returned from [NSNull null] are not nil.
1227  if (Cl == FC_NSNull) {
1228  if (M.getSelector() == NullSelector) {
1229  // Go ahead and assume the value is non-nil.
1230  State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1231  }
1232  }
1233  }
1234  C.addTransition(State);
1235 }
1236 
1237 //===----------------------------------------------------------------------===//
1238 // Check registration.
1239 //===----------------------------------------------------------------------===//
1240 
1241 void ento::registerNilArgChecker(CheckerManager &mgr) {
1242  mgr.registerChecker<NilArgChecker>();
1243 }
1244 
1245 bool ento::shouldRegisterNilArgChecker(const LangOptions &LO) {
1246  return true;
1247 }
1248 
1249 void ento::registerCFNumberChecker(CheckerManager &mgr) {
1250  mgr.registerChecker<CFNumberChecker>();
1251 }
1252 
1253 bool ento::shouldRegisterCFNumberChecker(const LangOptions &LO) {
1254  return true;
1255 }
1256 
1257 void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
1258  mgr.registerChecker<CFRetainReleaseChecker>();
1259 }
1260 
1261 bool ento::shouldRegisterCFRetainReleaseChecker(const LangOptions &LO) {
1262  return true;
1263 }
1264 
1265 void ento::registerClassReleaseChecker(CheckerManager &mgr) {
1266  mgr.registerChecker<ClassReleaseChecker>();
1267 }
1268 
1269 bool ento::shouldRegisterClassReleaseChecker(const LangOptions &LO) {
1270  return true;
1271 }
1272 
1273 void ento::registerVariadicMethodTypeChecker(CheckerManager &mgr) {
1274  mgr.registerChecker<VariadicMethodTypeChecker>();
1275 }
1276 
1277 bool ento::shouldRegisterVariadicMethodTypeChecker(const LangOptions &LO) {
1278  return true;
1279 }
1280 
1281 void ento::registerObjCLoopChecker(CheckerManager &mgr) {
1282  mgr.registerChecker<ObjCLoopChecker>();
1283 }
1284 
1285 bool ento::shouldRegisterObjCLoopChecker(const LangOptions &LO) {
1286  return true;
1287 }
1288 
1289 void ento::registerObjCNonNilReturnValueChecker(CheckerManager &mgr) {
1290  mgr.registerChecker<ObjCNonNilReturnValueChecker>();
1291 }
1292 
1293 bool ento::shouldRegisterObjCNonNilReturnValueChecker(const LangOptions &LO) {
1294  return true;
1295 }
Defines the clang::ASTContext interface.
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
Definition: CallEvent.cpp:959
CanQualType LongLongTy
Definition: ASTContext.h:1023
Represents a function declaration or definition.
Definition: Decl.h:1748
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:6359
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:2673
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...
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
Definition: Dominators.h:29
const SymExpr * SymbolRef
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:2660
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:1023
SourceRange getSourceRange() const override
Definition: CallEvent.cpp:988
RangeSelector name(std::string ID)
Given a node with a "name", (like NamedDecl, DeclRefExpr or CxxCtorInitializer) selects the name&#39;s to...
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:812
const T * getAs() const
Member-template getAs<specific type>&#39;.
Definition: Type.h:6818
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:138
Defines the Objective-C statement AST node classes.
long i
Definition: xmmintrin.h:1456
std::string getName(ArrayRef< StringRef > Parts) const
Get the platform-specific name separator.
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.
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:154
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:1033
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:6714
IdentifierTable & Idents
Definition: ASTContext.h:569
bool isUnarySelector() const
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:969
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:3029
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:975
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:2907
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:1023
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:1203
CanQualType FloatTy
Definition: ASTContext.h:1026
static Selector getKeywordSelector(ASTContext &Ctx, IdentifierInfos *... IIs)
bool isObjCObjectPointerType() const
Definition: Type.h:6455
ObjCBoxedExpr - used for generalized expression boxing.
Definition: ExprObjC.h:124
const ObjCMethodDecl * getDecl() const override
Definition: CallEvent.h:997
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:993
CanQualType CharTy
Definition: ASTContext.h:1016
Selector getSelector() const
Definition: CallEvent.h:1017
Dataflow Directional Tag Classes.
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:1219
ObjCMessageKind getMessageKind() const
Returns how the message was written in the source (property access, subscript, or explicit message se...
Definition: CallEvent.cpp:1019
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
Represents a pointer to an Objective C object.
Definition: Type.h:5849
bool isInstanceMessage() const
Definition: CallEvent.h:1009
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:5905
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:1001
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2079
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2280
const Expr * getArgExpr(unsigned Index) const override
Definition: CallEvent.h:1005
Selector GetUnarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing an unary selector.
Definition: ASTContext.h:3035
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:251
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2516
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:1023
result[0]
Definition: emmintrin.h:120
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:1026