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