xref: /llvm-project/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp (revision 0dbb783c7be1756482c491b3635dd07dd5fe712c)
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 "SelectorExtras.h"
18 #include "clang/AST/ASTContext.h"
19 #include "clang/AST/DeclObjC.h"
20 #include "clang/AST/Expr.h"
21 #include "clang/AST/ExprObjC.h"
22 #include "clang/AST/StmtObjC.h"
23 #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
24 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
25 #include "clang/StaticAnalyzer/Core/Checker.h"
26 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
27 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
28 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
29 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
30 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
31 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
32 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.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 
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 
58 enum FoundationClass {
59   FC_None,
60   FC_NSArray,
61   FC_NSDictionary,
62   FC_NSEnumerator,
63   FC_NSNull,
64   FC_NSOrderedSet,
65   FC_NSSet,
66   FC_NSString
67 };
68 
69 static FoundationClass findKnownClass(const ObjCInterfaceDecl *ID,
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 }
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.generateSink()) {
144       generateBugReport(N, Msg, E->getSourceRange(), E, C);
145     }
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   if (ExplodedNode *N = C.generateSink()) {
161     SmallString<128> sbuf;
162     llvm::raw_svector_ostream os(sbuf);
163 
164     if (CanBeSubscript && msg.getMessageKind() == OCM_Subscript) {
165 
166       if (Class == FC_NSArray) {
167         os << "Array element cannot be nil";
168       } else if (Class == FC_NSDictionary) {
169         if (Arg == 0) {
170           os << "Value stored into '";
171           os << GetReceiverInterfaceName(msg) << "' cannot be nil";
172         } else {
173           assert(Arg == 1);
174           os << "'"<< GetReceiverInterfaceName(msg) << "' key cannot be nil";
175         }
176       } else
177         llvm_unreachable("Missing foundation class for the subscript expr");
178 
179     } else {
180       if (Class == FC_NSDictionary) {
181         if (Arg == 0)
182           os << "Value argument ";
183         else {
184           assert(Arg == 1);
185           os << "Key argument ";
186         }
187         os << "to '";
188         msg.getSelector().print(os);
189         os << "' cannot be nil";
190       } else {
191         os << "Argument to '" << GetReceiverInterfaceName(msg) << "' method '";
192         msg.getSelector().print(os);
193         os << "' cannot be nil";
194       }
195     }
196 
197     generateBugReport(N, os.str(), msg.getArgSourceRange(Arg),
198                       msg.getArgExpr(Arg), C);
199   }
200 }
201 
202 void NilArgChecker::generateBugReport(ExplodedNode *N,
203                                       StringRef Msg,
204                                       SourceRange Range,
205                                       const Expr *E,
206                                       CheckerContext &C) const {
207   if (!BT)
208     BT.reset(new APIMisuse(this, "nil argument"));
209 
210   BugReport *R = new BugReport(*BT, Msg, N);
211   R->addRange(Range);
212   bugreporter::trackNullOrUndefValue(N, E, *R);
213   C.emitReport(R);
214 }
215 
216 void NilArgChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
217                                         CheckerContext &C) const {
218   const ObjCInterfaceDecl *ID = msg.getReceiverInterface();
219   if (!ID)
220     return;
221 
222   FoundationClass Class = findKnownClass(ID);
223 
224   static const unsigned InvalidArgIndex = UINT_MAX;
225   unsigned Arg = InvalidArgIndex;
226   bool CanBeSubscript = false;
227 
228   if (Class == FC_NSString) {
229     Selector S = msg.getSelector();
230 
231     if (S.isUnarySelector())
232       return;
233 
234     if (StringSelectors.empty()) {
235       ASTContext &Ctx = C.getASTContext();
236       Selector Sels[] = {
237         getKeywordSelector(Ctx, "caseInsensitiveCompare", nullptr),
238         getKeywordSelector(Ctx, "compare", nullptr),
239         getKeywordSelector(Ctx, "compare", "options", nullptr),
240         getKeywordSelector(Ctx, "compare", "options", "range", nullptr),
241         getKeywordSelector(Ctx, "compare", "options", "range", "locale",
242                            nullptr),
243         getKeywordSelector(Ctx, "componentsSeparatedByCharactersInSet",
244                            nullptr),
245         getKeywordSelector(Ctx, "initWithFormat",
246                            nullptr),
247         getKeywordSelector(Ctx, "localizedCaseInsensitiveCompare", nullptr),
248         getKeywordSelector(Ctx, "localizedCompare", nullptr),
249         getKeywordSelector(Ctx, "localizedStandardCompare", nullptr),
250       };
251       for (Selector KnownSel : Sels)
252         StringSelectors[KnownSel] = 0;
253     }
254     auto I = StringSelectors.find(S);
255     if (I == StringSelectors.end())
256       return;
257     Arg = I->second;
258   } else if (Class == FC_NSArray) {
259     Selector S = msg.getSelector();
260 
261     if (S.isUnarySelector())
262       return;
263 
264     if (ArrayWithObjectSel.isNull()) {
265       ASTContext &Ctx = C.getASTContext();
266       ArrayWithObjectSel = getKeywordSelector(Ctx, "arrayWithObject", nullptr);
267       AddObjectSel = getKeywordSelector(Ctx, "addObject", nullptr);
268       InsertObjectAtIndexSel =
269         getKeywordSelector(Ctx, "insertObject", "atIndex", nullptr);
270       ReplaceObjectAtIndexWithObjectSel =
271         getKeywordSelector(Ctx, "replaceObjectAtIndex", "withObject", nullptr);
272       SetObjectAtIndexedSubscriptSel =
273         getKeywordSelector(Ctx, "setObject", "atIndexedSubscript", nullptr);
274       ArrayByAddingObjectSel =
275         getKeywordSelector(Ctx, "arrayByAddingObject", nullptr);
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", nullptr);
297       SetObjectForKeySel =
298         getKeywordSelector(Ctx, "setObject", "forKey", nullptr);
299       SetObjectForKeyedSubscriptSel =
300         getKeywordSelector(Ctx, "setObject", "forKeyedSubscript", nullptr);
301       RemoveObjectForKeySel =
302         getKeywordSelector(Ctx, "removeObjectForKey", nullptr);
303     }
304 
305     if (S == DictionaryWithObjectForKeySel || S == SetObjectForKeySel) {
306       Arg = 0;
307       warnIfNilArg(C, msg, /* Arg */1, Class);
308     } else if (S == SetObjectForKeyedSubscriptSel) {
309       CanBeSubscript = true;
310       Arg = 0;
311       warnIfNilArg(C, msg, /* Arg */1, Class, CanBeSubscript);
312     } else if (S == RemoveObjectForKeySel) {
313       Arg = 0;
314     }
315   }
316 
317   // If argument is '0', report a warning.
318   if ((Arg != InvalidArgIndex))
319     warnIfNilArg(C, msg, Arg, Class, CanBeSubscript);
320 }
321 
322 void NilArgChecker::checkPostStmt(const ObjCArrayLiteral *AL,
323                                   CheckerContext &C) const {
324   unsigned NumOfElements = AL->getNumElements();
325   for (unsigned i = 0; i < NumOfElements; ++i) {
326     warnIfNilExpr(AL->getElement(i), "Array element cannot be nil", C);
327   }
328 }
329 
330 void NilArgChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
331                                   CheckerContext &C) const {
332   unsigned NumOfElements = DL->getNumElements();
333   for (unsigned i = 0; i < NumOfElements; ++i) {
334     ObjCDictionaryElement Element = DL->getKeyValueElement(i);
335     warnIfNilExpr(Element.Key, "Dictionary key cannot be nil", C);
336     warnIfNilExpr(Element.Value, "Dictionary value cannot be nil", C);
337   }
338 }
339 
340 //===----------------------------------------------------------------------===//
341 // Error reporting.
342 //===----------------------------------------------------------------------===//
343 
344 namespace {
345 class CFNumberCreateChecker : public Checker< check::PreStmt<CallExpr> > {
346   mutable std::unique_ptr<APIMisuse> BT;
347   mutable IdentifierInfo* II;
348 public:
349   CFNumberCreateChecker() : II(nullptr) {}
350 
351   void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
352 
353 private:
354   void EmitError(const TypedRegion* R, const Expr *Ex,
355                 uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind);
356 };
357 } // end anonymous namespace
358 
359 enum CFNumberType {
360   kCFNumberSInt8Type = 1,
361   kCFNumberSInt16Type = 2,
362   kCFNumberSInt32Type = 3,
363   kCFNumberSInt64Type = 4,
364   kCFNumberFloat32Type = 5,
365   kCFNumberFloat64Type = 6,
366   kCFNumberCharType = 7,
367   kCFNumberShortType = 8,
368   kCFNumberIntType = 9,
369   kCFNumberLongType = 10,
370   kCFNumberLongLongType = 11,
371   kCFNumberFloatType = 12,
372   kCFNumberDoubleType = 13,
373   kCFNumberCFIndexType = 14,
374   kCFNumberNSIntegerType = 15,
375   kCFNumberCGFloatType = 16
376 };
377 
378 static Optional<uint64_t> GetCFNumberSize(ASTContext &Ctx, uint64_t i) {
379   static const unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 };
380 
381   if (i < kCFNumberCharType)
382     return FixedSize[i-1];
383 
384   QualType T;
385 
386   switch (i) {
387     case kCFNumberCharType:     T = Ctx.CharTy;     break;
388     case kCFNumberShortType:    T = Ctx.ShortTy;    break;
389     case kCFNumberIntType:      T = Ctx.IntTy;      break;
390     case kCFNumberLongType:     T = Ctx.LongTy;     break;
391     case kCFNumberLongLongType: T = Ctx.LongLongTy; break;
392     case kCFNumberFloatType:    T = Ctx.FloatTy;    break;
393     case kCFNumberDoubleType:   T = Ctx.DoubleTy;   break;
394     case kCFNumberCFIndexType:
395     case kCFNumberNSIntegerType:
396     case kCFNumberCGFloatType:
397       // FIXME: We need a way to map from names to Type*.
398     default:
399       return None;
400   }
401 
402   return Ctx.getTypeSize(T);
403 }
404 
405 #if 0
406 static const char* GetCFNumberTypeStr(uint64_t i) {
407   static const char* Names[] = {
408     "kCFNumberSInt8Type",
409     "kCFNumberSInt16Type",
410     "kCFNumberSInt32Type",
411     "kCFNumberSInt64Type",
412     "kCFNumberFloat32Type",
413     "kCFNumberFloat64Type",
414     "kCFNumberCharType",
415     "kCFNumberShortType",
416     "kCFNumberIntType",
417     "kCFNumberLongType",
418     "kCFNumberLongLongType",
419     "kCFNumberFloatType",
420     "kCFNumberDoubleType",
421     "kCFNumberCFIndexType",
422     "kCFNumberNSIntegerType",
423     "kCFNumberCGFloatType"
424   };
425 
426   return i <= kCFNumberCGFloatType ? Names[i-1] : "Invalid CFNumberType";
427 }
428 #endif
429 
430 void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
431                                          CheckerContext &C) const {
432   ProgramStateRef state = C.getState();
433   const FunctionDecl *FD = C.getCalleeDecl(CE);
434   if (!FD)
435     return;
436 
437   ASTContext &Ctx = C.getASTContext();
438   if (!II)
439     II = &Ctx.Idents.get("CFNumberCreate");
440 
441   if (FD->getIdentifier() != II || CE->getNumArgs() != 3)
442     return;
443 
444   // Get the value of the "theType" argument.
445   const LocationContext *LCtx = C.getLocationContext();
446   SVal TheTypeVal = state->getSVal(CE->getArg(1), LCtx);
447 
448   // FIXME: We really should allow ranges of valid theType values, and
449   //   bifurcate the state appropriately.
450   Optional<nonloc::ConcreteInt> V = TheTypeVal.getAs<nonloc::ConcreteInt>();
451   if (!V)
452     return;
453 
454   uint64_t NumberKind = V->getValue().getLimitedValue();
455   Optional<uint64_t> OptTargetSize = GetCFNumberSize(Ctx, NumberKind);
456 
457   // FIXME: In some cases we can emit an error.
458   if (!OptTargetSize)
459     return;
460 
461   uint64_t TargetSize = *OptTargetSize;
462 
463   // Look at the value of the integer being passed by reference.  Essentially
464   // we want to catch cases where the value passed in is not equal to the
465   // size of the type being created.
466   SVal TheValueExpr = state->getSVal(CE->getArg(2), LCtx);
467 
468   // FIXME: Eventually we should handle arbitrary locations.  We can do this
469   //  by having an enhanced memory model that does low-level typing.
470   Optional<loc::MemRegionVal> LV = TheValueExpr.getAs<loc::MemRegionVal>();
471   if (!LV)
472     return;
473 
474   const TypedValueRegion* R = dyn_cast<TypedValueRegion>(LV->stripCasts());
475   if (!R)
476     return;
477 
478   QualType T = Ctx.getCanonicalType(R->getValueType());
479 
480   // FIXME: If the pointee isn't an integer type, should we flag a warning?
481   //  People can do weird stuff with pointers.
482 
483   if (!T->isIntegralOrEnumerationType())
484     return;
485 
486   uint64_t SourceSize = Ctx.getTypeSize(T);
487 
488   // CHECK: is SourceSize == TargetSize
489   if (SourceSize == TargetSize)
490     return;
491 
492   // Generate an error.  Only generate a sink if 'SourceSize < TargetSize';
493   // otherwise generate a regular node.
494   //
495   // FIXME: We can actually create an abstract "CFNumber" object that has
496   //  the bits initialized to the provided values.
497   //
498   if (ExplodedNode *N = SourceSize < TargetSize ? C.generateSink()
499                                                 : C.addTransition()) {
500     SmallString<128> sbuf;
501     llvm::raw_svector_ostream os(sbuf);
502 
503     os << (SourceSize == 8 ? "An " : "A ")
504        << SourceSize << " bit integer is used to initialize a CFNumber "
505                         "object that represents "
506        << (TargetSize == 8 ? "an " : "a ")
507        << TargetSize << " bit integer. ";
508 
509     if (SourceSize < TargetSize)
510       os << (TargetSize - SourceSize)
511       << " bits of the CFNumber value will be garbage." ;
512     else
513       os << (SourceSize - TargetSize)
514       << " bits of the input integer will be lost.";
515 
516     if (!BT)
517       BT.reset(new APIMisuse(this, "Bad use of CFNumberCreate"));
518 
519     BugReport *report = new BugReport(*BT, os.str(), N);
520     report->addRange(CE->getArg(2)->getSourceRange());
521     C.emitReport(report);
522   }
523 }
524 
525 //===----------------------------------------------------------------------===//
526 // CFRetain/CFRelease/CFMakeCollectable checking for null arguments.
527 //===----------------------------------------------------------------------===//
528 
529 namespace {
530 class CFRetainReleaseChecker : public Checker< check::PreStmt<CallExpr> > {
531   mutable std::unique_ptr<APIMisuse> BT;
532   mutable IdentifierInfo *Retain, *Release, *MakeCollectable;
533 public:
534   CFRetainReleaseChecker()
535       : Retain(nullptr), Release(nullptr), MakeCollectable(nullptr) {}
536   void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
537 };
538 } // end anonymous namespace
539 
540 
541 void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
542                                           CheckerContext &C) const {
543   // If the CallExpr doesn't have exactly 1 argument just give up checking.
544   if (CE->getNumArgs() != 1)
545     return;
546 
547   ProgramStateRef state = C.getState();
548   const FunctionDecl *FD = C.getCalleeDecl(CE);
549   if (!FD)
550     return;
551 
552   if (!BT) {
553     ASTContext &Ctx = C.getASTContext();
554     Retain = &Ctx.Idents.get("CFRetain");
555     Release = &Ctx.Idents.get("CFRelease");
556     MakeCollectable = &Ctx.Idents.get("CFMakeCollectable");
557     BT.reset(new APIMisuse(
558         this, "null passed to CFRetain/CFRelease/CFMakeCollectable"));
559   }
560 
561   // Check if we called CFRetain/CFRelease/CFMakeCollectable.
562   const IdentifierInfo *FuncII = FD->getIdentifier();
563   if (!(FuncII == Retain || FuncII == Release || FuncII == MakeCollectable))
564     return;
565 
566   // FIXME: The rest of this just checks that the argument is non-null.
567   // It should probably be refactored and combined with NonNullParamChecker.
568 
569   // Get the argument's value.
570   const Expr *Arg = CE->getArg(0);
571   SVal ArgVal = state->getSVal(Arg, C.getLocationContext());
572   Optional<DefinedSVal> DefArgVal = ArgVal.getAs<DefinedSVal>();
573   if (!DefArgVal)
574     return;
575 
576   // Get a NULL value.
577   SValBuilder &svalBuilder = C.getSValBuilder();
578   DefinedSVal zero =
579       svalBuilder.makeZeroVal(Arg->getType()).castAs<DefinedSVal>();
580 
581   // Make an expression asserting that they're equal.
582   DefinedOrUnknownSVal ArgIsNull = svalBuilder.evalEQ(state, zero, *DefArgVal);
583 
584   // Are they equal?
585   ProgramStateRef stateTrue, stateFalse;
586   std::tie(stateTrue, stateFalse) = state->assume(ArgIsNull);
587 
588   if (stateTrue && !stateFalse) {
589     ExplodedNode *N = C.generateSink(stateTrue);
590     if (!N)
591       return;
592 
593     const char *description;
594     if (FuncII == Retain)
595       description = "Null pointer argument in call to CFRetain";
596     else if (FuncII == Release)
597       description = "Null pointer argument in call to CFRelease";
598     else if (FuncII == MakeCollectable)
599       description = "Null pointer argument in call to CFMakeCollectable";
600     else
601       llvm_unreachable("impossible case");
602 
603     BugReport *report = new BugReport(*BT, description, N);
604     report->addRange(Arg->getSourceRange());
605     bugreporter::trackNullOrUndefValue(N, Arg, *report);
606     C.emitReport(report);
607     return;
608   }
609 
610   // From here on, we know the argument is non-null.
611   C.addTransition(stateFalse);
612 }
613 
614 //===----------------------------------------------------------------------===//
615 // Check for sending 'retain', 'release', or 'autorelease' directly to a Class.
616 //===----------------------------------------------------------------------===//
617 
618 namespace {
619 class ClassReleaseChecker : public Checker<check::PreObjCMessage> {
620   mutable Selector releaseS;
621   mutable Selector retainS;
622   mutable Selector autoreleaseS;
623   mutable Selector drainS;
624   mutable std::unique_ptr<BugType> BT;
625 
626 public:
627   void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
628 };
629 }
630 
631 void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
632                                               CheckerContext &C) const {
633 
634   if (!BT) {
635     BT.reset(new APIMisuse(
636         this, "message incorrectly sent to class instead of class instance"));
637 
638     ASTContext &Ctx = C.getASTContext();
639     releaseS = GetNullarySelector("release", Ctx);
640     retainS = GetNullarySelector("retain", Ctx);
641     autoreleaseS = GetNullarySelector("autorelease", Ctx);
642     drainS = GetNullarySelector("drain", Ctx);
643   }
644 
645   if (msg.isInstanceMessage())
646     return;
647   const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
648   assert(Class);
649 
650   Selector S = msg.getSelector();
651   if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
652     return;
653 
654   if (ExplodedNode *N = C.addTransition()) {
655     SmallString<200> buf;
656     llvm::raw_svector_ostream os(buf);
657 
658     os << "The '";
659     S.print(os);
660     os << "' message should be sent to instances "
661           "of class '" << Class->getName()
662        << "' and not the class directly";
663 
664     BugReport *report = new BugReport(*BT, os.str(), N);
665     report->addRange(msg.getSourceRange());
666     C.emitReport(report);
667   }
668 }
669 
670 //===----------------------------------------------------------------------===//
671 // Check for passing non-Objective-C types to variadic methods that expect
672 // only Objective-C types.
673 //===----------------------------------------------------------------------===//
674 
675 namespace {
676 class VariadicMethodTypeChecker : public Checker<check::PreObjCMessage> {
677   mutable Selector arrayWithObjectsS;
678   mutable Selector dictionaryWithObjectsAndKeysS;
679   mutable Selector setWithObjectsS;
680   mutable Selector orderedSetWithObjectsS;
681   mutable Selector initWithObjectsS;
682   mutable Selector initWithObjectsAndKeysS;
683   mutable std::unique_ptr<BugType> BT;
684 
685   bool isVariadicMessage(const ObjCMethodCall &msg) const;
686 
687 public:
688   void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
689 };
690 }
691 
692 /// isVariadicMessage - Returns whether the given message is a variadic message,
693 /// where all arguments must be Objective-C types.
694 bool
695 VariadicMethodTypeChecker::isVariadicMessage(const ObjCMethodCall &msg) const {
696   const ObjCMethodDecl *MD = msg.getDecl();
697 
698   if (!MD || !MD->isVariadic() || isa<ObjCProtocolDecl>(MD->getDeclContext()))
699     return false;
700 
701   Selector S = msg.getSelector();
702 
703   if (msg.isInstanceMessage()) {
704     // FIXME: Ideally we'd look at the receiver interface here, but that's not
705     // useful for init, because alloc returns 'id'. In theory, this could lead
706     // to false positives, for example if there existed a class that had an
707     // initWithObjects: implementation that does accept non-Objective-C pointer
708     // types, but the chance of that happening is pretty small compared to the
709     // gains that this analysis gives.
710     const ObjCInterfaceDecl *Class = MD->getClassInterface();
711 
712     switch (findKnownClass(Class)) {
713     case FC_NSArray:
714     case FC_NSOrderedSet:
715     case FC_NSSet:
716       return S == initWithObjectsS;
717     case FC_NSDictionary:
718       return S == initWithObjectsAndKeysS;
719     default:
720       return false;
721     }
722   } else {
723     const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
724 
725     switch (findKnownClass(Class)) {
726       case FC_NSArray:
727         return S == arrayWithObjectsS;
728       case FC_NSOrderedSet:
729         return S == orderedSetWithObjectsS;
730       case FC_NSSet:
731         return S == setWithObjectsS;
732       case FC_NSDictionary:
733         return S == dictionaryWithObjectsAndKeysS;
734       default:
735         return false;
736     }
737   }
738 }
739 
740 void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
741                                                     CheckerContext &C) const {
742   if (!BT) {
743     BT.reset(new APIMisuse(this,
744                            "Arguments passed to variadic method aren't all "
745                            "Objective-C pointer types"));
746 
747     ASTContext &Ctx = C.getASTContext();
748     arrayWithObjectsS = GetUnarySelector("arrayWithObjects", Ctx);
749     dictionaryWithObjectsAndKeysS =
750       GetUnarySelector("dictionaryWithObjectsAndKeys", Ctx);
751     setWithObjectsS = GetUnarySelector("setWithObjects", Ctx);
752     orderedSetWithObjectsS = GetUnarySelector("orderedSetWithObjects", Ctx);
753 
754     initWithObjectsS = GetUnarySelector("initWithObjects", Ctx);
755     initWithObjectsAndKeysS = GetUnarySelector("initWithObjectsAndKeys", Ctx);
756   }
757 
758   if (!isVariadicMessage(msg))
759       return;
760 
761   // We are not interested in the selector arguments since they have
762   // well-defined types, so the compiler will issue a warning for them.
763   unsigned variadicArgsBegin = msg.getSelector().getNumArgs();
764 
765   // We're not interested in the last argument since it has to be nil or the
766   // compiler would have issued a warning for it elsewhere.
767   unsigned variadicArgsEnd = msg.getNumArgs() - 1;
768 
769   if (variadicArgsEnd <= variadicArgsBegin)
770     return;
771 
772   // Verify that all arguments have Objective-C types.
773   Optional<ExplodedNode*> errorNode;
774 
775   for (unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) {
776     QualType ArgTy = msg.getArgExpr(I)->getType();
777     if (ArgTy->isObjCObjectPointerType())
778       continue;
779 
780     // Block pointers are treaded as Objective-C pointers.
781     if (ArgTy->isBlockPointerType())
782       continue;
783 
784     // Ignore pointer constants.
785     if (msg.getArgSVal(I).getAs<loc::ConcreteInt>())
786       continue;
787 
788     // Ignore pointer types annotated with 'NSObject' attribute.
789     if (C.getASTContext().isObjCNSObjectType(ArgTy))
790       continue;
791 
792     // Ignore CF references, which can be toll-free bridged.
793     if (coreFoundation::isCFObjectRef(ArgTy))
794       continue;
795 
796     // Generate only one error node to use for all bug reports.
797     if (!errorNode.hasValue())
798       errorNode = C.addTransition();
799 
800     if (!errorNode.getValue())
801       continue;
802 
803     SmallString<128> sbuf;
804     llvm::raw_svector_ostream os(sbuf);
805 
806     StringRef TypeName = GetReceiverInterfaceName(msg);
807     if (!TypeName.empty())
808       os << "Argument to '" << TypeName << "' method '";
809     else
810       os << "Argument to method '";
811 
812     msg.getSelector().print(os);
813     os << "' should be an Objective-C pointer type, not '";
814     ArgTy.print(os, C.getLangOpts());
815     os << "'";
816 
817     BugReport *R = new BugReport(*BT, os.str(), errorNode.getValue());
818     R->addRange(msg.getArgSourceRange(I));
819     C.emitReport(R);
820   }
821 }
822 
823 //===----------------------------------------------------------------------===//
824 // Improves the modeling of loops over Cocoa collections.
825 //===----------------------------------------------------------------------===//
826 
827 // The map from container symbol to the container count symbol.
828 // We currently will remember the last countainer count symbol encountered.
829 REGISTER_MAP_WITH_PROGRAMSTATE(ContainerCountMap, SymbolRef, SymbolRef)
830 REGISTER_MAP_WITH_PROGRAMSTATE(ContainerNonEmptyMap, SymbolRef, bool)
831 
832 namespace {
833 class ObjCLoopChecker
834   : public Checker<check::PostStmt<ObjCForCollectionStmt>,
835                    check::PostObjCMessage,
836                    check::DeadSymbols,
837                    check::PointerEscape > {
838   mutable IdentifierInfo *CountSelectorII;
839 
840   bool isCollectionCountMethod(const ObjCMethodCall &M,
841                                CheckerContext &C) const;
842 
843 public:
844   ObjCLoopChecker() : CountSelectorII(nullptr) {}
845   void checkPostStmt(const ObjCForCollectionStmt *FCS, CheckerContext &C) const;
846   void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
847   void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
848   ProgramStateRef checkPointerEscape(ProgramStateRef State,
849                                      const InvalidatedSymbols &Escaped,
850                                      const CallEvent *Call,
851                                      PointerEscapeKind Kind) const;
852 };
853 }
854 
855 static bool isKnownNonNilCollectionType(QualType T) {
856   const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
857   if (!PT)
858     return false;
859 
860   const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
861   if (!ID)
862     return false;
863 
864   switch (findKnownClass(ID)) {
865   case FC_NSArray:
866   case FC_NSDictionary:
867   case FC_NSEnumerator:
868   case FC_NSOrderedSet:
869   case FC_NSSet:
870     return true;
871   default:
872     return false;
873   }
874 }
875 
876 /// Assumes that the collection is non-nil.
877 ///
878 /// If the collection is known to be nil, returns NULL to indicate an infeasible
879 /// path.
880 static ProgramStateRef checkCollectionNonNil(CheckerContext &C,
881                                              ProgramStateRef State,
882                                              const ObjCForCollectionStmt *FCS) {
883   if (!State)
884     return nullptr;
885 
886   SVal CollectionVal = C.getSVal(FCS->getCollection());
887   Optional<DefinedSVal> KnownCollection = CollectionVal.getAs<DefinedSVal>();
888   if (!KnownCollection)
889     return State;
890 
891   ProgramStateRef StNonNil, StNil;
892   std::tie(StNonNil, StNil) = State->assume(*KnownCollection);
893   if (StNil && !StNonNil) {
894     // The collection is nil. This path is infeasible.
895     return nullptr;
896   }
897 
898   return StNonNil;
899 }
900 
901 /// Assumes that the collection elements are non-nil.
902 ///
903 /// This only applies if the collection is one of those known not to contain
904 /// nil values.
905 static ProgramStateRef checkElementNonNil(CheckerContext &C,
906                                           ProgramStateRef State,
907                                           const ObjCForCollectionStmt *FCS) {
908   if (!State)
909     return nullptr;
910 
911   // See if the collection is one where we /know/ the elements are non-nil.
912   if (!isKnownNonNilCollectionType(FCS->getCollection()->getType()))
913     return State;
914 
915   const LocationContext *LCtx = C.getLocationContext();
916   const Stmt *Element = FCS->getElement();
917 
918   // FIXME: Copied from ExprEngineObjC.
919   Optional<Loc> ElementLoc;
920   if (const DeclStmt *DS = dyn_cast<DeclStmt>(Element)) {
921     const VarDecl *ElemDecl = cast<VarDecl>(DS->getSingleDecl());
922     assert(ElemDecl->getInit() == nullptr);
923     ElementLoc = State->getLValue(ElemDecl, LCtx);
924   } else {
925     ElementLoc = State->getSVal(Element, LCtx).getAs<Loc>();
926   }
927 
928   if (!ElementLoc)
929     return State;
930 
931   // Go ahead and assume the value is non-nil.
932   SVal Val = State->getSVal(*ElementLoc);
933   return State->assume(Val.castAs<DefinedOrUnknownSVal>(), true);
934 }
935 
936 /// Returns NULL state if the collection is known to contain elements
937 /// (or is known not to contain elements if the Assumption parameter is false.)
938 static ProgramStateRef
939 assumeCollectionNonEmpty(CheckerContext &C, ProgramStateRef State,
940                          SymbolRef CollectionS, bool Assumption) {
941   if (!State || !CollectionS)
942     return State;
943 
944   const SymbolRef *CountS = State->get<ContainerCountMap>(CollectionS);
945   if (!CountS) {
946     const bool *KnownNonEmpty = State->get<ContainerNonEmptyMap>(CollectionS);
947     if (!KnownNonEmpty)
948       return State->set<ContainerNonEmptyMap>(CollectionS, Assumption);
949     return (Assumption == *KnownNonEmpty) ? State : nullptr;
950   }
951 
952   SValBuilder &SvalBuilder = C.getSValBuilder();
953   SVal CountGreaterThanZeroVal =
954     SvalBuilder.evalBinOp(State, BO_GT,
955                           nonloc::SymbolVal(*CountS),
956                           SvalBuilder.makeIntVal(0, (*CountS)->getType()),
957                           SvalBuilder.getConditionType());
958   Optional<DefinedSVal> CountGreaterThanZero =
959     CountGreaterThanZeroVal.getAs<DefinedSVal>();
960   if (!CountGreaterThanZero) {
961     // The SValBuilder cannot construct a valid SVal for this condition.
962     // This means we cannot properly reason about it.
963     return State;
964   }
965 
966   return State->assume(*CountGreaterThanZero, Assumption);
967 }
968 
969 static ProgramStateRef
970 assumeCollectionNonEmpty(CheckerContext &C, ProgramStateRef State,
971                          const ObjCForCollectionStmt *FCS,
972                          bool Assumption) {
973   if (!State)
974     return nullptr;
975 
976   SymbolRef CollectionS =
977     State->getSVal(FCS->getCollection(), C.getLocationContext()).getAsSymbol();
978   return assumeCollectionNonEmpty(C, State, CollectionS, Assumption);
979 }
980 
981 
982 /// If the fist block edge is a back edge, we are reentering the loop.
983 static bool alreadyExecutedAtLeastOneLoopIteration(const ExplodedNode *N,
984                                              const ObjCForCollectionStmt *FCS) {
985   if (!N)
986     return false;
987 
988   ProgramPoint P = N->getLocation();
989   if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
990     if (BE->getSrc()->getLoopTarget() == FCS)
991       return true;
992     return false;
993   }
994 
995   // Keep looking for a block edge.
996   for (ExplodedNode::const_pred_iterator I = N->pred_begin(),
997                                          E = N->pred_end(); I != E; ++I) {
998     if (alreadyExecutedAtLeastOneLoopIteration(*I, FCS))
999       return true;
1000   }
1001 
1002   return false;
1003 }
1004 
1005 void ObjCLoopChecker::checkPostStmt(const ObjCForCollectionStmt *FCS,
1006                                     CheckerContext &C) const {
1007   ProgramStateRef State = C.getState();
1008 
1009   // Check if this is the branch for the end of the loop.
1010   SVal CollectionSentinel = C.getSVal(FCS);
1011   if (CollectionSentinel.isZeroConstant()) {
1012     if (!alreadyExecutedAtLeastOneLoopIteration(C.getPredecessor(), FCS))
1013       State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/false);
1014 
1015   // Otherwise, this is a branch that goes through the loop body.
1016   } else {
1017     State = checkCollectionNonNil(C, State, FCS);
1018     State = checkElementNonNil(C, State, FCS);
1019     State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/true);
1020   }
1021 
1022   if (!State)
1023     C.generateSink();
1024   else if (State != C.getState())
1025     C.addTransition(State);
1026 }
1027 
1028 bool ObjCLoopChecker::isCollectionCountMethod(const ObjCMethodCall &M,
1029                                               CheckerContext &C) const {
1030   Selector S = M.getSelector();
1031   // Initialize the identifiers on first use.
1032   if (!CountSelectorII)
1033     CountSelectorII = &C.getASTContext().Idents.get("count");
1034 
1035   // If the method returns collection count, record the value.
1036   if (S.isUnarySelector() &&
1037       (S.getIdentifierInfoForSlot(0) == CountSelectorII))
1038     return true;
1039 
1040   return false;
1041 }
1042 
1043 void ObjCLoopChecker::checkPostObjCMessage(const ObjCMethodCall &M,
1044                                            CheckerContext &C) const {
1045   if (!M.isInstanceMessage())
1046     return;
1047 
1048   const ObjCInterfaceDecl *ClassID = M.getReceiverInterface();
1049   if (!ClassID)
1050     return;
1051 
1052   FoundationClass Class = findKnownClass(ClassID);
1053   if (Class != FC_NSDictionary &&
1054       Class != FC_NSArray &&
1055       Class != FC_NSSet &&
1056       Class != FC_NSOrderedSet)
1057     return;
1058 
1059   SymbolRef ContainerS = M.getReceiverSVal().getAsSymbol();
1060   if (!ContainerS)
1061     return;
1062 
1063   // If we are processing a call to "count", get the symbolic value returned by
1064   // a call to "count" and add it to the map.
1065   if (!isCollectionCountMethod(M, C))
1066     return;
1067 
1068   const Expr *MsgExpr = M.getOriginExpr();
1069   SymbolRef CountS = C.getSVal(MsgExpr).getAsSymbol();
1070   if (CountS) {
1071     ProgramStateRef State = C.getState();
1072 
1073     C.getSymbolManager().addSymbolDependency(ContainerS, CountS);
1074     State = State->set<ContainerCountMap>(ContainerS, CountS);
1075 
1076     if (const bool *NonEmpty = State->get<ContainerNonEmptyMap>(ContainerS)) {
1077       State = State->remove<ContainerNonEmptyMap>(ContainerS);
1078       State = assumeCollectionNonEmpty(C, State, ContainerS, *NonEmpty);
1079     }
1080 
1081     C.addTransition(State);
1082   }
1083   return;
1084 }
1085 
1086 static SymbolRef getMethodReceiverIfKnownImmutable(const CallEvent *Call) {
1087   const ObjCMethodCall *Message = dyn_cast_or_null<ObjCMethodCall>(Call);
1088   if (!Message)
1089     return nullptr;
1090 
1091   const ObjCMethodDecl *MD = Message->getDecl();
1092   if (!MD)
1093     return nullptr;
1094 
1095   const ObjCInterfaceDecl *StaticClass;
1096   if (isa<ObjCProtocolDecl>(MD->getDeclContext())) {
1097     // We can't find out where the method was declared without doing more work.
1098     // Instead, see if the receiver is statically typed as a known immutable
1099     // collection.
1100     StaticClass = Message->getOriginExpr()->getReceiverInterface();
1101   } else {
1102     StaticClass = MD->getClassInterface();
1103   }
1104 
1105   if (!StaticClass)
1106     return nullptr;
1107 
1108   switch (findKnownClass(StaticClass, /*IncludeSuper=*/false)) {
1109   case FC_None:
1110     return nullptr;
1111   case FC_NSArray:
1112   case FC_NSDictionary:
1113   case FC_NSEnumerator:
1114   case FC_NSNull:
1115   case FC_NSOrderedSet:
1116   case FC_NSSet:
1117   case FC_NSString:
1118     break;
1119   }
1120 
1121   return Message->getReceiverSVal().getAsSymbol();
1122 }
1123 
1124 ProgramStateRef
1125 ObjCLoopChecker::checkPointerEscape(ProgramStateRef State,
1126                                     const InvalidatedSymbols &Escaped,
1127                                     const CallEvent *Call,
1128                                     PointerEscapeKind Kind) const {
1129   SymbolRef ImmutableReceiver = getMethodReceiverIfKnownImmutable(Call);
1130 
1131   // Remove the invalidated symbols form the collection count map.
1132   for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
1133        E = Escaped.end();
1134        I != E; ++I) {
1135     SymbolRef Sym = *I;
1136 
1137     // Don't invalidate this symbol's count if we know the method being called
1138     // is declared on an immutable class. This isn't completely correct if the
1139     // receiver is also passed as an argument, but in most uses of NSArray,
1140     // NSDictionary, etc. this isn't likely to happen in a dangerous way.
1141     if (Sym == ImmutableReceiver)
1142       continue;
1143 
1144     // The symbol escaped. Pessimistically, assume that the count could have
1145     // changed.
1146     State = State->remove<ContainerCountMap>(Sym);
1147     State = State->remove<ContainerNonEmptyMap>(Sym);
1148   }
1149   return State;
1150 }
1151 
1152 void ObjCLoopChecker::checkDeadSymbols(SymbolReaper &SymReaper,
1153                                        CheckerContext &C) const {
1154   ProgramStateRef State = C.getState();
1155 
1156   // Remove the dead symbols from the collection count map.
1157   ContainerCountMapTy Tracked = State->get<ContainerCountMap>();
1158   for (ContainerCountMapTy::iterator I = Tracked.begin(),
1159                                      E = Tracked.end(); I != E; ++I) {
1160     SymbolRef Sym = I->first;
1161     if (SymReaper.isDead(Sym)) {
1162       State = State->remove<ContainerCountMap>(Sym);
1163       State = State->remove<ContainerNonEmptyMap>(Sym);
1164     }
1165   }
1166 
1167   C.addTransition(State);
1168 }
1169 
1170 namespace {
1171 /// \class ObjCNonNilReturnValueChecker
1172 /// \brief The checker restricts the return values of APIs known to
1173 /// never (or almost never) return 'nil'.
1174 class ObjCNonNilReturnValueChecker
1175   : public Checker<check::PostObjCMessage,
1176                    check::PostStmt<ObjCArrayLiteral>,
1177                    check::PostStmt<ObjCDictionaryLiteral>,
1178                    check::PostStmt<ObjCBoxedExpr> > {
1179     mutable bool Initialized;
1180     mutable Selector ObjectAtIndex;
1181     mutable Selector ObjectAtIndexedSubscript;
1182     mutable Selector NullSelector;
1183 
1184 public:
1185   ObjCNonNilReturnValueChecker() : Initialized(false) {}
1186 
1187   ProgramStateRef assumeExprIsNonNull(const Expr *NonNullExpr,
1188                                       ProgramStateRef State,
1189                                       CheckerContext &C) const;
1190   void assumeExprIsNonNull(const Expr *E, CheckerContext &C) const {
1191     C.addTransition(assumeExprIsNonNull(E, C.getState(), C));
1192   }
1193 
1194   void checkPostStmt(const ObjCArrayLiteral *E, CheckerContext &C) const {
1195     assumeExprIsNonNull(E, C);
1196   }
1197   void checkPostStmt(const ObjCDictionaryLiteral *E, CheckerContext &C) const {
1198     assumeExprIsNonNull(E, C);
1199   }
1200   void checkPostStmt(const ObjCBoxedExpr *E, CheckerContext &C) const {
1201     assumeExprIsNonNull(E, C);
1202   }
1203 
1204   void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
1205 };
1206 }
1207 
1208 ProgramStateRef
1209 ObjCNonNilReturnValueChecker::assumeExprIsNonNull(const Expr *NonNullExpr,
1210                                                   ProgramStateRef State,
1211                                                   CheckerContext &C) const {
1212   SVal Val = State->getSVal(NonNullExpr, C.getLocationContext());
1213   if (Optional<DefinedOrUnknownSVal> DV = Val.getAs<DefinedOrUnknownSVal>())
1214     return State->assume(*DV, true);
1215   return State;
1216 }
1217 
1218 void ObjCNonNilReturnValueChecker::checkPostObjCMessage(const ObjCMethodCall &M,
1219                                                         CheckerContext &C)
1220                                                         const {
1221   ProgramStateRef State = C.getState();
1222 
1223   if (!Initialized) {
1224     ASTContext &Ctx = C.getASTContext();
1225     ObjectAtIndex = GetUnarySelector("objectAtIndex", Ctx);
1226     ObjectAtIndexedSubscript = GetUnarySelector("objectAtIndexedSubscript", Ctx);
1227     NullSelector = GetNullarySelector("null", Ctx);
1228   }
1229 
1230   // Check the receiver type.
1231   if (const ObjCInterfaceDecl *Interface = M.getReceiverInterface()) {
1232 
1233     // Assume that object returned from '[self init]' or '[super init]' is not
1234     // 'nil' if we are processing an inlined function/method.
1235     //
1236     // A defensive callee will (and should) check if the object returned by
1237     // '[super init]' is 'nil' before doing it's own initialization. However,
1238     // since 'nil' is rarely returned in practice, we should not warn when the
1239     // caller to the defensive constructor uses the object in contexts where
1240     // 'nil' is not accepted.
1241     if (!C.inTopFrame() && M.getDecl() &&
1242         M.getDecl()->getMethodFamily() == OMF_init &&
1243         M.isReceiverSelfOrSuper()) {
1244       State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1245     }
1246 
1247     FoundationClass Cl = findKnownClass(Interface);
1248 
1249     // Objects returned from
1250     // [NSArray|NSOrderedSet]::[ObjectAtIndex|ObjectAtIndexedSubscript]
1251     // are never 'nil'.
1252     if (Cl == FC_NSArray || Cl == FC_NSOrderedSet) {
1253       Selector Sel = M.getSelector();
1254       if (Sel == ObjectAtIndex || Sel == ObjectAtIndexedSubscript) {
1255         // Go ahead and assume the value is non-nil.
1256         State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1257       }
1258     }
1259 
1260     // Objects returned from [NSNull null] are not nil.
1261     if (Cl == FC_NSNull) {
1262       if (M.getSelector() == NullSelector) {
1263         // Go ahead and assume the value is non-nil.
1264         State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1265       }
1266     }
1267   }
1268   C.addTransition(State);
1269 }
1270 
1271 //===----------------------------------------------------------------------===//
1272 // Check registration.
1273 //===----------------------------------------------------------------------===//
1274 
1275 void ento::registerNilArgChecker(CheckerManager &mgr) {
1276   mgr.registerChecker<NilArgChecker>();
1277 }
1278 
1279 void ento::registerCFNumberCreateChecker(CheckerManager &mgr) {
1280   mgr.registerChecker<CFNumberCreateChecker>();
1281 }
1282 
1283 void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
1284   mgr.registerChecker<CFRetainReleaseChecker>();
1285 }
1286 
1287 void ento::registerClassReleaseChecker(CheckerManager &mgr) {
1288   mgr.registerChecker<ClassReleaseChecker>();
1289 }
1290 
1291 void ento::registerVariadicMethodTypeChecker(CheckerManager &mgr) {
1292   mgr.registerChecker<VariadicMethodTypeChecker>();
1293 }
1294 
1295 void ento::registerObjCLoopChecker(CheckerManager &mgr) {
1296   mgr.registerChecker<ObjCLoopChecker>();
1297 }
1298 
1299 void
1300 ento::registerObjCNonNilReturnValueChecker(CheckerManager &mgr) {
1301   mgr.registerChecker<ObjCNonNilReturnValueChecker>();
1302 }
1303