clang  8.0.0svn
BasicObjCFoundationChecks.cpp
Go to the documentation of this file.
1 //== BasicObjCFoundationChecks.cpp - Simple Apple-Foundation checks -*- C++ -*--
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines BasicObjCFoundationChecks, a class that encapsulates
11 // a set of simple checks to run on Objective-C code using Apple's Foundation
12 // classes.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "ClangSACheckers.h"
17 #include "clang/AST/ASTContext.h"
18 #include "clang/AST/DeclObjC.h"
19 #include "clang/AST/Expr.h"
20 #include "clang/AST/ExprObjC.h"
21 #include "clang/AST/StmtObjC.h"
33 #include "llvm/ADT/SmallString.h"
34 #include "llvm/ADT/StringMap.h"
35 #include "llvm/Support/raw_ostream.h"
36 
37 using namespace clang;
38 using namespace ento;
39 using namespace llvm;
40 
41 namespace {
42 class APIMisuse : public BugType {
43 public:
44  APIMisuse(const CheckerBase *checker, const char *name)
45  : BugType(checker, name, "API Misuse (Apple)") {}
46 };
47 } // end anonymous namespace
48 
49 //===----------------------------------------------------------------------===//
50 // Utility functions.
51 //===----------------------------------------------------------------------===//
52 
53 static StringRef GetReceiverInterfaceName(const ObjCMethodCall &msg) {
54  if (const ObjCInterfaceDecl *ID = msg.getReceiverInterface())
55  return ID->getIdentifier()->getName();
56  return StringRef();
57 }
58 
68 };
69 
71  bool IncludeSuperclasses = true) {
72  static llvm::StringMap<FoundationClass> Classes;
73  if (Classes.empty()) {
74  Classes["NSArray"] = FC_NSArray;
75  Classes["NSDictionary"] = FC_NSDictionary;
76  Classes["NSEnumerator"] = FC_NSEnumerator;
77  Classes["NSNull"] = FC_NSNull;
78  Classes["NSOrderedSet"] = FC_NSOrderedSet;
79  Classes["NSSet"] = FC_NSSet;
80  Classes["NSString"] = FC_NSString;
81  }
82 
83  // FIXME: Should we cache this at all?
84  FoundationClass result = Classes.lookup(ID->getIdentifier()->getName());
85  if (result == FC_None && IncludeSuperclasses)
86  if (const ObjCInterfaceDecl *Super = ID->getSuperClass())
87  return findKnownClass(Super);
88 
89  return result;
90 }
91 
92 //===----------------------------------------------------------------------===//
93 // NilArgChecker - Check for prohibited nil arguments to ObjC method calls.
94 //===----------------------------------------------------------------------===//
95 
96 namespace {
97  class NilArgChecker : public Checker<check::PreObjCMessage,
98  check::PostStmt<ObjCDictionaryLiteral>,
99  check::PostStmt<ObjCArrayLiteral> > {
100  mutable std::unique_ptr<APIMisuse> BT;
101 
102  mutable llvm::SmallDenseMap<Selector, unsigned, 16> StringSelectors;
103  mutable Selector ArrayWithObjectSel;
104  mutable Selector AddObjectSel;
105  mutable Selector InsertObjectAtIndexSel;
106  mutable Selector ReplaceObjectAtIndexWithObjectSel;
107  mutable Selector SetObjectAtIndexedSubscriptSel;
108  mutable Selector ArrayByAddingObjectSel;
109  mutable Selector DictionaryWithObjectForKeySel;
110  mutable Selector SetObjectForKeySel;
111  mutable Selector SetObjectForKeyedSubscriptSel;
112  mutable Selector RemoveObjectForKeySel;
113 
114  void warnIfNilExpr(const Expr *E,
115  const char *Msg,
116  CheckerContext &C) const;
117 
118  void warnIfNilArg(CheckerContext &C,
119  const ObjCMethodCall &msg, unsigned Arg,
120  FoundationClass Class,
121  bool CanBeSubscript = false) const;
122 
123  void generateBugReport(ExplodedNode *N,
124  StringRef Msg,
125  SourceRange Range,
126  const Expr *Expr,
127  CheckerContext &C) const;
128 
129  public:
130  void checkPreObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
131  void checkPostStmt(const ObjCDictionaryLiteral *DL,
132  CheckerContext &C) const;
133  void checkPostStmt(const ObjCArrayLiteral *AL,
134  CheckerContext &C) const;
135  };
136 } // end anonymous namespace
137 
138 void NilArgChecker::warnIfNilExpr(const Expr *E,
139  const char *Msg,
140  CheckerContext &C) const {
141  ProgramStateRef State = C.getState();
142  if (State->isNull(C.getSVal(E)).isConstrainedTrue()) {
143 
144  if (ExplodedNode *N = C.generateErrorNode()) {
145  generateBugReport(N, Msg, E->getSourceRange(), E, C);
146  }
147  }
148 }
149 
150 void NilArgChecker::warnIfNilArg(CheckerContext &C,
151  const ObjCMethodCall &msg,
152  unsigned int Arg,
153  FoundationClass Class,
154  bool CanBeSubscript) const {
155  // Check if the argument is nil.
156  ProgramStateRef State = C.getState();
157  if (!State->isNull(msg.getArgSVal(Arg)).isConstrainedTrue())
158  return;
159 
160  // NOTE: We cannot throw non-fatal errors from warnIfNilExpr,
161  // because it's called multiple times from some callers, so it'd cause
162  // an unwanted state split if two or more non-fatal errors are thrown
163  // within the same checker callback. For now we don't want to, but
164  // it'll need to be fixed if we ever want to.
165  if (ExplodedNode *N = C.generateErrorNode()) {
166  SmallString<128> sbuf;
167  llvm::raw_svector_ostream os(sbuf);
168 
169  if (CanBeSubscript && msg.getMessageKind() == OCM_Subscript) {
170 
171  if (Class == FC_NSArray) {
172  os << "Array element cannot be nil";
173  } else if (Class == FC_NSDictionary) {
174  if (Arg == 0) {
175  os << "Value stored into '";
176  os << GetReceiverInterfaceName(msg) << "' cannot be nil";
177  } else {
178  assert(Arg == 1);
179  os << "'"<< GetReceiverInterfaceName(msg) << "' key cannot be nil";
180  }
181  } else
182  llvm_unreachable("Missing foundation class for the subscript expr");
183 
184  } else {
185  if (Class == FC_NSDictionary) {
186  if (Arg == 0)
187  os << "Value argument ";
188  else {
189  assert(Arg == 1);
190  os << "Key argument ";
191  }
192  os << "to '";
193  msg.getSelector().print(os);
194  os << "' cannot be nil";
195  } else {
196  os << "Argument to '" << GetReceiverInterfaceName(msg) << "' method '";
197  msg.getSelector().print(os);
198  os << "' cannot be nil";
199  }
200  }
201 
202  generateBugReport(N, os.str(), msg.getArgSourceRange(Arg),
203  msg.getArgExpr(Arg), C);
204  }
205 }
206 
207 void NilArgChecker::generateBugReport(ExplodedNode *N,
208  StringRef Msg,
209  SourceRange Range,
210  const Expr *E,
211  CheckerContext &C) const {
212  if (!BT)
213  BT.reset(new APIMisuse(this, "nil argument"));
214 
215  auto R = llvm::make_unique<BugReport>(*BT, Msg, N);
216  R->addRange(Range);
217  bugreporter::trackExpressionValue(N, E, *R);
218  C.emitReport(std::move(R));
219 }
220 
221 void NilArgChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
222  CheckerContext &C) const {
224  if (!ID)
225  return;
226 
227  FoundationClass Class = findKnownClass(ID);
228 
229  static const unsigned InvalidArgIndex = UINT_MAX;
230  unsigned Arg = InvalidArgIndex;
231  bool CanBeSubscript = false;
232 
233  if (Class == FC_NSString) {
234  Selector S = msg.getSelector();
235 
236  if (S.isUnarySelector())
237  return;
238 
239  if (StringSelectors.empty()) {
240  ASTContext &Ctx = C.getASTContext();
241  Selector Sels[] = {
242  getKeywordSelector(Ctx, "caseInsensitiveCompare"),
243  getKeywordSelector(Ctx, "compare"),
244  getKeywordSelector(Ctx, "compare", "options"),
245  getKeywordSelector(Ctx, "compare", "options", "range"),
246  getKeywordSelector(Ctx, "compare", "options", "range", "locale"),
247  getKeywordSelector(Ctx, "componentsSeparatedByCharactersInSet"),
248  getKeywordSelector(Ctx, "initWithFormat"),
249  getKeywordSelector(Ctx, "localizedCaseInsensitiveCompare"),
250  getKeywordSelector(Ctx, "localizedCompare"),
251  getKeywordSelector(Ctx, "localizedStandardCompare"),
252  };
253  for (Selector KnownSel : Sels)
254  StringSelectors[KnownSel] = 0;
255  }
256  auto I = StringSelectors.find(S);
257  if (I == StringSelectors.end())
258  return;
259  Arg = I->second;
260  } else if (Class == FC_NSArray) {
261  Selector S = msg.getSelector();
262 
263  if (S.isUnarySelector())
264  return;
265 
266  if (ArrayWithObjectSel.isNull()) {
267  ASTContext &Ctx = C.getASTContext();
268  ArrayWithObjectSel = getKeywordSelector(Ctx, "arrayWithObject");
269  AddObjectSel = getKeywordSelector(Ctx, "addObject");
270  InsertObjectAtIndexSel =
271  getKeywordSelector(Ctx, "insertObject", "atIndex");
272  ReplaceObjectAtIndexWithObjectSel =
273  getKeywordSelector(Ctx, "replaceObjectAtIndex", "withObject");
274  SetObjectAtIndexedSubscriptSel =
275  getKeywordSelector(Ctx, "setObject", "atIndexedSubscript");
276  ArrayByAddingObjectSel = getKeywordSelector(Ctx, "arrayByAddingObject");
277  }
278 
279  if (S == ArrayWithObjectSel || S == AddObjectSel ||
280  S == InsertObjectAtIndexSel || S == ArrayByAddingObjectSel) {
281  Arg = 0;
282  } else if (S == SetObjectAtIndexedSubscriptSel) {
283  Arg = 0;
284  CanBeSubscript = true;
285  } else if (S == ReplaceObjectAtIndexWithObjectSel) {
286  Arg = 1;
287  }
288  } else if (Class == FC_NSDictionary) {
289  Selector S = msg.getSelector();
290 
291  if (S.isUnarySelector())
292  return;
293 
294  if (DictionaryWithObjectForKeySel.isNull()) {
295  ASTContext &Ctx = C.getASTContext();
296  DictionaryWithObjectForKeySel =
297  getKeywordSelector(Ctx, "dictionaryWithObject", "forKey");
298  SetObjectForKeySel = getKeywordSelector(Ctx, "setObject", "forKey");
299  SetObjectForKeyedSubscriptSel =
300  getKeywordSelector(Ctx, "setObject", "forKeyedSubscript");
301  RemoveObjectForKeySel = getKeywordSelector(Ctx, "removeObjectForKey");
302  }
303 
304  if (S == DictionaryWithObjectForKeySel || S == SetObjectForKeySel) {
305  Arg = 0;
306  warnIfNilArg(C, msg, /* Arg */1, Class);
307  } else if (S == SetObjectForKeyedSubscriptSel) {
308  CanBeSubscript = true;
309  Arg = 1;
310  } else if (S == RemoveObjectForKeySel) {
311  Arg = 0;
312  }
313  }
314 
315  // If argument is '0', report a warning.
316  if ((Arg != InvalidArgIndex))
317  warnIfNilArg(C, msg, Arg, Class, CanBeSubscript);
318 }
319 
320 void NilArgChecker::checkPostStmt(const ObjCArrayLiteral *AL,
321  CheckerContext &C) const {
322  unsigned NumOfElements = AL->getNumElements();
323  for (unsigned i = 0; i < NumOfElements; ++i) {
324  warnIfNilExpr(AL->getElement(i), "Array element cannot be nil", C);
325  }
326 }
327 
328 void NilArgChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
329  CheckerContext &C) const {
330  unsigned NumOfElements = DL->getNumElements();
331  for (unsigned i = 0; i < NumOfElements; ++i) {
332  ObjCDictionaryElement Element = DL->getKeyValueElement(i);
333  warnIfNilExpr(Element.Key, "Dictionary key cannot be nil", C);
334  warnIfNilExpr(Element.Value, "Dictionary value cannot be nil", C);
335  }
336 }
337 
338 //===----------------------------------------------------------------------===//
339 // Checking for mismatched types passed to CFNumberCreate/CFNumberGetValue.
340 //===----------------------------------------------------------------------===//
341 
342 namespace {
343 class CFNumberChecker : public Checker< check::PreStmt<CallExpr> > {
344  mutable std::unique_ptr<APIMisuse> BT;
345  mutable IdentifierInfo *ICreate, *IGetValue;
346 public:
347  CFNumberChecker() : ICreate(nullptr), IGetValue(nullptr) {}
348 
349  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
350 
351 private:
352  void EmitError(const TypedRegion* R, const Expr *Ex,
353  uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind);
354 };
355 } // end anonymous namespace
356 
374 };
375 
377  static const unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 };
378 
379  if (i < kCFNumberCharType)
380  return FixedSize[i-1];
381 
382  QualType T;
383 
384  switch (i) {
385  case kCFNumberCharType: T = Ctx.CharTy; break;
386  case kCFNumberShortType: T = Ctx.ShortTy; break;
387  case kCFNumberIntType: T = Ctx.IntTy; break;
388  case kCFNumberLongType: T = Ctx.LongTy; break;
389  case kCFNumberLongLongType: T = Ctx.LongLongTy; break;
390  case kCFNumberFloatType: T = Ctx.FloatTy; break;
391  case kCFNumberDoubleType: T = Ctx.DoubleTy; break;
395  // FIXME: We need a way to map from names to Type*.
396  default:
397  return None;
398  }
399 
400  return Ctx.getTypeSize(T);
401 }
402 
403 #if 0
404 static const char* GetCFNumberTypeStr(uint64_t i) {
405  static const char* Names[] = {
406  "kCFNumberSInt8Type",
407  "kCFNumberSInt16Type",
408  "kCFNumberSInt32Type",
409  "kCFNumberSInt64Type",
410  "kCFNumberFloat32Type",
411  "kCFNumberFloat64Type",
412  "kCFNumberCharType",
413  "kCFNumberShortType",
414  "kCFNumberIntType",
415  "kCFNumberLongType",
416  "kCFNumberLongLongType",
417  "kCFNumberFloatType",
418  "kCFNumberDoubleType",
419  "kCFNumberCFIndexType",
420  "kCFNumberNSIntegerType",
421  "kCFNumberCGFloatType"
422  };
423 
424  return i <= kCFNumberCGFloatType ? Names[i-1] : "Invalid CFNumberType";
425 }
426 #endif
427 
428 void CFNumberChecker::checkPreStmt(const CallExpr *CE,
429  CheckerContext &C) const {
430  ProgramStateRef state = C.getState();
431  const FunctionDecl *FD = C.getCalleeDecl(CE);
432  if (!FD)
433  return;
434 
435  ASTContext &Ctx = C.getASTContext();
436  if (!ICreate) {
437  ICreate = &Ctx.Idents.get("CFNumberCreate");
438  IGetValue = &Ctx.Idents.get("CFNumberGetValue");
439  }
440  if (!(FD->getIdentifier() == ICreate || FD->getIdentifier() == IGetValue) ||
441  CE->getNumArgs() != 3)
442  return;
443 
444  // Get the value of the "theType" argument.
445  SVal TheTypeVal = C.getSVal(CE->getArg(1));
446 
447  // FIXME: We really should allow ranges of valid theType values, and
448  // bifurcate the state appropriately.
449  Optional<nonloc::ConcreteInt> V = TheTypeVal.getAs<nonloc::ConcreteInt>();
450  if (!V)
451  return;
452 
453  uint64_t NumberKind = V->getValue().getLimitedValue();
454  Optional<uint64_t> OptCFNumberSize = GetCFNumberSize(Ctx, NumberKind);
455 
456  // FIXME: In some cases we can emit an error.
457  if (!OptCFNumberSize)
458  return;
459 
460  uint64_t CFNumberSize = *OptCFNumberSize;
461 
462  // Look at the value of the integer being passed by reference. Essentially
463  // we want to catch cases where the value passed in is not equal to the
464  // size of the type being created.
465  SVal TheValueExpr = C.getSVal(CE->getArg(2));
466 
467  // FIXME: Eventually we should handle arbitrary locations. We can do this
468  // by having an enhanced memory model that does low-level typing.
469  Optional<loc::MemRegionVal> LV = TheValueExpr.getAs<loc::MemRegionVal>();
470  if (!LV)
471  return;
472 
473  const TypedValueRegion* R = dyn_cast<TypedValueRegion>(LV->stripCasts());
474  if (!R)
475  return;
476 
477  QualType T = Ctx.getCanonicalType(R->getValueType());
478 
479  // FIXME: If the pointee isn't an integer type, should we flag a warning?
480  // People can do weird stuff with pointers.
481 
482  if (!T->isIntegralOrEnumerationType())
483  return;
484 
485  uint64_t PrimitiveTypeSize = Ctx.getTypeSize(T);
486 
487  if (PrimitiveTypeSize == CFNumberSize)
488  return;
489 
490  // FIXME: We can actually create an abstract "CFNumber" object that has
491  // the bits initialized to the provided values.
492  ExplodedNode *N = C.generateNonFatalErrorNode();
493  if (N) {
494  SmallString<128> sbuf;
495  llvm::raw_svector_ostream os(sbuf);
496  bool isCreate = (FD->getIdentifier() == ICreate);
497 
498  if (isCreate) {
499  os << (PrimitiveTypeSize == 8 ? "An " : "A ")
500  << PrimitiveTypeSize << "-bit integer is used to initialize a "
501  << "CFNumber object that represents "
502  << (CFNumberSize == 8 ? "an " : "a ")
503  << CFNumberSize << "-bit integer; ";
504  } else {
505  os << "A CFNumber object that represents "
506  << (CFNumberSize == 8 ? "an " : "a ")
507  << CFNumberSize << "-bit integer is used to initialize "
508  << (PrimitiveTypeSize == 8 ? "an " : "a ")
509  << PrimitiveTypeSize << "-bit integer; ";
510  }
511 
512  if (PrimitiveTypeSize < CFNumberSize)
513  os << (CFNumberSize - PrimitiveTypeSize)
514  << " bits of the CFNumber value will "
515  << (isCreate ? "be garbage." : "overwrite adjacent storage.");
516  else
517  os << (PrimitiveTypeSize - CFNumberSize)
518  << " bits of the integer value will be "
519  << (isCreate ? "lost." : "garbage.");
520 
521  if (!BT)
522  BT.reset(new APIMisuse(this, "Bad use of CFNumber APIs"));
523 
524  auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
525  report->addRange(CE->getArg(2)->getSourceRange());
526  C.emitReport(std::move(report));
527  }
528 }
529 
530 //===----------------------------------------------------------------------===//
531 // CFRetain/CFRelease/CFMakeCollectable/CFAutorelease checking for null arguments.
532 //===----------------------------------------------------------------------===//
533 
534 namespace {
535 class CFRetainReleaseChecker : public Checker<check::PreCall> {
536  mutable APIMisuse BT{this, "null passed to CF memory management function"};
537  CallDescription CFRetain{"CFRetain", 1},
538  CFRelease{"CFRelease", 1},
539  CFMakeCollectable{"CFMakeCollectable", 1},
540  CFAutorelease{"CFAutorelease", 1};
541 
542 public:
543  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
544 };
545 } // end anonymous namespace
546 
547 void CFRetainReleaseChecker::checkPreCall(const CallEvent &Call,
548  CheckerContext &C) const {
549  // TODO: Make this check part of CallDescription.
550  if (!Call.isGlobalCFunction())
551  return;
552 
553  // Check if we called CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
554  if (!(Call.isCalled(CFRetain) || Call.isCalled(CFRelease) ||
555  Call.isCalled(CFMakeCollectable) || Call.isCalled(CFAutorelease)))
556  return;
557 
558  // Get the argument's value.
559  SVal ArgVal = Call.getArgSVal(0);
560  Optional<DefinedSVal> DefArgVal = ArgVal.getAs<DefinedSVal>();
561  if (!DefArgVal)
562  return;
563 
564  // Is it null?
565  ProgramStateRef state = C.getState();
566  ProgramStateRef stateNonNull, stateNull;
567  std::tie(stateNonNull, stateNull) = state->assume(*DefArgVal);
568 
569  if (!stateNonNull) {
570  ExplodedNode *N = C.generateErrorNode(stateNull);
571  if (!N)
572  return;
573 
574  SmallString<64> Str;
575  raw_svector_ostream OS(Str);
576  OS << "Null pointer argument in call to "
577  << cast<FunctionDecl>(Call.getDecl())->getName();
578 
579  auto report = llvm::make_unique<BugReport>(BT, OS.str(), N);
580  report->addRange(Call.getArgSourceRange(0));
581  bugreporter::trackExpressionValue(N, Call.getArgExpr(0), *report);
582  C.emitReport(std::move(report));
583  return;
584  }
585 
586  // From here on, we know the argument is non-null.
587  C.addTransition(stateNonNull);
588 }
589 
590 //===----------------------------------------------------------------------===//
591 // Check for sending 'retain', 'release', or 'autorelease' directly to a Class.
592 //===----------------------------------------------------------------------===//
593 
594 namespace {
595 class ClassReleaseChecker : public Checker<check::PreObjCMessage> {
596  mutable Selector releaseS;
597  mutable Selector retainS;
598  mutable Selector autoreleaseS;
599  mutable Selector drainS;
600  mutable std::unique_ptr<BugType> BT;
601 
602 public:
603  void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
604 };
605 } // end anonymous namespace
606 
607 void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
608  CheckerContext &C) const {
609  if (!BT) {
610  BT.reset(new APIMisuse(
611  this, "message incorrectly sent to class instead of class instance"));
612 
613  ASTContext &Ctx = C.getASTContext();
614  releaseS = GetNullarySelector("release", Ctx);
615  retainS = GetNullarySelector("retain", Ctx);
616  autoreleaseS = GetNullarySelector("autorelease", Ctx);
617  drainS = GetNullarySelector("drain", Ctx);
618  }
619 
620  if (msg.isInstanceMessage())
621  return;
622  const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
623  assert(Class);
624 
625  Selector S = msg.getSelector();
626  if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
627  return;
628 
629  if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
630  SmallString<200> buf;
631  llvm::raw_svector_ostream os(buf);
632 
633  os << "The '";
634  S.print(os);
635  os << "' message should be sent to instances "
636  "of class '" << Class->getName()
637  << "' and not the class directly";
638 
639  auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
640  report->addRange(msg.getSourceRange());
641  C.emitReport(std::move(report));
642  }
643 }
644 
645 //===----------------------------------------------------------------------===//
646 // Check for passing non-Objective-C types to variadic methods that expect
647 // only Objective-C types.
648 //===----------------------------------------------------------------------===//
649 
650 namespace {
651 class VariadicMethodTypeChecker : public Checker<check::PreObjCMessage> {
652  mutable Selector arrayWithObjectsS;
653  mutable Selector dictionaryWithObjectsAndKeysS;
654  mutable Selector setWithObjectsS;
655  mutable Selector orderedSetWithObjectsS;
656  mutable Selector initWithObjectsS;
657  mutable Selector initWithObjectsAndKeysS;
658  mutable std::unique_ptr<BugType> BT;
659 
660  bool isVariadicMessage(const ObjCMethodCall &msg) const;
661 
662 public:
663  void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
664 };
665 } // end anonymous namespace
666 
667 /// isVariadicMessage - Returns whether the given message is a variadic message,
668 /// where all arguments must be Objective-C types.
669 bool
670 VariadicMethodTypeChecker::isVariadicMessage(const ObjCMethodCall &msg) const {
671  const ObjCMethodDecl *MD = msg.getDecl();
672 
673  if (!MD || !MD->isVariadic() || isa<ObjCProtocolDecl>(MD->getDeclContext()))
674  return false;
675 
676  Selector S = msg.getSelector();
677 
678  if (msg.isInstanceMessage()) {
679  // FIXME: Ideally we'd look at the receiver interface here, but that's not
680  // useful for init, because alloc returns 'id'. In theory, this could lead
681  // to false positives, for example if there existed a class that had an
682  // initWithObjects: implementation that does accept non-Objective-C pointer
683  // types, but the chance of that happening is pretty small compared to the
684  // gains that this analysis gives.
685  const ObjCInterfaceDecl *Class = MD->getClassInterface();
686 
687  switch (findKnownClass(Class)) {
688  case FC_NSArray:
689  case FC_NSOrderedSet:
690  case FC_NSSet:
691  return S == initWithObjectsS;
692  case FC_NSDictionary:
693  return S == initWithObjectsAndKeysS;
694  default:
695  return false;
696  }
697  } else {
698  const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
699 
700  switch (findKnownClass(Class)) {
701  case FC_NSArray:
702  return S == arrayWithObjectsS;
703  case FC_NSOrderedSet:
704  return S == orderedSetWithObjectsS;
705  case FC_NSSet:
706  return S == setWithObjectsS;
707  case FC_NSDictionary:
708  return S == dictionaryWithObjectsAndKeysS;
709  default:
710  return false;
711  }
712  }
713 }
714 
715 void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
716  CheckerContext &C) const {
717  if (!BT) {
718  BT.reset(new APIMisuse(this,
719  "Arguments passed to variadic method aren't all "
720  "Objective-C pointer types"));
721 
722  ASTContext &Ctx = C.getASTContext();
723  arrayWithObjectsS = GetUnarySelector("arrayWithObjects", Ctx);
724  dictionaryWithObjectsAndKeysS =
725  GetUnarySelector("dictionaryWithObjectsAndKeys", Ctx);
726  setWithObjectsS = GetUnarySelector("setWithObjects", Ctx);
727  orderedSetWithObjectsS = GetUnarySelector("orderedSetWithObjects", Ctx);
728 
729  initWithObjectsS = GetUnarySelector("initWithObjects", Ctx);
730  initWithObjectsAndKeysS = GetUnarySelector("initWithObjectsAndKeys", Ctx);
731  }
732 
733  if (!isVariadicMessage(msg))
734  return;
735 
736  // We are not interested in the selector arguments since they have
737  // well-defined types, so the compiler will issue a warning for them.
738  unsigned variadicArgsBegin = msg.getSelector().getNumArgs();
739 
740  // We're not interested in the last argument since it has to be nil or the
741  // compiler would have issued a warning for it elsewhere.
742  unsigned variadicArgsEnd = msg.getNumArgs() - 1;
743 
744  if (variadicArgsEnd <= variadicArgsBegin)
745  return;
746 
747  // Verify that all arguments have Objective-C types.
748  Optional<ExplodedNode*> errorNode;
749 
750  for (unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) {
751  QualType ArgTy = msg.getArgExpr(I)->getType();
752  if (ArgTy->isObjCObjectPointerType())
753  continue;
754 
755  // Block pointers are treaded as Objective-C pointers.
756  if (ArgTy->isBlockPointerType())
757  continue;
758 
759  // Ignore pointer constants.
760  if (msg.getArgSVal(I).getAs<loc::ConcreteInt>())
761  continue;
762 
763  // Ignore pointer types annotated with 'NSObject' attribute.
764  if (C.getASTContext().isObjCNSObjectType(ArgTy))
765  continue;
766 
767  // Ignore CF references, which can be toll-free bridged.
769  continue;
770 
771  // Generate only one error node to use for all bug reports.
772  if (!errorNode.hasValue())
773  errorNode = C.generateNonFatalErrorNode();
774 
775  if (!errorNode.getValue())
776  continue;
777 
778  SmallString<128> sbuf;
779  llvm::raw_svector_ostream os(sbuf);
780 
781  StringRef TypeName = GetReceiverInterfaceName(msg);
782  if (!TypeName.empty())
783  os << "Argument to '" << TypeName << "' method '";
784  else
785  os << "Argument to method '";
786 
787  msg.getSelector().print(os);
788  os << "' should be an Objective-C pointer type, not '";
789  ArgTy.print(os, C.getLangOpts());
790  os << "'";
791 
792  auto R = llvm::make_unique<BugReport>(*BT, os.str(), 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 countainer 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 void ento::registerCFNumberChecker(CheckerManager &mgr) {
1247  mgr.registerChecker<CFNumberChecker>();
1248 }
1249 
1250 void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
1251  mgr.registerChecker<CFRetainReleaseChecker>();
1252 }
1253 
1254 void ento::registerClassReleaseChecker(CheckerManager &mgr) {
1255  mgr.registerChecker<ClassReleaseChecker>();
1256 }
1257 
1258 void ento::registerVariadicMethodTypeChecker(CheckerManager &mgr) {
1259  mgr.registerChecker<VariadicMethodTypeChecker>();
1260 }
1261 
1262 void ento::registerObjCLoopChecker(CheckerManager &mgr) {
1263  mgr.registerChecker<ObjCLoopChecker>();
1264 }
1265 
1266 void
1267 ento::registerObjCNonNilReturnValueChecker(CheckerManager &mgr) {
1268  mgr.registerChecker<ObjCNonNilReturnValueChecker>();
1269 }
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:1024
Represents a function declaration or definition.
Definition: Decl.h:1732
ObjCDictionaryElement getKeyValueElement(unsigned Index) const
Definition: ExprObjC.h:344
Smart pointer class that efficiently represents Objective-C method names.
A (possibly-)qualified type.
Definition: Type.h:642
bool isBlockPointerType() const
Definition: Type.h:6290
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:2474
ObjCInterfaceDecl * getClassInterface()
Definition: DeclObjC.cpp:1144
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
Definition: Type.h:985
llvm::DenseSet< SymbolRef > InvalidatedSymbols
Definition: Store.h:52
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:30
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:2462
ObjCInterfaceDecl * getReceiverInterface() const
Retrieve the Objective-C interface to which this message is being directed, if known.
Definition: ExprObjC.cpp:333
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:988
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:6716
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:139
Defines the Objective-C statement AST node classes.
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:239
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:1034
ObjCArrayLiteral - used for objective-c array containers; as in: @["Hello", NSApp, [NSNumber numberWithInt:42]];.
Definition: ExprObjC.h:171
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:6630
IdentifierTable & Idents
Definition: ASTContext.h:565
bool isUnarySelector() const
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
Definition: DeclObjC.cpp:986
Represents any expression that calls an Objective-C method.
Definition: CallEvent.h:970
Selector GetNullarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing a nullary selector.
Definition: ASTContext.h:2952
Expr * Key
The key for the dictionary element.
Definition: ExprObjC.h:241
#define UINT_MAX
Definition: limits.h:72
Represents an ObjC class declaration.
Definition: DeclObjC.h:1164
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:302
This represents one expression.
Definition: Expr.h:106
static FoundationClass findKnownClass(const ObjCInterfaceDecl *ID, bool IncludeSuperclasses=true)
ObjCDictionaryLiteral - AST node to represent objective-c dictionary literals; as in:"name" : NSUserN...
Definition: ExprObjC.h:288
DeclContext * getDeclContext()
Definition: DeclBase.h:427
ObjCInterfaceDecl * getSuperClass() const
Definition: DeclObjC.cpp:338
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:128
Expr * getElement(unsigned Index)
getElement - Return the Element at the specified index.
Definition: ExprObjC.h:213
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:342
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Definition: Stmt.h:841
CanQualType FloatTy
Definition: ASTContext.h:1027
static Selector getKeywordSelector(ASTContext &Ctx, IdentifierInfos *... IIs)
bool isObjCObjectPointerType() const
Definition: Type.h:6379
ObjCBoxedExpr - used for generalized expression boxing.
Definition: ExprObjC.h:117
const ObjCMethodDecl * getDecl() const override
Definition: CallEvent.h:998
Expr * Value
The value of the dictionary element.
Definition: ExprObjC.h:244
StringRef getName() const
Return the actual identifier string.
virtual const ObjCMessageExpr * getOriginExpr() const
Definition: CallEvent.h:994
CanQualType CharTy
Definition: ASTContext.h:1017
Selector getSelector() const
Definition: CallEvent.h:1018
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:5780
bool isInstanceMessage() const
Definition: CallEvent.h:1010
ObjCInterfaceDecl * getInterfaceDecl() const
If this pointer points to an Objective @interface type, gets the declaration for that interface...
Definition: Type.h:5836
unsigned getNumElements() const
getNumElements - Return number of elements of objective-c array literal.
Definition: ExprObjC.h:210
Represents Objective-C&#39;s collection statement.
Definition: StmtObjC.h:24
unsigned getNumArgs() const override
Definition: CallEvent.h:1002
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2069
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2252
const Expr * getArgExpr(unsigned Index) const override
Definition: CallEvent.h:1006
Selector GetUnarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing an unary selector.
Definition: ASTContext.h:2958
pred_iterator pred_begin()
bool isVariadic() const
Definition: DeclObjC.h:419
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:268
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2405
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:153
CanQualType DoubleTy
Definition: ASTContext.h:1027