]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
Merge from head
[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.generateSink()) {
144       generateBugReport(N, Msg, E->getSourceRange(), E, C);
145     }
146     
147   }
148 }
149
150 void NilArgChecker::warnIfNilArg(CheckerContext &C,
151                                  const ObjCMethodCall &msg,
152                                  unsigned int Arg,
153                                  FoundationClass Class,
154                                  bool CanBeSubscript) const {
155   // Check if the argument is nil.
156   ProgramStateRef State = C.getState();
157   if (!State->isNull(msg.getArgSVal(Arg)).isConstrainedTrue())
158       return;
159       
160   if (ExplodedNode *N = C.generateSink()) {
161     SmallString<128> sbuf;
162     llvm::raw_svector_ostream os(sbuf);
163
164     if (CanBeSubscript && msg.getMessageKind() == OCM_Subscript) {
165
166       if (Class == FC_NSArray) {
167         os << "Array element cannot be nil";
168       } else if (Class == FC_NSDictionary) {
169         if (Arg == 0) {
170           os << "Value stored into '";
171           os << GetReceiverInterfaceName(msg) << "' cannot be nil";
172         } else {
173           assert(Arg == 1);
174           os << "'"<< GetReceiverInterfaceName(msg) << "' key cannot be nil";
175         }
176       } else
177         llvm_unreachable("Missing foundation class for the subscript expr");
178
179     } else {
180       if (Class == FC_NSDictionary) {
181         if (Arg == 0)
182           os << "Value argument ";
183         else {
184           assert(Arg == 1);
185           os << "Key argument ";
186         }
187         os << "to '";
188         msg.getSelector().print(os);
189         os << "' cannot be nil";
190       } else {
191         os << "Argument to '" << GetReceiverInterfaceName(msg) << "' method '";
192         msg.getSelector().print(os);
193         os << "' cannot be nil";
194       }
195     }
196     
197     generateBugReport(N, os.str(), msg.getArgSourceRange(Arg),
198                       msg.getArgExpr(Arg), C);
199   }
200 }
201
202 void NilArgChecker::generateBugReport(ExplodedNode *N,
203                                       StringRef Msg,
204                                       SourceRange Range,
205                                       const Expr *E,
206                                       CheckerContext &C) const {
207   if (!BT)
208     BT.reset(new APIMisuse(this, "nil argument"));
209
210   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 = 0;
311       warnIfNilArg(C, msg, /* Arg */1, Class, CanBeSubscript);
312     } else if (S == RemoveObjectForKeySel) {
313       Arg = 0;
314     }
315   }
316
317   // If argument is '0', report a warning.
318   if ((Arg != InvalidArgIndex))
319     warnIfNilArg(C, msg, Arg, Class, CanBeSubscript);
320 }
321
322 void NilArgChecker::checkPostStmt(const ObjCArrayLiteral *AL,
323                                   CheckerContext &C) const {
324   unsigned NumOfElements = AL->getNumElements();
325   for (unsigned i = 0; i < NumOfElements; ++i) {
326     warnIfNilExpr(AL->getElement(i), "Array element cannot be nil", C);
327   }
328 }
329
330 void NilArgChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
331                                   CheckerContext &C) const {
332   unsigned NumOfElements = DL->getNumElements();
333   for (unsigned i = 0; i < NumOfElements; ++i) {
334     ObjCDictionaryElement Element = DL->getKeyValueElement(i);
335     warnIfNilExpr(Element.Key, "Dictionary key cannot be nil", C);
336     warnIfNilExpr(Element.Value, "Dictionary value cannot be nil", C);
337   }
338 }
339
340 //===----------------------------------------------------------------------===//
341 // Error reporting.
342 //===----------------------------------------------------------------------===//
343
344 namespace {
345 class CFNumberCreateChecker : public Checker< check::PreStmt<CallExpr> > {
346   mutable std::unique_ptr<APIMisuse> BT;
347   mutable IdentifierInfo* II;
348 public:
349   CFNumberCreateChecker() : II(nullptr) {}
350
351   void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
352
353 private:
354   void EmitError(const TypedRegion* R, const Expr *Ex,
355                 uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind);
356 };
357 } // end anonymous namespace
358
359 enum CFNumberType {
360   kCFNumberSInt8Type = 1,
361   kCFNumberSInt16Type = 2,
362   kCFNumberSInt32Type = 3,
363   kCFNumberSInt64Type = 4,
364   kCFNumberFloat32Type = 5,
365   kCFNumberFloat64Type = 6,
366   kCFNumberCharType = 7,
367   kCFNumberShortType = 8,
368   kCFNumberIntType = 9,
369   kCFNumberLongType = 10,
370   kCFNumberLongLongType = 11,
371   kCFNumberFloatType = 12,
372   kCFNumberDoubleType = 13,
373   kCFNumberCFIndexType = 14,
374   kCFNumberNSIntegerType = 15,
375   kCFNumberCGFloatType = 16
376 };
377
378 static Optional<uint64_t> GetCFNumberSize(ASTContext &Ctx, uint64_t i) {
379   static const unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 };
380
381   if (i < kCFNumberCharType)
382     return FixedSize[i-1];
383
384   QualType T;
385
386   switch (i) {
387     case kCFNumberCharType:     T = Ctx.CharTy;     break;
388     case kCFNumberShortType:    T = Ctx.ShortTy;    break;
389     case kCFNumberIntType:      T = Ctx.IntTy;      break;
390     case kCFNumberLongType:     T = Ctx.LongTy;     break;
391     case kCFNumberLongLongType: T = Ctx.LongLongTy; break;
392     case kCFNumberFloatType:    T = Ctx.FloatTy;    break;
393     case kCFNumberDoubleType:   T = Ctx.DoubleTy;   break;
394     case kCFNumberCFIndexType:
395     case kCFNumberNSIntegerType:
396     case kCFNumberCGFloatType:
397       // FIXME: We need a way to map from names to Type*.
398     default:
399       return None;
400   }
401
402   return Ctx.getTypeSize(T);
403 }
404
405 #if 0
406 static const char* GetCFNumberTypeStr(uint64_t i) {
407   static const char* Names[] = {
408     "kCFNumberSInt8Type",
409     "kCFNumberSInt16Type",
410     "kCFNumberSInt32Type",
411     "kCFNumberSInt64Type",
412     "kCFNumberFloat32Type",
413     "kCFNumberFloat64Type",
414     "kCFNumberCharType",
415     "kCFNumberShortType",
416     "kCFNumberIntType",
417     "kCFNumberLongType",
418     "kCFNumberLongLongType",
419     "kCFNumberFloatType",
420     "kCFNumberDoubleType",
421     "kCFNumberCFIndexType",
422     "kCFNumberNSIntegerType",
423     "kCFNumberCGFloatType"
424   };
425
426   return i <= kCFNumberCGFloatType ? Names[i-1] : "Invalid CFNumberType";
427 }
428 #endif
429
430 void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
431                                          CheckerContext &C) const {
432   ProgramStateRef state = C.getState();
433   const FunctionDecl *FD = C.getCalleeDecl(CE);
434   if (!FD)
435     return;
436   
437   ASTContext &Ctx = C.getASTContext();
438   if (!II)
439     II = &Ctx.Idents.get("CFNumberCreate");
440
441   if (FD->getIdentifier() != II || CE->getNumArgs() != 3)
442     return;
443
444   // Get the value of the "theType" argument.
445   const LocationContext *LCtx = C.getLocationContext();
446   SVal TheTypeVal = state->getSVal(CE->getArg(1), LCtx);
447
448   // FIXME: We really should allow ranges of valid theType values, and
449   //   bifurcate the state appropriately.
450   Optional<nonloc::ConcreteInt> V = TheTypeVal.getAs<nonloc::ConcreteInt>();
451   if (!V)
452     return;
453
454   uint64_t NumberKind = V->getValue().getLimitedValue();
455   Optional<uint64_t> OptTargetSize = GetCFNumberSize(Ctx, NumberKind);
456
457   // FIXME: In some cases we can emit an error.
458   if (!OptTargetSize)
459     return;
460
461   uint64_t TargetSize = *OptTargetSize;
462
463   // Look at the value of the integer being passed by reference.  Essentially
464   // we want to catch cases where the value passed in is not equal to the
465   // size of the type being created.
466   SVal TheValueExpr = state->getSVal(CE->getArg(2), LCtx);
467
468   // FIXME: Eventually we should handle arbitrary locations.  We can do this
469   //  by having an enhanced memory model that does low-level typing.
470   Optional<loc::MemRegionVal> LV = TheValueExpr.getAs<loc::MemRegionVal>();
471   if (!LV)
472     return;
473
474   const TypedValueRegion* R = dyn_cast<TypedValueRegion>(LV->stripCasts());
475   if (!R)
476     return;
477
478   QualType T = Ctx.getCanonicalType(R->getValueType());
479
480   // FIXME: If the pointee isn't an integer type, should we flag a warning?
481   //  People can do weird stuff with pointers.
482
483   if (!T->isIntegralOrEnumerationType())
484     return;
485
486   uint64_t SourceSize = Ctx.getTypeSize(T);
487
488   // CHECK: is SourceSize == TargetSize
489   if (SourceSize == TargetSize)
490     return;
491
492   // Generate an error.  Only generate a sink if 'SourceSize < TargetSize';
493   // otherwise generate a regular node.
494   //
495   // FIXME: We can actually create an abstract "CFNumber" object that has
496   //  the bits initialized to the provided values.
497   //
498   if (ExplodedNode *N = SourceSize < TargetSize ? C.generateSink() 
499                                                 : C.addTransition()) {
500     SmallString<128> sbuf;
501     llvm::raw_svector_ostream os(sbuf);
502     
503     os << (SourceSize == 8 ? "An " : "A ")
504        << SourceSize << " bit integer is used to initialize a CFNumber "
505                         "object that represents "
506        << (TargetSize == 8 ? "an " : "a ")
507        << TargetSize << " bit integer. ";
508     
509     if (SourceSize < TargetSize)
510       os << (TargetSize - SourceSize)
511       << " bits of the CFNumber value will be garbage." ;
512     else
513       os << (SourceSize - TargetSize)
514       << " bits of the input integer will be lost.";
515
516     if (!BT)
517       BT.reset(new APIMisuse(this, "Bad use of CFNumberCreate"));
518
519     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.generateSink(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.addTransition()) {
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.addTransition();
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     if (BE->getSrc()->getLoopTarget() == FCS)
996       return true;
997     return false;
998   }
999
1000   // Keep looking for a block edge.
1001   for (ExplodedNode::const_pred_iterator I = N->pred_begin(),
1002                                          E = N->pred_end(); I != E; ++I) {
1003     if (alreadyExecutedAtLeastOneLoopIteration(*I, FCS))
1004       return true;
1005   }
1006
1007   return false;
1008 }
1009
1010 void ObjCLoopChecker::checkPostStmt(const ObjCForCollectionStmt *FCS,
1011                                     CheckerContext &C) const {
1012   ProgramStateRef State = C.getState();
1013
1014   // Check if this is the branch for the end of the loop.
1015   SVal CollectionSentinel = C.getSVal(FCS);
1016   if (CollectionSentinel.isZeroConstant()) {
1017     if (!alreadyExecutedAtLeastOneLoopIteration(C.getPredecessor(), FCS))
1018       State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/false);
1019
1020   // Otherwise, this is a branch that goes through the loop body.
1021   } else {
1022     State = checkCollectionNonNil(C, State, FCS);
1023     State = checkElementNonNil(C, State, FCS);
1024     State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/true);
1025   }
1026   
1027   if (!State)
1028     C.generateSink();
1029   else if (State != C.getState())
1030     C.addTransition(State);
1031 }
1032
1033 bool ObjCLoopChecker::isCollectionCountMethod(const ObjCMethodCall &M,
1034                                               CheckerContext &C) const {
1035   Selector S = M.getSelector();
1036   // Initialize the identifiers on first use.
1037   if (!CountSelectorII)
1038     CountSelectorII = &C.getASTContext().Idents.get("count");
1039
1040   // If the method returns collection count, record the value.
1041   if (S.isUnarySelector() &&
1042       (S.getIdentifierInfoForSlot(0) == CountSelectorII))
1043     return true;
1044   
1045   return false;
1046 }
1047
1048 void ObjCLoopChecker::checkPostObjCMessage(const ObjCMethodCall &M,
1049                                            CheckerContext &C) const {
1050   if (!M.isInstanceMessage())
1051     return;
1052
1053   const ObjCInterfaceDecl *ClassID = M.getReceiverInterface();
1054   if (!ClassID)
1055     return;
1056
1057   FoundationClass Class = findKnownClass(ClassID);
1058   if (Class != FC_NSDictionary &&
1059       Class != FC_NSArray &&
1060       Class != FC_NSSet &&
1061       Class != FC_NSOrderedSet)
1062     return;
1063
1064   SymbolRef ContainerS = M.getReceiverSVal().getAsSymbol();
1065   if (!ContainerS)
1066     return;
1067
1068   // If we are processing a call to "count", get the symbolic value returned by
1069   // a call to "count" and add it to the map.
1070   if (!isCollectionCountMethod(M, C))
1071     return;
1072   
1073   const Expr *MsgExpr = M.getOriginExpr();
1074   SymbolRef CountS = C.getSVal(MsgExpr).getAsSymbol();
1075   if (CountS) {
1076     ProgramStateRef State = C.getState();
1077
1078     C.getSymbolManager().addSymbolDependency(ContainerS, CountS);
1079     State = State->set<ContainerCountMap>(ContainerS, CountS);
1080
1081     if (const bool *NonEmpty = State->get<ContainerNonEmptyMap>(ContainerS)) {
1082       State = State->remove<ContainerNonEmptyMap>(ContainerS);
1083       State = assumeCollectionNonEmpty(C, State, ContainerS, *NonEmpty);
1084     }
1085
1086     C.addTransition(State);
1087   }
1088   return;
1089 }
1090
1091 static SymbolRef getMethodReceiverIfKnownImmutable(const CallEvent *Call) {
1092   const ObjCMethodCall *Message = dyn_cast_or_null<ObjCMethodCall>(Call);
1093   if (!Message)
1094     return nullptr;
1095
1096   const ObjCMethodDecl *MD = Message->getDecl();
1097   if (!MD)
1098     return nullptr;
1099
1100   const ObjCInterfaceDecl *StaticClass;
1101   if (isa<ObjCProtocolDecl>(MD->getDeclContext())) {
1102     // We can't find out where the method was declared without doing more work.
1103     // Instead, see if the receiver is statically typed as a known immutable
1104     // collection.
1105     StaticClass = Message->getOriginExpr()->getReceiverInterface();
1106   } else {
1107     StaticClass = MD->getClassInterface();
1108   }
1109
1110   if (!StaticClass)
1111     return nullptr;
1112
1113   switch (findKnownClass(StaticClass, /*IncludeSuper=*/false)) {
1114   case FC_None:
1115     return nullptr;
1116   case FC_NSArray:
1117   case FC_NSDictionary:
1118   case FC_NSEnumerator:
1119   case FC_NSNull:
1120   case FC_NSOrderedSet:
1121   case FC_NSSet:
1122   case FC_NSString:
1123     break;
1124   }
1125
1126   return Message->getReceiverSVal().getAsSymbol();
1127 }
1128
1129 ProgramStateRef
1130 ObjCLoopChecker::checkPointerEscape(ProgramStateRef State,
1131                                     const InvalidatedSymbols &Escaped,
1132                                     const CallEvent *Call,
1133                                     PointerEscapeKind Kind) const {
1134   SymbolRef ImmutableReceiver = getMethodReceiverIfKnownImmutable(Call);
1135
1136   // Remove the invalidated symbols form the collection count map.
1137   for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
1138        E = Escaped.end();
1139        I != E; ++I) {
1140     SymbolRef Sym = *I;
1141
1142     // Don't invalidate this symbol's count if we know the method being called
1143     // is declared on an immutable class. This isn't completely correct if the
1144     // receiver is also passed as an argument, but in most uses of NSArray,
1145     // NSDictionary, etc. this isn't likely to happen in a dangerous way.
1146     if (Sym == ImmutableReceiver)
1147       continue;
1148
1149     // The symbol escaped. Pessimistically, assume that the count could have
1150     // changed.
1151     State = State->remove<ContainerCountMap>(Sym);
1152     State = State->remove<ContainerNonEmptyMap>(Sym);
1153   }
1154   return State;
1155 }
1156
1157 void ObjCLoopChecker::checkDeadSymbols(SymbolReaper &SymReaper,
1158                                        CheckerContext &C) const {
1159   ProgramStateRef State = C.getState();
1160
1161   // Remove the dead symbols from the collection count map.
1162   ContainerCountMapTy Tracked = State->get<ContainerCountMap>();
1163   for (ContainerCountMapTy::iterator I = Tracked.begin(),
1164                                      E = Tracked.end(); I != E; ++I) {
1165     SymbolRef Sym = I->first;
1166     if (SymReaper.isDead(Sym)) {
1167       State = State->remove<ContainerCountMap>(Sym);
1168       State = State->remove<ContainerNonEmptyMap>(Sym);
1169     }
1170   }
1171
1172   C.addTransition(State);
1173 }
1174
1175 namespace {
1176 /// \class ObjCNonNilReturnValueChecker
1177 /// \brief The checker restricts the return values of APIs known to
1178 /// never (or almost never) return 'nil'.
1179 class ObjCNonNilReturnValueChecker
1180   : public Checker<check::PostObjCMessage,
1181                    check::PostStmt<ObjCArrayLiteral>,
1182                    check::PostStmt<ObjCDictionaryLiteral>,
1183                    check::PostStmt<ObjCBoxedExpr> > {
1184     mutable bool Initialized;
1185     mutable Selector ObjectAtIndex;
1186     mutable Selector ObjectAtIndexedSubscript;
1187     mutable Selector NullSelector;
1188
1189 public:
1190   ObjCNonNilReturnValueChecker() : Initialized(false) {}
1191
1192   ProgramStateRef assumeExprIsNonNull(const Expr *NonNullExpr,
1193                                       ProgramStateRef State,
1194                                       CheckerContext &C) const;
1195   void assumeExprIsNonNull(const Expr *E, CheckerContext &C) const {
1196     C.addTransition(assumeExprIsNonNull(E, C.getState(), C));
1197   }
1198
1199   void checkPostStmt(const ObjCArrayLiteral *E, CheckerContext &C) const {
1200     assumeExprIsNonNull(E, C);
1201   }
1202   void checkPostStmt(const ObjCDictionaryLiteral *E, CheckerContext &C) const {
1203     assumeExprIsNonNull(E, C);
1204   }
1205   void checkPostStmt(const ObjCBoxedExpr *E, CheckerContext &C) const {
1206     assumeExprIsNonNull(E, C);
1207   }
1208
1209   void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
1210 };
1211 }
1212
1213 ProgramStateRef
1214 ObjCNonNilReturnValueChecker::assumeExprIsNonNull(const Expr *NonNullExpr,
1215                                                   ProgramStateRef State,
1216                                                   CheckerContext &C) const {
1217   SVal Val = State->getSVal(NonNullExpr, C.getLocationContext());
1218   if (Optional<DefinedOrUnknownSVal> DV = Val.getAs<DefinedOrUnknownSVal>())
1219     return State->assume(*DV, true);
1220   return State;
1221 }
1222
1223 void ObjCNonNilReturnValueChecker::checkPostObjCMessage(const ObjCMethodCall &M,
1224                                                         CheckerContext &C)
1225                                                         const {
1226   ProgramStateRef State = C.getState();
1227
1228   if (!Initialized) {
1229     ASTContext &Ctx = C.getASTContext();
1230     ObjectAtIndex = GetUnarySelector("objectAtIndex", Ctx);
1231     ObjectAtIndexedSubscript = GetUnarySelector("objectAtIndexedSubscript", Ctx);
1232     NullSelector = GetNullarySelector("null", Ctx);
1233   }
1234
1235   // Check the receiver type.
1236   if (const ObjCInterfaceDecl *Interface = M.getReceiverInterface()) {
1237
1238     // Assume that object returned from '[self init]' or '[super init]' is not
1239     // 'nil' if we are processing an inlined function/method.
1240     //
1241     // A defensive callee will (and should) check if the object returned by
1242     // '[super init]' is 'nil' before doing it's own initialization. However,
1243     // since 'nil' is rarely returned in practice, we should not warn when the
1244     // caller to the defensive constructor uses the object in contexts where
1245     // 'nil' is not accepted.
1246     if (!C.inTopFrame() && M.getDecl() &&
1247         M.getDecl()->getMethodFamily() == OMF_init &&
1248         M.isReceiverSelfOrSuper()) {
1249       State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1250     }
1251
1252     FoundationClass Cl = findKnownClass(Interface);
1253
1254     // Objects returned from
1255     // [NSArray|NSOrderedSet]::[ObjectAtIndex|ObjectAtIndexedSubscript]
1256     // are never 'nil'.
1257     if (Cl == FC_NSArray || Cl == FC_NSOrderedSet) {
1258       Selector Sel = M.getSelector();
1259       if (Sel == ObjectAtIndex || Sel == ObjectAtIndexedSubscript) {
1260         // Go ahead and assume the value is non-nil.
1261         State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1262       }
1263     }
1264
1265     // Objects returned from [NSNull null] are not nil.
1266     if (Cl == FC_NSNull) {
1267       if (M.getSelector() == NullSelector) {
1268         // Go ahead and assume the value is non-nil.
1269         State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1270       }
1271     }
1272   }
1273   C.addTransition(State);
1274 }
1275
1276 //===----------------------------------------------------------------------===//
1277 // Check registration.
1278 //===----------------------------------------------------------------------===//
1279
1280 void ento::registerNilArgChecker(CheckerManager &mgr) {
1281   mgr.registerChecker<NilArgChecker>();
1282 }
1283
1284 void ento::registerCFNumberCreateChecker(CheckerManager &mgr) {
1285   mgr.registerChecker<CFNumberCreateChecker>();
1286 }
1287
1288 void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
1289   mgr.registerChecker<CFRetainReleaseChecker>();
1290 }
1291
1292 void ento::registerClassReleaseChecker(CheckerManager &mgr) {
1293   mgr.registerChecker<ClassReleaseChecker>();
1294 }
1295
1296 void ento::registerVariadicMethodTypeChecker(CheckerManager &mgr) {
1297   mgr.registerChecker<VariadicMethodTypeChecker>();
1298 }
1299
1300 void ento::registerObjCLoopChecker(CheckerManager &mgr) {
1301   mgr.registerChecker<ObjCLoopChecker>();
1302 }
1303
1304 void
1305 ento::registerObjCNonNilReturnValueChecker(CheckerManager &mgr) {
1306   mgr.registerChecker<ObjCNonNilReturnValueChecker>();
1307 }