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