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