]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
Update clang to trunk r256633.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / StaticAnalyzer / Checkers / BasicObjCFoundationChecks.cpp
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.generateErrorNode()) {
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.generateErrorNode()) {
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   auto R = llvm::make_unique<BugReport>(*BT, Msg, N);
211   R->addRange(Range);
212   bugreporter::trackNullOrUndefValue(N, E, *R);
213   C.emitReport(std::move(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 = 1;
311     } else if (S == RemoveObjectForKeySel) {
312       Arg = 0;
313     }
314   }
315
316   // If argument is '0', report a warning.
317   if ((Arg != InvalidArgIndex))
318     warnIfNilArg(C, msg, Arg, Class, CanBeSubscript);
319 }
320
321 void NilArgChecker::checkPostStmt(const ObjCArrayLiteral *AL,
322                                   CheckerContext &C) const {
323   unsigned NumOfElements = AL->getNumElements();
324   for (unsigned i = 0; i < NumOfElements; ++i) {
325     warnIfNilExpr(AL->getElement(i), "Array element cannot be nil", C);
326   }
327 }
328
329 void NilArgChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
330                                   CheckerContext &C) const {
331   unsigned NumOfElements = DL->getNumElements();
332   for (unsigned i = 0; i < NumOfElements; ++i) {
333     ObjCDictionaryElement Element = DL->getKeyValueElement(i);
334     warnIfNilExpr(Element.Key, "Dictionary key cannot be nil", C);
335     warnIfNilExpr(Element.Value, "Dictionary value cannot be nil", C);
336   }
337 }
338
339 //===----------------------------------------------------------------------===//
340 // Error reporting.
341 //===----------------------------------------------------------------------===//
342
343 namespace {
344 class CFNumberCreateChecker : public Checker< check::PreStmt<CallExpr> > {
345   mutable std::unique_ptr<APIMisuse> BT;
346   mutable IdentifierInfo* II;
347 public:
348   CFNumberCreateChecker() : II(nullptr) {}
349
350   void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
351
352 private:
353   void EmitError(const TypedRegion* R, const Expr *Ex,
354                 uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind);
355 };
356 } // end anonymous namespace
357
358 enum CFNumberType {
359   kCFNumberSInt8Type = 1,
360   kCFNumberSInt16Type = 2,
361   kCFNumberSInt32Type = 3,
362   kCFNumberSInt64Type = 4,
363   kCFNumberFloat32Type = 5,
364   kCFNumberFloat64Type = 6,
365   kCFNumberCharType = 7,
366   kCFNumberShortType = 8,
367   kCFNumberIntType = 9,
368   kCFNumberLongType = 10,
369   kCFNumberLongLongType = 11,
370   kCFNumberFloatType = 12,
371   kCFNumberDoubleType = 13,
372   kCFNumberCFIndexType = 14,
373   kCFNumberNSIntegerType = 15,
374   kCFNumberCGFloatType = 16
375 };
376
377 static Optional<uint64_t> GetCFNumberSize(ASTContext &Ctx, uint64_t i) {
378   static const unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 };
379
380   if (i < kCFNumberCharType)
381     return FixedSize[i-1];
382
383   QualType T;
384
385   switch (i) {
386     case kCFNumberCharType:     T = Ctx.CharTy;     break;
387     case kCFNumberShortType:    T = Ctx.ShortTy;    break;
388     case kCFNumberIntType:      T = Ctx.IntTy;      break;
389     case kCFNumberLongType:     T = Ctx.LongTy;     break;
390     case kCFNumberLongLongType: T = Ctx.LongLongTy; break;
391     case kCFNumberFloatType:    T = Ctx.FloatTy;    break;
392     case kCFNumberDoubleType:   T = Ctx.DoubleTy;   break;
393     case kCFNumberCFIndexType:
394     case kCFNumberNSIntegerType:
395     case kCFNumberCGFloatType:
396       // FIXME: We need a way to map from names to Type*.
397     default:
398       return None;
399   }
400
401   return Ctx.getTypeSize(T);
402 }
403
404 #if 0
405 static const char* GetCFNumberTypeStr(uint64_t i) {
406   static const char* Names[] = {
407     "kCFNumberSInt8Type",
408     "kCFNumberSInt16Type",
409     "kCFNumberSInt32Type",
410     "kCFNumberSInt64Type",
411     "kCFNumberFloat32Type",
412     "kCFNumberFloat64Type",
413     "kCFNumberCharType",
414     "kCFNumberShortType",
415     "kCFNumberIntType",
416     "kCFNumberLongType",
417     "kCFNumberLongLongType",
418     "kCFNumberFloatType",
419     "kCFNumberDoubleType",
420     "kCFNumberCFIndexType",
421     "kCFNumberNSIntegerType",
422     "kCFNumberCGFloatType"
423   };
424
425   return i <= kCFNumberCGFloatType ? Names[i-1] : "Invalid CFNumberType";
426 }
427 #endif
428
429 void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
430                                          CheckerContext &C) const {
431   ProgramStateRef state = C.getState();
432   const FunctionDecl *FD = C.getCalleeDecl(CE);
433   if (!FD)
434     return;
435
436   ASTContext &Ctx = C.getASTContext();
437   if (!II)
438     II = &Ctx.Idents.get("CFNumberCreate");
439
440   if (FD->getIdentifier() != II || CE->getNumArgs() != 3)
441     return;
442
443   // Get the value of the "theType" argument.
444   const LocationContext *LCtx = C.getLocationContext();
445   SVal TheTypeVal = state->getSVal(CE->getArg(1), LCtx);
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> OptTargetSize = GetCFNumberSize(Ctx, NumberKind);
455
456   // FIXME: In some cases we can emit an error.
457   if (!OptTargetSize)
458     return;
459
460   uint64_t TargetSize = *OptTargetSize;
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 = state->getSVal(CE->getArg(2), LCtx);
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 SourceSize = Ctx.getTypeSize(T);
486
487   // CHECK: is SourceSize == TargetSize
488   if (SourceSize == TargetSize)
489     return;
490
491   // Generate an error.  Only generate a sink error node
492   // if 'SourceSize < TargetSize'; otherwise generate a non-fatal error node.
493   //
494   // FIXME: We can actually create an abstract "CFNumber" object that has
495   //  the bits initialized to the provided values.
496   //
497   ExplodedNode *N = SourceSize < TargetSize ? C.generateErrorNode()
498                                             : C.generateNonFatalErrorNode();
499   if (N) {
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     auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
520     report->addRange(CE->getArg(2)->getSourceRange());
521     C.emitReport(std::move(report));
522   }
523 }
524
525 //===----------------------------------------------------------------------===//
526 // CFRetain/CFRelease/CFMakeCollectable/CFAutorelease 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, *Autorelease;
533 public:
534   CFRetainReleaseChecker()
535       : Retain(nullptr), Release(nullptr), MakeCollectable(nullptr),
536         Autorelease(nullptr) {}
537   void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
538 };
539 } // end anonymous namespace
540
541
542 void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
543                                           CheckerContext &C) const {
544   // If the CallExpr doesn't have exactly 1 argument just give up checking.
545   if (CE->getNumArgs() != 1)
546     return;
547
548   ProgramStateRef state = C.getState();
549   const FunctionDecl *FD = C.getCalleeDecl(CE);
550   if (!FD)
551     return;
552
553   if (!BT) {
554     ASTContext &Ctx = C.getASTContext();
555     Retain = &Ctx.Idents.get("CFRetain");
556     Release = &Ctx.Idents.get("CFRelease");
557     MakeCollectable = &Ctx.Idents.get("CFMakeCollectable");
558     Autorelease = &Ctx.Idents.get("CFAutorelease");
559     BT.reset(new APIMisuse(
560         this, "null passed to CF memory management function"));
561   }
562
563   // Check if we called CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
564   const IdentifierInfo *FuncII = FD->getIdentifier();
565   if (!(FuncII == Retain || FuncII == Release || FuncII == MakeCollectable ||
566         FuncII == Autorelease))
567     return;
568
569   // FIXME: The rest of this just checks that the argument is non-null.
570   // It should probably be refactored and combined with NonNullParamChecker.
571
572   // Get the argument's value.
573   const Expr *Arg = CE->getArg(0);
574   SVal ArgVal = state->getSVal(Arg, C.getLocationContext());
575   Optional<DefinedSVal> DefArgVal = ArgVal.getAs<DefinedSVal>();
576   if (!DefArgVal)
577     return;
578
579   // Get a NULL value.
580   SValBuilder &svalBuilder = C.getSValBuilder();
581   DefinedSVal zero =
582       svalBuilder.makeZeroVal(Arg->getType()).castAs<DefinedSVal>();
583
584   // Make an expression asserting that they're equal.
585   DefinedOrUnknownSVal ArgIsNull = svalBuilder.evalEQ(state, zero, *DefArgVal);
586
587   // Are they equal?
588   ProgramStateRef stateTrue, stateFalse;
589   std::tie(stateTrue, stateFalse) = state->assume(ArgIsNull);
590
591   if (stateTrue && !stateFalse) {
592     ExplodedNode *N = C.generateErrorNode(stateTrue);
593     if (!N)
594       return;
595
596     const char *description;
597     if (FuncII == Retain)
598       description = "Null pointer argument in call to CFRetain";
599     else if (FuncII == Release)
600       description = "Null pointer argument in call to CFRelease";
601     else if (FuncII == MakeCollectable)
602       description = "Null pointer argument in call to CFMakeCollectable";
603     else if (FuncII == Autorelease)
604       description = "Null pointer argument in call to CFAutorelease";
605     else
606       llvm_unreachable("impossible case");
607
608     auto report = llvm::make_unique<BugReport>(*BT, description, N);
609     report->addRange(Arg->getSourceRange());
610     bugreporter::trackNullOrUndefValue(N, Arg, *report);
611     C.emitReport(std::move(report));
612     return;
613   }
614
615   // From here on, we know the argument is non-null.
616   C.addTransition(stateFalse);
617 }
618
619 //===----------------------------------------------------------------------===//
620 // Check for sending 'retain', 'release', or 'autorelease' directly to a Class.
621 //===----------------------------------------------------------------------===//
622
623 namespace {
624 class ClassReleaseChecker : public Checker<check::PreObjCMessage> {
625   mutable Selector releaseS;
626   mutable Selector retainS;
627   mutable Selector autoreleaseS;
628   mutable Selector drainS;
629   mutable std::unique_ptr<BugType> BT;
630
631 public:
632   void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
633 };
634 }
635
636 void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
637                                               CheckerContext &C) const {
638
639   if (!BT) {
640     BT.reset(new APIMisuse(
641         this, "message incorrectly sent to class instead of class instance"));
642
643     ASTContext &Ctx = C.getASTContext();
644     releaseS = GetNullarySelector("release", Ctx);
645     retainS = GetNullarySelector("retain", Ctx);
646     autoreleaseS = GetNullarySelector("autorelease", Ctx);
647     drainS = GetNullarySelector("drain", Ctx);
648   }
649
650   if (msg.isInstanceMessage())
651     return;
652   const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
653   assert(Class);
654
655   Selector S = msg.getSelector();
656   if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
657     return;
658
659   if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
660     SmallString<200> buf;
661     llvm::raw_svector_ostream os(buf);
662
663     os << "The '";
664     S.print(os);
665     os << "' message should be sent to instances "
666           "of class '" << Class->getName()
667        << "' and not the class directly";
668
669     auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
670     report->addRange(msg.getSourceRange());
671     C.emitReport(std::move(report));
672   }
673 }
674
675 //===----------------------------------------------------------------------===//
676 // Check for passing non-Objective-C types to variadic methods that expect
677 // only Objective-C types.
678 //===----------------------------------------------------------------------===//
679
680 namespace {
681 class VariadicMethodTypeChecker : public Checker<check::PreObjCMessage> {
682   mutable Selector arrayWithObjectsS;
683   mutable Selector dictionaryWithObjectsAndKeysS;
684   mutable Selector setWithObjectsS;
685   mutable Selector orderedSetWithObjectsS;
686   mutable Selector initWithObjectsS;
687   mutable Selector initWithObjectsAndKeysS;
688   mutable std::unique_ptr<BugType> BT;
689
690   bool isVariadicMessage(const ObjCMethodCall &msg) const;
691
692 public:
693   void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
694 };
695 }
696
697 /// isVariadicMessage - Returns whether the given message is a variadic message,
698 /// where all arguments must be Objective-C types.
699 bool
700 VariadicMethodTypeChecker::isVariadicMessage(const ObjCMethodCall &msg) const {
701   const ObjCMethodDecl *MD = msg.getDecl();
702
703   if (!MD || !MD->isVariadic() || isa<ObjCProtocolDecl>(MD->getDeclContext()))
704     return false;
705
706   Selector S = msg.getSelector();
707
708   if (msg.isInstanceMessage()) {
709     // FIXME: Ideally we'd look at the receiver interface here, but that's not
710     // useful for init, because alloc returns 'id'. In theory, this could lead
711     // to false positives, for example if there existed a class that had an
712     // initWithObjects: implementation that does accept non-Objective-C pointer
713     // types, but the chance of that happening is pretty small compared to the
714     // gains that this analysis gives.
715     const ObjCInterfaceDecl *Class = MD->getClassInterface();
716
717     switch (findKnownClass(Class)) {
718     case FC_NSArray:
719     case FC_NSOrderedSet:
720     case FC_NSSet:
721       return S == initWithObjectsS;
722     case FC_NSDictionary:
723       return S == initWithObjectsAndKeysS;
724     default:
725       return false;
726     }
727   } else {
728     const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
729
730     switch (findKnownClass(Class)) {
731       case FC_NSArray:
732         return S == arrayWithObjectsS;
733       case FC_NSOrderedSet:
734         return S == orderedSetWithObjectsS;
735       case FC_NSSet:
736         return S == setWithObjectsS;
737       case FC_NSDictionary:
738         return S == dictionaryWithObjectsAndKeysS;
739       default:
740         return false;
741     }
742   }
743 }
744
745 void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
746                                                     CheckerContext &C) const {
747   if (!BT) {
748     BT.reset(new APIMisuse(this,
749                            "Arguments passed to variadic method aren't all "
750                            "Objective-C pointer types"));
751
752     ASTContext &Ctx = C.getASTContext();
753     arrayWithObjectsS = GetUnarySelector("arrayWithObjects", Ctx);
754     dictionaryWithObjectsAndKeysS =
755       GetUnarySelector("dictionaryWithObjectsAndKeys", Ctx);
756     setWithObjectsS = GetUnarySelector("setWithObjects", Ctx);
757     orderedSetWithObjectsS = GetUnarySelector("orderedSetWithObjects", Ctx);
758
759     initWithObjectsS = GetUnarySelector("initWithObjects", Ctx);
760     initWithObjectsAndKeysS = GetUnarySelector("initWithObjectsAndKeys", Ctx);
761   }
762
763   if (!isVariadicMessage(msg))
764       return;
765
766   // We are not interested in the selector arguments since they have
767   // well-defined types, so the compiler will issue a warning for them.
768   unsigned variadicArgsBegin = msg.getSelector().getNumArgs();
769
770   // We're not interested in the last argument since it has to be nil or the
771   // compiler would have issued a warning for it elsewhere.
772   unsigned variadicArgsEnd = msg.getNumArgs() - 1;
773
774   if (variadicArgsEnd <= variadicArgsBegin)
775     return;
776
777   // Verify that all arguments have Objective-C types.
778   Optional<ExplodedNode*> errorNode;
779
780   for (unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) {
781     QualType ArgTy = msg.getArgExpr(I)->getType();
782     if (ArgTy->isObjCObjectPointerType())
783       continue;
784
785     // Block pointers are treaded as Objective-C pointers.
786     if (ArgTy->isBlockPointerType())
787       continue;
788
789     // Ignore pointer constants.
790     if (msg.getArgSVal(I).getAs<loc::ConcreteInt>())
791       continue;
792
793     // Ignore pointer types annotated with 'NSObject' attribute.
794     if (C.getASTContext().isObjCNSObjectType(ArgTy))
795       continue;
796
797     // Ignore CF references, which can be toll-free bridged.
798     if (coreFoundation::isCFObjectRef(ArgTy))
799       continue;
800
801     // Generate only one error node to use for all bug reports.
802     if (!errorNode.hasValue())
803       errorNode = C.generateNonFatalErrorNode();
804
805     if (!errorNode.getValue())
806       continue;
807
808     SmallString<128> sbuf;
809     llvm::raw_svector_ostream os(sbuf);
810
811     StringRef TypeName = GetReceiverInterfaceName(msg);
812     if (!TypeName.empty())
813       os << "Argument to '" << TypeName << "' method '";
814     else
815       os << "Argument to method '";
816
817     msg.getSelector().print(os);
818     os << "' should be an Objective-C pointer type, not '";
819     ArgTy.print(os, C.getLangOpts());
820     os << "'";
821
822     auto R = llvm::make_unique<BugReport>(*BT, os.str(), errorNode.getValue());
823     R->addRange(msg.getArgSourceRange(I));
824     C.emitReport(std::move(R));
825   }
826 }
827
828 //===----------------------------------------------------------------------===//
829 // Improves the modeling of loops over Cocoa collections.
830 //===----------------------------------------------------------------------===//
831
832 // The map from container symbol to the container count symbol.
833 // We currently will remember the last countainer count symbol encountered.
834 REGISTER_MAP_WITH_PROGRAMSTATE(ContainerCountMap, SymbolRef, SymbolRef)
835 REGISTER_MAP_WITH_PROGRAMSTATE(ContainerNonEmptyMap, SymbolRef, bool)
836
837 namespace {
838 class ObjCLoopChecker
839   : public Checker<check::PostStmt<ObjCForCollectionStmt>,
840                    check::PostObjCMessage,
841                    check::DeadSymbols,
842                    check::PointerEscape > {
843   mutable IdentifierInfo *CountSelectorII;
844
845   bool isCollectionCountMethod(const ObjCMethodCall &M,
846                                CheckerContext &C) const;
847
848 public:
849   ObjCLoopChecker() : CountSelectorII(nullptr) {}
850   void checkPostStmt(const ObjCForCollectionStmt *FCS, CheckerContext &C) const;
851   void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
852   void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
853   ProgramStateRef checkPointerEscape(ProgramStateRef State,
854                                      const InvalidatedSymbols &Escaped,
855                                      const CallEvent *Call,
856                                      PointerEscapeKind Kind) const;
857 };
858 }
859
860 static bool isKnownNonNilCollectionType(QualType T) {
861   const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
862   if (!PT)
863     return false;
864
865   const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
866   if (!ID)
867     return false;
868
869   switch (findKnownClass(ID)) {
870   case FC_NSArray:
871   case FC_NSDictionary:
872   case FC_NSEnumerator:
873   case FC_NSOrderedSet:
874   case FC_NSSet:
875     return true;
876   default:
877     return false;
878   }
879 }
880
881 /// Assumes that the collection is non-nil.
882 ///
883 /// If the collection is known to be nil, returns NULL to indicate an infeasible
884 /// path.
885 static ProgramStateRef checkCollectionNonNil(CheckerContext &C,
886                                              ProgramStateRef State,
887                                              const ObjCForCollectionStmt *FCS) {
888   if (!State)
889     return nullptr;
890
891   SVal CollectionVal = C.getSVal(FCS->getCollection());
892   Optional<DefinedSVal> KnownCollection = CollectionVal.getAs<DefinedSVal>();
893   if (!KnownCollection)
894     return State;
895
896   ProgramStateRef StNonNil, StNil;
897   std::tie(StNonNil, StNil) = State->assume(*KnownCollection);
898   if (StNil && !StNonNil) {
899     // The collection is nil. This path is infeasible.
900     return nullptr;
901   }
902
903   return StNonNil;
904 }
905
906 /// Assumes that the collection elements are non-nil.
907 ///
908 /// This only applies if the collection is one of those known not to contain
909 /// nil values.
910 static ProgramStateRef checkElementNonNil(CheckerContext &C,
911                                           ProgramStateRef State,
912                                           const ObjCForCollectionStmt *FCS) {
913   if (!State)
914     return nullptr;
915
916   // See if the collection is one where we /know/ the elements are non-nil.
917   if (!isKnownNonNilCollectionType(FCS->getCollection()->getType()))
918     return State;
919
920   const LocationContext *LCtx = C.getLocationContext();
921   const Stmt *Element = FCS->getElement();
922
923   // FIXME: Copied from ExprEngineObjC.
924   Optional<Loc> ElementLoc;
925   if (const DeclStmt *DS = dyn_cast<DeclStmt>(Element)) {
926     const VarDecl *ElemDecl = cast<VarDecl>(DS->getSingleDecl());
927     assert(ElemDecl->getInit() == nullptr);
928     ElementLoc = State->getLValue(ElemDecl, LCtx);
929   } else {
930     ElementLoc = State->getSVal(Element, LCtx).getAs<Loc>();
931   }
932
933   if (!ElementLoc)
934     return State;
935
936   // Go ahead and assume the value is non-nil.
937   SVal Val = State->getSVal(*ElementLoc);
938   return State->assume(Val.castAs<DefinedOrUnknownSVal>(), true);
939 }
940
941 /// Returns NULL state if the collection is known to contain elements
942 /// (or is known not to contain elements if the Assumption parameter is false.)
943 static ProgramStateRef
944 assumeCollectionNonEmpty(CheckerContext &C, ProgramStateRef State,
945                          SymbolRef CollectionS, bool Assumption) {
946   if (!State || !CollectionS)
947     return State;
948
949   const SymbolRef *CountS = State->get<ContainerCountMap>(CollectionS);
950   if (!CountS) {
951     const bool *KnownNonEmpty = State->get<ContainerNonEmptyMap>(CollectionS);
952     if (!KnownNonEmpty)
953       return State->set<ContainerNonEmptyMap>(CollectionS, Assumption);
954     return (Assumption == *KnownNonEmpty) ? State : nullptr;
955   }
956
957   SValBuilder &SvalBuilder = C.getSValBuilder();
958   SVal CountGreaterThanZeroVal =
959     SvalBuilder.evalBinOp(State, BO_GT,
960                           nonloc::SymbolVal(*CountS),
961                           SvalBuilder.makeIntVal(0, (*CountS)->getType()),
962                           SvalBuilder.getConditionType());
963   Optional<DefinedSVal> CountGreaterThanZero =
964     CountGreaterThanZeroVal.getAs<DefinedSVal>();
965   if (!CountGreaterThanZero) {
966     // The SValBuilder cannot construct a valid SVal for this condition.
967     // This means we cannot properly reason about it.
968     return State;
969   }
970
971   return State->assume(*CountGreaterThanZero, Assumption);
972 }
973
974 static ProgramStateRef
975 assumeCollectionNonEmpty(CheckerContext &C, ProgramStateRef State,
976                          const ObjCForCollectionStmt *FCS,
977                          bool Assumption) {
978   if (!State)
979     return nullptr;
980
981   SymbolRef CollectionS =
982     State->getSVal(FCS->getCollection(), C.getLocationContext()).getAsSymbol();
983   return assumeCollectionNonEmpty(C, State, CollectionS, Assumption);
984 }
985
986
987 /// If the fist block edge is a back edge, we are reentering the loop.
988 static bool alreadyExecutedAtLeastOneLoopIteration(const ExplodedNode *N,
989                                              const ObjCForCollectionStmt *FCS) {
990   if (!N)
991     return false;
992
993   ProgramPoint P = N->getLocation();
994   if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
995     return BE->getSrc()->getLoopTarget() == FCS;
996   }
997
998   // Keep looking for a block edge.
999   for (ExplodedNode::const_pred_iterator I = N->pred_begin(),
1000                                          E = N->pred_end(); I != E; ++I) {
1001     if (alreadyExecutedAtLeastOneLoopIteration(*I, FCS))
1002       return true;
1003   }
1004
1005   return false;
1006 }
1007
1008 void ObjCLoopChecker::checkPostStmt(const ObjCForCollectionStmt *FCS,
1009                                     CheckerContext &C) const {
1010   ProgramStateRef State = C.getState();
1011
1012   // Check if this is the branch for the end of the loop.
1013   SVal CollectionSentinel = C.getSVal(FCS);
1014   if (CollectionSentinel.isZeroConstant()) {
1015     if (!alreadyExecutedAtLeastOneLoopIteration(C.getPredecessor(), FCS))
1016       State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/false);
1017
1018   // Otherwise, this is a branch that goes through the loop body.
1019   } else {
1020     State = checkCollectionNonNil(C, State, FCS);
1021     State = checkElementNonNil(C, State, FCS);
1022     State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/true);
1023   }
1024
1025   if (!State)
1026     C.generateSink(C.getState(), C.getPredecessor());
1027   else if (State != C.getState())
1028     C.addTransition(State);
1029 }
1030
1031 bool ObjCLoopChecker::isCollectionCountMethod(const ObjCMethodCall &M,
1032                                               CheckerContext &C) const {
1033   Selector S = M.getSelector();
1034   // Initialize the identifiers on first use.
1035   if (!CountSelectorII)
1036     CountSelectorII = &C.getASTContext().Idents.get("count");
1037
1038   // If the method returns collection count, record the value.
1039   return S.isUnarySelector() &&
1040          (S.getIdentifierInfoForSlot(0) == CountSelectorII);
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 }