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