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