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 } // end anonymous namespace
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.generateErrorNode()) {
144       generateBugReport(N, Msg, E->getSourceRange(), E, C);
145     }
146   }
147 }
148 
149 void NilArgChecker::warnIfNilArg(CheckerContext &C,
150                                  const ObjCMethodCall &msg,
151                                  unsigned int Arg,
152                                  FoundationClass Class,
153                                  bool CanBeSubscript) const {
154   // Check if the argument is nil.
155   ProgramStateRef State = C.getState();
156   if (!State->isNull(msg.getArgSVal(Arg)).isConstrainedTrue())
157       return;
158 
159   if (ExplodedNode *N = C.generateErrorNode()) {
160     SmallString<128> sbuf;
161     llvm::raw_svector_ostream os(sbuf);
162 
163     if (CanBeSubscript && msg.getMessageKind() == OCM_Subscript) {
164 
165       if (Class == FC_NSArray) {
166         os << "Array element cannot be nil";
167       } else if (Class == FC_NSDictionary) {
168         if (Arg == 0) {
169           os << "Value stored into '";
170           os << GetReceiverInterfaceName(msg) << "' cannot be nil";
171         } else {
172           assert(Arg == 1);
173           os << "'"<< GetReceiverInterfaceName(msg) << "' key cannot be nil";
174         }
175       } else
176         llvm_unreachable("Missing foundation class for the subscript expr");
177 
178     } else {
179       if (Class == FC_NSDictionary) {
180         if (Arg == 0)
181           os << "Value argument ";
182         else {
183           assert(Arg == 1);
184           os << "Key argument ";
185         }
186         os << "to '";
187         msg.getSelector().print(os);
188         os << "' cannot be nil";
189       } else {
190         os << "Argument to '" << GetReceiverInterfaceName(msg) << "' method '";
191         msg.getSelector().print(os);
192         os << "' cannot be nil";
193       }
194     }
195 
196     generateBugReport(N, os.str(), msg.getArgSourceRange(Arg),
197                       msg.getArgExpr(Arg), C);
198   }
199 }
200 
201 void NilArgChecker::generateBugReport(ExplodedNode *N,
202                                       StringRef Msg,
203                                       SourceRange Range,
204                                       const Expr *E,
205                                       CheckerContext &C) const {
206   if (!BT)
207     BT.reset(new APIMisuse(this, "nil argument"));
208 
209   auto R = llvm::make_unique<BugReport>(*BT, Msg, N);
210   R->addRange(Range);
211   bugreporter::trackNullOrUndefValue(N, E, *R);
212   C.emitReport(std::move(R));
213 }
214 
215 void NilArgChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
216                                         CheckerContext &C) const {
217   const ObjCInterfaceDecl *ID = msg.getReceiverInterface();
218   if (!ID)
219     return;
220 
221   FoundationClass Class = findKnownClass(ID);
222 
223   static const unsigned InvalidArgIndex = UINT_MAX;
224   unsigned Arg = InvalidArgIndex;
225   bool CanBeSubscript = false;
226 
227   if (Class == FC_NSString) {
228     Selector S = msg.getSelector();
229 
230     if (S.isUnarySelector())
231       return;
232 
233     if (StringSelectors.empty()) {
234       ASTContext &Ctx = C.getASTContext();
235       Selector Sels[] = {
236         getKeywordSelector(Ctx, "caseInsensitiveCompare", nullptr),
237         getKeywordSelector(Ctx, "compare", nullptr),
238         getKeywordSelector(Ctx, "compare", "options", nullptr),
239         getKeywordSelector(Ctx, "compare", "options", "range", nullptr),
240         getKeywordSelector(Ctx, "compare", "options", "range", "locale",
241                            nullptr),
242         getKeywordSelector(Ctx, "componentsSeparatedByCharactersInSet",
243                            nullptr),
244         getKeywordSelector(Ctx, "initWithFormat",
245                            nullptr),
246         getKeywordSelector(Ctx, "localizedCaseInsensitiveCompare", nullptr),
247         getKeywordSelector(Ctx, "localizedCompare", nullptr),
248         getKeywordSelector(Ctx, "localizedStandardCompare", nullptr),
249       };
250       for (Selector KnownSel : Sels)
251         StringSelectors[KnownSel] = 0;
252     }
253     auto I = StringSelectors.find(S);
254     if (I == StringSelectors.end())
255       return;
256     Arg = I->second;
257   } else if (Class == FC_NSArray) {
258     Selector S = msg.getSelector();
259 
260     if (S.isUnarySelector())
261       return;
262 
263     if (ArrayWithObjectSel.isNull()) {
264       ASTContext &Ctx = C.getASTContext();
265       ArrayWithObjectSel = getKeywordSelector(Ctx, "arrayWithObject", nullptr);
266       AddObjectSel = getKeywordSelector(Ctx, "addObject", nullptr);
267       InsertObjectAtIndexSel =
268         getKeywordSelector(Ctx, "insertObject", "atIndex", nullptr);
269       ReplaceObjectAtIndexWithObjectSel =
270         getKeywordSelector(Ctx, "replaceObjectAtIndex", "withObject", nullptr);
271       SetObjectAtIndexedSubscriptSel =
272         getKeywordSelector(Ctx, "setObject", "atIndexedSubscript", nullptr);
273       ArrayByAddingObjectSel =
274         getKeywordSelector(Ctx, "arrayByAddingObject", nullptr);
275     }
276 
277     if (S == ArrayWithObjectSel || S == AddObjectSel ||
278         S == InsertObjectAtIndexSel || S == ArrayByAddingObjectSel) {
279       Arg = 0;
280     } else if (S == SetObjectAtIndexedSubscriptSel) {
281       Arg = 0;
282       CanBeSubscript = true;
283     } else if (S == ReplaceObjectAtIndexWithObjectSel) {
284       Arg = 1;
285     }
286   } else if (Class == FC_NSDictionary) {
287     Selector S = msg.getSelector();
288 
289     if (S.isUnarySelector())
290       return;
291 
292     if (DictionaryWithObjectForKeySel.isNull()) {
293       ASTContext &Ctx = C.getASTContext();
294       DictionaryWithObjectForKeySel =
295         getKeywordSelector(Ctx, "dictionaryWithObject", "forKey", nullptr);
296       SetObjectForKeySel =
297         getKeywordSelector(Ctx, "setObject", "forKey", nullptr);
298       SetObjectForKeyedSubscriptSel =
299         getKeywordSelector(Ctx, "setObject", "forKeyedSubscript", nullptr);
300       RemoveObjectForKeySel =
301         getKeywordSelector(Ctx, "removeObjectForKey", nullptr);
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   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> OptCFNumberSize = GetCFNumberSize(Ctx, NumberKind);
456 
457   // FIXME: In some cases we can emit an error.
458   if (!OptCFNumberSize)
459     return;
460 
461   uint64_t CFNumberSize = *OptCFNumberSize;
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 PrimitiveTypeSize = Ctx.getTypeSize(T);
487 
488   if (PrimitiveTypeSize == CFNumberSize)
489     return;
490 
491   // FIXME: We can actually create an abstract "CFNumber" object that has
492   //  the bits initialized to the provided values.
493   ExplodedNode *N = C.generateNonFatalErrorNode();
494   if (N) {
495     SmallString<128> sbuf;
496     llvm::raw_svector_ostream os(sbuf);
497     bool isCreate = (FD->getIdentifier() == ICreate);
498 
499     if (isCreate) {
500       os << (PrimitiveTypeSize == 8 ? "An " : "A ")
501          << PrimitiveTypeSize << "-bit integer is used to initialize a "
502          << "CFNumber object that represents "
503          << (CFNumberSize == 8 ? "an " : "a ")
504          << CFNumberSize << "-bit integer; ";
505     } else {
506       os << "A CFNumber object that represents "
507          << (CFNumberSize == 8 ? "an " : "a ")
508          << CFNumberSize << "-bit integer is used to initialize "
509          << (PrimitiveTypeSize == 8 ? "an " : "a ")
510          << PrimitiveTypeSize << "-bit integer; ";
511     }
512 
513     if (PrimitiveTypeSize < CFNumberSize)
514       os << (CFNumberSize - PrimitiveTypeSize)
515       << " bits of the CFNumber value will "
516       << (isCreate ? "be garbage." : "overwrite adjacent storage.");
517     else
518       os << (PrimitiveTypeSize - CFNumberSize)
519       << " bits of the integer value will be "
520       << (isCreate ? "lost." : "garbage.");
521 
522     if (!BT)
523       BT.reset(new APIMisuse(this, "Bad use of CFNumber APIs"));
524 
525     auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
526     report->addRange(CE->getArg(2)->getSourceRange());
527     C.emitReport(std::move(report));
528   }
529 }
530 
531 //===----------------------------------------------------------------------===//
532 // CFRetain/CFRelease/CFMakeCollectable/CFAutorelease checking for null arguments.
533 //===----------------------------------------------------------------------===//
534 
535 namespace {
536 class CFRetainReleaseChecker : public Checker< check::PreStmt<CallExpr> > {
537   mutable std::unique_ptr<APIMisuse> BT;
538   mutable IdentifierInfo *Retain, *Release, *MakeCollectable, *Autorelease;
539 
540 public:
541   CFRetainReleaseChecker()
542       : Retain(nullptr), Release(nullptr), MakeCollectable(nullptr),
543         Autorelease(nullptr) {}
544   void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
545 };
546 } // end anonymous namespace
547 
548 void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
549                                           CheckerContext &C) const {
550   // If the CallExpr doesn't have exactly 1 argument just give up checking.
551   if (CE->getNumArgs() != 1)
552     return;
553 
554   ProgramStateRef state = C.getState();
555   const FunctionDecl *FD = C.getCalleeDecl(CE);
556   if (!FD)
557     return;
558 
559   if (!BT) {
560     ASTContext &Ctx = C.getASTContext();
561     Retain = &Ctx.Idents.get("CFRetain");
562     Release = &Ctx.Idents.get("CFRelease");
563     MakeCollectable = &Ctx.Idents.get("CFMakeCollectable");
564     Autorelease = &Ctx.Idents.get("CFAutorelease");
565     BT.reset(new APIMisuse(
566         this, "null passed to CF memory management function"));
567   }
568 
569   // Check if we called CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
570   const IdentifierInfo *FuncII = FD->getIdentifier();
571   if (!(FuncII == Retain || FuncII == Release || FuncII == MakeCollectable ||
572         FuncII == Autorelease))
573     return;
574 
575   // FIXME: The rest of this just checks that the argument is non-null.
576   // It should probably be refactored and combined with NonNullParamChecker.
577 
578   // Get the argument's value.
579   const Expr *Arg = CE->getArg(0);
580   SVal ArgVal = state->getSVal(Arg, C.getLocationContext());
581   Optional<DefinedSVal> DefArgVal = ArgVal.getAs<DefinedSVal>();
582   if (!DefArgVal)
583     return;
584 
585   // Get a NULL value.
586   SValBuilder &svalBuilder = C.getSValBuilder();
587   DefinedSVal zero =
588       svalBuilder.makeZeroVal(Arg->getType()).castAs<DefinedSVal>();
589 
590   // Make an expression asserting that they're equal.
591   DefinedOrUnknownSVal ArgIsNull = svalBuilder.evalEQ(state, zero, *DefArgVal);
592 
593   // Are they equal?
594   ProgramStateRef stateTrue, stateFalse;
595   std::tie(stateTrue, stateFalse) = state->assume(ArgIsNull);
596 
597   if (stateTrue && !stateFalse) {
598     ExplodedNode *N = C.generateErrorNode(stateTrue);
599     if (!N)
600       return;
601 
602     const char *description;
603     if (FuncII == Retain)
604       description = "Null pointer argument in call to CFRetain";
605     else if (FuncII == Release)
606       description = "Null pointer argument in call to CFRelease";
607     else if (FuncII == MakeCollectable)
608       description = "Null pointer argument in call to CFMakeCollectable";
609     else if (FuncII == Autorelease)
610       description = "Null pointer argument in call to CFAutorelease";
611     else
612       llvm_unreachable("impossible case");
613 
614     auto report = llvm::make_unique<BugReport>(*BT, description, N);
615     report->addRange(Arg->getSourceRange());
616     bugreporter::trackNullOrUndefValue(N, Arg, *report);
617     C.emitReport(std::move(report));
618     return;
619   }
620 
621   // From here on, we know the argument is non-null.
622   C.addTransition(stateFalse);
623 }
624 
625 //===----------------------------------------------------------------------===//
626 // Check for sending 'retain', 'release', or 'autorelease' directly to a Class.
627 //===----------------------------------------------------------------------===//
628 
629 namespace {
630 class ClassReleaseChecker : public Checker<check::PreObjCMessage> {
631   mutable Selector releaseS;
632   mutable Selector retainS;
633   mutable Selector autoreleaseS;
634   mutable Selector drainS;
635   mutable std::unique_ptr<BugType> BT;
636 
637 public:
638   void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
639 };
640 } // end anonymous namespace
641 
642 void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
643                                               CheckerContext &C) const {
644   if (!BT) {
645     BT.reset(new APIMisuse(
646         this, "message incorrectly sent to class instead of class instance"));
647 
648     ASTContext &Ctx = C.getASTContext();
649     releaseS = GetNullarySelector("release", Ctx);
650     retainS = GetNullarySelector("retain", Ctx);
651     autoreleaseS = GetNullarySelector("autorelease", Ctx);
652     drainS = GetNullarySelector("drain", Ctx);
653   }
654 
655   if (msg.isInstanceMessage())
656     return;
657   const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
658   assert(Class);
659 
660   Selector S = msg.getSelector();
661   if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
662     return;
663 
664   if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
665     SmallString<200> buf;
666     llvm::raw_svector_ostream os(buf);
667 
668     os << "The '";
669     S.print(os);
670     os << "' message should be sent to instances "
671           "of class '" << Class->getName()
672        << "' and not the class directly";
673 
674     auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
675     report->addRange(msg.getSourceRange());
676     C.emitReport(std::move(report));
677   }
678 }
679 
680 //===----------------------------------------------------------------------===//
681 // Check for passing non-Objective-C types to variadic methods that expect
682 // only Objective-C types.
683 //===----------------------------------------------------------------------===//
684 
685 namespace {
686 class VariadicMethodTypeChecker : public Checker<check::PreObjCMessage> {
687   mutable Selector arrayWithObjectsS;
688   mutable Selector dictionaryWithObjectsAndKeysS;
689   mutable Selector setWithObjectsS;
690   mutable Selector orderedSetWithObjectsS;
691   mutable Selector initWithObjectsS;
692   mutable Selector initWithObjectsAndKeysS;
693   mutable std::unique_ptr<BugType> BT;
694 
695   bool isVariadicMessage(const ObjCMethodCall &msg) const;
696 
697 public:
698   void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
699 };
700 } // end anonymous namespace
701 
702 /// isVariadicMessage - Returns whether the given message is a variadic message,
703 /// where all arguments must be Objective-C types.
704 bool
705 VariadicMethodTypeChecker::isVariadicMessage(const ObjCMethodCall &msg) const {
706   const ObjCMethodDecl *MD = msg.getDecl();
707 
708   if (!MD || !MD->isVariadic() || isa<ObjCProtocolDecl>(MD->getDeclContext()))
709     return false;
710 
711   Selector S = msg.getSelector();
712 
713   if (msg.isInstanceMessage()) {
714     // FIXME: Ideally we'd look at the receiver interface here, but that's not
715     // useful for init, because alloc returns 'id'. In theory, this could lead
716     // to false positives, for example if there existed a class that had an
717     // initWithObjects: implementation that does accept non-Objective-C pointer
718     // types, but the chance of that happening is pretty small compared to the
719     // gains that this analysis gives.
720     const ObjCInterfaceDecl *Class = MD->getClassInterface();
721 
722     switch (findKnownClass(Class)) {
723     case FC_NSArray:
724     case FC_NSOrderedSet:
725     case FC_NSSet:
726       return S == initWithObjectsS;
727     case FC_NSDictionary:
728       return S == initWithObjectsAndKeysS;
729     default:
730       return false;
731     }
732   } else {
733     const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
734 
735     switch (findKnownClass(Class)) {
736       case FC_NSArray:
737         return S == arrayWithObjectsS;
738       case FC_NSOrderedSet:
739         return S == orderedSetWithObjectsS;
740       case FC_NSSet:
741         return S == setWithObjectsS;
742       case FC_NSDictionary:
743         return S == dictionaryWithObjectsAndKeysS;
744       default:
745         return false;
746     }
747   }
748 }
749 
750 void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
751                                                     CheckerContext &C) const {
752   if (!BT) {
753     BT.reset(new APIMisuse(this,
754                            "Arguments passed to variadic method aren't all "
755                            "Objective-C pointer types"));
756 
757     ASTContext &Ctx = C.getASTContext();
758     arrayWithObjectsS = GetUnarySelector("arrayWithObjects", Ctx);
759     dictionaryWithObjectsAndKeysS =
760       GetUnarySelector("dictionaryWithObjectsAndKeys", Ctx);
761     setWithObjectsS = GetUnarySelector("setWithObjects", Ctx);
762     orderedSetWithObjectsS = GetUnarySelector("orderedSetWithObjects", Ctx);
763 
764     initWithObjectsS = GetUnarySelector("initWithObjects", Ctx);
765     initWithObjectsAndKeysS = GetUnarySelector("initWithObjectsAndKeys", Ctx);
766   }
767 
768   if (!isVariadicMessage(msg))
769       return;
770 
771   // We are not interested in the selector arguments since they have
772   // well-defined types, so the compiler will issue a warning for them.
773   unsigned variadicArgsBegin = msg.getSelector().getNumArgs();
774 
775   // We're not interested in the last argument since it has to be nil or the
776   // compiler would have issued a warning for it elsewhere.
777   unsigned variadicArgsEnd = msg.getNumArgs() - 1;
778 
779   if (variadicArgsEnd <= variadicArgsBegin)
780     return;
781 
782   // Verify that all arguments have Objective-C types.
783   Optional<ExplodedNode*> errorNode;
784 
785   for (unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) {
786     QualType ArgTy = msg.getArgExpr(I)->getType();
787     if (ArgTy->isObjCObjectPointerType())
788       continue;
789 
790     // Block pointers are treaded as Objective-C pointers.
791     if (ArgTy->isBlockPointerType())
792       continue;
793 
794     // Ignore pointer constants.
795     if (msg.getArgSVal(I).getAs<loc::ConcreteInt>())
796       continue;
797 
798     // Ignore pointer types annotated with 'NSObject' attribute.
799     if (C.getASTContext().isObjCNSObjectType(ArgTy))
800       continue;
801 
802     // Ignore CF references, which can be toll-free bridged.
803     if (coreFoundation::isCFObjectRef(ArgTy))
804       continue;
805 
806     // Generate only one error node to use for all bug reports.
807     if (!errorNode.hasValue())
808       errorNode = C.generateNonFatalErrorNode();
809 
810     if (!errorNode.getValue())
811       continue;
812 
813     SmallString<128> sbuf;
814     llvm::raw_svector_ostream os(sbuf);
815 
816     StringRef TypeName = GetReceiverInterfaceName(msg);
817     if (!TypeName.empty())
818       os << "Argument to '" << TypeName << "' method '";
819     else
820       os << "Argument to method '";
821 
822     msg.getSelector().print(os);
823     os << "' should be an Objective-C pointer type, not '";
824     ArgTy.print(os, C.getLangOpts());
825     os << "'";
826 
827     auto R = llvm::make_unique<BugReport>(*BT, os.str(), errorNode.getValue());
828     R->addRange(msg.getArgSourceRange(I));
829     C.emitReport(std::move(R));
830   }
831 }
832 
833 //===----------------------------------------------------------------------===//
834 // Improves the modeling of loops over Cocoa collections.
835 //===----------------------------------------------------------------------===//
836 
837 // The map from container symbol to the container count symbol.
838 // We currently will remember the last countainer count symbol encountered.
839 REGISTER_MAP_WITH_PROGRAMSTATE(ContainerCountMap, SymbolRef, SymbolRef)
840 REGISTER_MAP_WITH_PROGRAMSTATE(ContainerNonEmptyMap, SymbolRef, bool)
841 
842 namespace {
843 class ObjCLoopChecker
844   : public Checker<check::PostStmt<ObjCForCollectionStmt>,
845                    check::PostObjCMessage,
846                    check::DeadSymbols,
847                    check::PointerEscape > {
848   mutable IdentifierInfo *CountSelectorII;
849 
850   bool isCollectionCountMethod(const ObjCMethodCall &M,
851                                CheckerContext &C) const;
852 
853 public:
854   ObjCLoopChecker() : CountSelectorII(nullptr) {}
855   void checkPostStmt(const ObjCForCollectionStmt *FCS, CheckerContext &C) const;
856   void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
857   void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
858   ProgramStateRef checkPointerEscape(ProgramStateRef State,
859                                      const InvalidatedSymbols &Escaped,
860                                      const CallEvent *Call,
861                                      PointerEscapeKind Kind) const;
862 };
863 } // end anonymous namespace
864 
865 static bool isKnownNonNilCollectionType(QualType T) {
866   const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
867   if (!PT)
868     return false;
869 
870   const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
871   if (!ID)
872     return false;
873 
874   switch (findKnownClass(ID)) {
875   case FC_NSArray:
876   case FC_NSDictionary:
877   case FC_NSEnumerator:
878   case FC_NSOrderedSet:
879   case FC_NSSet:
880     return true;
881   default:
882     return false;
883   }
884 }
885 
886 /// Assumes that the collection is non-nil.
887 ///
888 /// If the collection is known to be nil, returns NULL to indicate an infeasible
889 /// path.
890 static ProgramStateRef checkCollectionNonNil(CheckerContext &C,
891                                              ProgramStateRef State,
892                                              const ObjCForCollectionStmt *FCS) {
893   if (!State)
894     return nullptr;
895 
896   SVal CollectionVal = C.getSVal(FCS->getCollection());
897   Optional<DefinedSVal> KnownCollection = CollectionVal.getAs<DefinedSVal>();
898   if (!KnownCollection)
899     return State;
900 
901   ProgramStateRef StNonNil, StNil;
902   std::tie(StNonNil, StNil) = State->assume(*KnownCollection);
903   if (StNil && !StNonNil) {
904     // The collection is nil. This path is infeasible.
905     return nullptr;
906   }
907 
908   return StNonNil;
909 }
910 
911 /// Assumes that the collection elements are non-nil.
912 ///
913 /// This only applies if the collection is one of those known not to contain
914 /// nil values.
915 static ProgramStateRef checkElementNonNil(CheckerContext &C,
916                                           ProgramStateRef State,
917                                           const ObjCForCollectionStmt *FCS) {
918   if (!State)
919     return nullptr;
920 
921   // See if the collection is one where we /know/ the elements are non-nil.
922   if (!isKnownNonNilCollectionType(FCS->getCollection()->getType()))
923     return State;
924 
925   const LocationContext *LCtx = C.getLocationContext();
926   const Stmt *Element = FCS->getElement();
927 
928   // FIXME: Copied from ExprEngineObjC.
929   Optional<Loc> ElementLoc;
930   if (const DeclStmt *DS = dyn_cast<DeclStmt>(Element)) {
931     const VarDecl *ElemDecl = cast<VarDecl>(DS->getSingleDecl());
932     assert(ElemDecl->getInit() == nullptr);
933     ElementLoc = State->getLValue(ElemDecl, LCtx);
934   } else {
935     ElementLoc = State->getSVal(Element, LCtx).getAs<Loc>();
936   }
937 
938   if (!ElementLoc)
939     return State;
940 
941   // Go ahead and assume the value is non-nil.
942   SVal Val = State->getSVal(*ElementLoc);
943   return State->assume(Val.castAs<DefinedOrUnknownSVal>(), true);
944 }
945 
946 /// Returns NULL state if the collection is known to contain elements
947 /// (or is known not to contain elements if the Assumption parameter is false.)
948 static ProgramStateRef
949 assumeCollectionNonEmpty(CheckerContext &C, ProgramStateRef State,
950                          SymbolRef CollectionS, bool Assumption) {
951   if (!State || !CollectionS)
952     return State;
953 
954   const SymbolRef *CountS = State->get<ContainerCountMap>(CollectionS);
955   if (!CountS) {
956     const bool *KnownNonEmpty = State->get<ContainerNonEmptyMap>(CollectionS);
957     if (!KnownNonEmpty)
958       return State->set<ContainerNonEmptyMap>(CollectionS, Assumption);
959     return (Assumption == *KnownNonEmpty) ? State : nullptr;
960   }
961 
962   SValBuilder &SvalBuilder = C.getSValBuilder();
963   SVal CountGreaterThanZeroVal =
964     SvalBuilder.evalBinOp(State, BO_GT,
965                           nonloc::SymbolVal(*CountS),
966                           SvalBuilder.makeIntVal(0, (*CountS)->getType()),
967                           SvalBuilder.getConditionType());
968   Optional<DefinedSVal> CountGreaterThanZero =
969     CountGreaterThanZeroVal.getAs<DefinedSVal>();
970   if (!CountGreaterThanZero) {
971     // The SValBuilder cannot construct a valid SVal for this condition.
972     // This means we cannot properly reason about it.
973     return State;
974   }
975 
976   return State->assume(*CountGreaterThanZero, Assumption);
977 }
978 
979 static ProgramStateRef
980 assumeCollectionNonEmpty(CheckerContext &C, ProgramStateRef State,
981                          const ObjCForCollectionStmt *FCS,
982                          bool Assumption) {
983   if (!State)
984     return nullptr;
985 
986   SymbolRef CollectionS =
987     State->getSVal(FCS->getCollection(), C.getLocationContext()).getAsSymbol();
988   return assumeCollectionNonEmpty(C, State, CollectionS, Assumption);
989 }
990 
991 /// If the fist block edge is a back edge, we are reentering the loop.
992 static bool alreadyExecutedAtLeastOneLoopIteration(const ExplodedNode *N,
993                                              const ObjCForCollectionStmt *FCS) {
994   if (!N)
995     return false;
996 
997   ProgramPoint P = N->getLocation();
998   if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
999     return BE->getSrc()->getLoopTarget() == FCS;
1000   }
1001 
1002   // Keep looking for a block edge.
1003   for (ExplodedNode::const_pred_iterator I = N->pred_begin(),
1004                                          E = N->pred_end(); I != E; ++I) {
1005     if (alreadyExecutedAtLeastOneLoopIteration(*I, FCS))
1006       return true;
1007   }
1008 
1009   return false;
1010 }
1011 
1012 void ObjCLoopChecker::checkPostStmt(const ObjCForCollectionStmt *FCS,
1013                                     CheckerContext &C) const {
1014   ProgramStateRef State = C.getState();
1015 
1016   // Check if this is the branch for the end of the loop.
1017   SVal CollectionSentinel = C.getSVal(FCS);
1018   if (CollectionSentinel.isZeroConstant()) {
1019     if (!alreadyExecutedAtLeastOneLoopIteration(C.getPredecessor(), FCS))
1020       State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/false);
1021 
1022   // Otherwise, this is a branch that goes through the loop body.
1023   } else {
1024     State = checkCollectionNonNil(C, State, FCS);
1025     State = checkElementNonNil(C, State, FCS);
1026     State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/true);
1027   }
1028 
1029   if (!State)
1030     C.generateSink(C.getState(), C.getPredecessor());
1031   else if (State != C.getState())
1032     C.addTransition(State);
1033 }
1034 
1035 bool ObjCLoopChecker::isCollectionCountMethod(const ObjCMethodCall &M,
1036                                               CheckerContext &C) const {
1037   Selector S = M.getSelector();
1038   // Initialize the identifiers on first use.
1039   if (!CountSelectorII)
1040     CountSelectorII = &C.getASTContext().Idents.get("count");
1041 
1042   // If the method returns collection count, record the value.
1043   return S.isUnarySelector() &&
1044          (S.getIdentifierInfoForSlot(0) == CountSelectorII);
1045 }
1046 
1047 void ObjCLoopChecker::checkPostObjCMessage(const ObjCMethodCall &M,
1048                                            CheckerContext &C) const {
1049   if (!M.isInstanceMessage())
1050     return;
1051 
1052   const ObjCInterfaceDecl *ClassID = M.getReceiverInterface();
1053   if (!ClassID)
1054     return;
1055 
1056   FoundationClass Class = findKnownClass(ClassID);
1057   if (Class != FC_NSDictionary &&
1058       Class != FC_NSArray &&
1059       Class != FC_NSSet &&
1060       Class != FC_NSOrderedSet)
1061     return;
1062 
1063   SymbolRef ContainerS = M.getReceiverSVal().getAsSymbol();
1064   if (!ContainerS)
1065     return;
1066 
1067   // If we are processing a call to "count", get the symbolic value returned by
1068   // a call to "count" and add it to the map.
1069   if (!isCollectionCountMethod(M, C))
1070     return;
1071 
1072   const Expr *MsgExpr = M.getOriginExpr();
1073   SymbolRef CountS = C.getSVal(MsgExpr).getAsSymbol();
1074   if (CountS) {
1075     ProgramStateRef State = C.getState();
1076 
1077     C.getSymbolManager().addSymbolDependency(ContainerS, CountS);
1078     State = State->set<ContainerCountMap>(ContainerS, CountS);
1079 
1080     if (const bool *NonEmpty = State->get<ContainerNonEmptyMap>(ContainerS)) {
1081       State = State->remove<ContainerNonEmptyMap>(ContainerS);
1082       State = assumeCollectionNonEmpty(C, State, ContainerS, *NonEmpty);
1083     }
1084 
1085     C.addTransition(State);
1086   }
1087 }
1088 
1089 static SymbolRef getMethodReceiverIfKnownImmutable(const CallEvent *Call) {
1090   const ObjCMethodCall *Message = dyn_cast_or_null<ObjCMethodCall>(Call);
1091   if (!Message)
1092     return nullptr;
1093 
1094   const ObjCMethodDecl *MD = Message->getDecl();
1095   if (!MD)
1096     return nullptr;
1097 
1098   const ObjCInterfaceDecl *StaticClass;
1099   if (isa<ObjCProtocolDecl>(MD->getDeclContext())) {
1100     // We can't find out where the method was declared without doing more work.
1101     // Instead, see if the receiver is statically typed as a known immutable
1102     // collection.
1103     StaticClass = Message->getOriginExpr()->getReceiverInterface();
1104   } else {
1105     StaticClass = MD->getClassInterface();
1106   }
1107 
1108   if (!StaticClass)
1109     return nullptr;
1110 
1111   switch (findKnownClass(StaticClass, /*IncludeSuper=*/false)) {
1112   case FC_None:
1113     return nullptr;
1114   case FC_NSArray:
1115   case FC_NSDictionary:
1116   case FC_NSEnumerator:
1117   case FC_NSNull:
1118   case FC_NSOrderedSet:
1119   case FC_NSSet:
1120   case FC_NSString:
1121     break;
1122   }
1123 
1124   return Message->getReceiverSVal().getAsSymbol();
1125 }
1126 
1127 ProgramStateRef
1128 ObjCLoopChecker::checkPointerEscape(ProgramStateRef State,
1129                                     const InvalidatedSymbols &Escaped,
1130                                     const CallEvent *Call,
1131                                     PointerEscapeKind Kind) const {
1132   SymbolRef ImmutableReceiver = getMethodReceiverIfKnownImmutable(Call);
1133 
1134   // Remove the invalidated symbols form the collection count map.
1135   for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
1136        E = Escaped.end();
1137        I != E; ++I) {
1138     SymbolRef Sym = *I;
1139 
1140     // Don't invalidate this symbol's count if we know the method being called
1141     // is declared on an immutable class. This isn't completely correct if the
1142     // receiver is also passed as an argument, but in most uses of NSArray,
1143     // NSDictionary, etc. this isn't likely to happen in a dangerous way.
1144     if (Sym == ImmutableReceiver)
1145       continue;
1146 
1147     // The symbol escaped. Pessimistically, assume that the count could have
1148     // changed.
1149     State = State->remove<ContainerCountMap>(Sym);
1150     State = State->remove<ContainerNonEmptyMap>(Sym);
1151   }
1152   return State;
1153 }
1154 
1155 void ObjCLoopChecker::checkDeadSymbols(SymbolReaper &SymReaper,
1156                                        CheckerContext &C) const {
1157   ProgramStateRef State = C.getState();
1158 
1159   // Remove the dead symbols from the collection count map.
1160   ContainerCountMapTy Tracked = State->get<ContainerCountMap>();
1161   for (ContainerCountMapTy::iterator I = Tracked.begin(),
1162                                      E = Tracked.end(); I != E; ++I) {
1163     SymbolRef Sym = I->first;
1164     if (SymReaper.isDead(Sym)) {
1165       State = State->remove<ContainerCountMap>(Sym);
1166       State = State->remove<ContainerNonEmptyMap>(Sym);
1167     }
1168   }
1169 
1170   C.addTransition(State);
1171 }
1172 
1173 namespace {
1174 /// \class ObjCNonNilReturnValueChecker
1175 /// \brief The checker restricts the return values of APIs known to
1176 /// never (or almost never) return 'nil'.
1177 class ObjCNonNilReturnValueChecker
1178   : public Checker<check::PostObjCMessage,
1179                    check::PostStmt<ObjCArrayLiteral>,
1180                    check::PostStmt<ObjCDictionaryLiteral>,
1181                    check::PostStmt<ObjCBoxedExpr> > {
1182     mutable bool Initialized;
1183     mutable Selector ObjectAtIndex;
1184     mutable Selector ObjectAtIndexedSubscript;
1185     mutable Selector NullSelector;
1186 
1187 public:
1188   ObjCNonNilReturnValueChecker() : Initialized(false) {}
1189 
1190   ProgramStateRef assumeExprIsNonNull(const Expr *NonNullExpr,
1191                                       ProgramStateRef State,
1192                                       CheckerContext &C) const;
1193   void assumeExprIsNonNull(const Expr *E, CheckerContext &C) const {
1194     C.addTransition(assumeExprIsNonNull(E, C.getState(), C));
1195   }
1196 
1197   void checkPostStmt(const ObjCArrayLiteral *E, CheckerContext &C) const {
1198     assumeExprIsNonNull(E, C);
1199   }
1200   void checkPostStmt(const ObjCDictionaryLiteral *E, CheckerContext &C) const {
1201     assumeExprIsNonNull(E, C);
1202   }
1203   void checkPostStmt(const ObjCBoxedExpr *E, CheckerContext &C) const {
1204     assumeExprIsNonNull(E, C);
1205   }
1206 
1207   void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
1208 };
1209 } // end anonymous namespace
1210 
1211 ProgramStateRef
1212 ObjCNonNilReturnValueChecker::assumeExprIsNonNull(const Expr *NonNullExpr,
1213                                                   ProgramStateRef State,
1214                                                   CheckerContext &C) const {
1215   SVal Val = State->getSVal(NonNullExpr, C.getLocationContext());
1216   if (Optional<DefinedOrUnknownSVal> DV = Val.getAs<DefinedOrUnknownSVal>())
1217     return State->assume(*DV, true);
1218   return State;
1219 }
1220 
1221 void ObjCNonNilReturnValueChecker::checkPostObjCMessage(const ObjCMethodCall &M,
1222                                                         CheckerContext &C)
1223                                                         const {
1224   ProgramStateRef State = C.getState();
1225 
1226   if (!Initialized) {
1227     ASTContext &Ctx = C.getASTContext();
1228     ObjectAtIndex = GetUnarySelector("objectAtIndex", Ctx);
1229     ObjectAtIndexedSubscript = GetUnarySelector("objectAtIndexedSubscript", Ctx);
1230     NullSelector = GetNullarySelector("null", Ctx);
1231   }
1232 
1233   // Check the receiver type.
1234   if (const ObjCInterfaceDecl *Interface = M.getReceiverInterface()) {
1235 
1236     // Assume that object returned from '[self init]' or '[super init]' is not
1237     // 'nil' if we are processing an inlined function/method.
1238     //
1239     // A defensive callee will (and should) check if the object returned by
1240     // '[super init]' is 'nil' before doing it's own initialization. However,
1241     // since 'nil' is rarely returned in practice, we should not warn when the
1242     // caller to the defensive constructor uses the object in contexts where
1243     // 'nil' is not accepted.
1244     if (!C.inTopFrame() && M.getDecl() &&
1245         M.getDecl()->getMethodFamily() == OMF_init &&
1246         M.isReceiverSelfOrSuper()) {
1247       State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1248     }
1249 
1250     FoundationClass Cl = findKnownClass(Interface);
1251 
1252     // Objects returned from
1253     // [NSArray|NSOrderedSet]::[ObjectAtIndex|ObjectAtIndexedSubscript]
1254     // are never 'nil'.
1255     if (Cl == FC_NSArray || Cl == FC_NSOrderedSet) {
1256       Selector Sel = M.getSelector();
1257       if (Sel == ObjectAtIndex || Sel == ObjectAtIndexedSubscript) {
1258         // Go ahead and assume the value is non-nil.
1259         State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1260       }
1261     }
1262 
1263     // Objects returned from [NSNull null] are not nil.
1264     if (Cl == FC_NSNull) {
1265       if (M.getSelector() == NullSelector) {
1266         // Go ahead and assume the value is non-nil.
1267         State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1268       }
1269     }
1270   }
1271   C.addTransition(State);
1272 }
1273 
1274 //===----------------------------------------------------------------------===//
1275 // Check registration.
1276 //===----------------------------------------------------------------------===//
1277 
1278 void ento::registerNilArgChecker(CheckerManager &mgr) {
1279   mgr.registerChecker<NilArgChecker>();
1280 }
1281 
1282 void ento::registerCFNumberChecker(CheckerManager &mgr) {
1283   mgr.registerChecker<CFNumberChecker>();
1284 }
1285 
1286 void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
1287   mgr.registerChecker<CFRetainReleaseChecker>();
1288 }
1289 
1290 void ento::registerClassReleaseChecker(CheckerManager &mgr) {
1291   mgr.registerChecker<ClassReleaseChecker>();
1292 }
1293 
1294 void ento::registerVariadicMethodTypeChecker(CheckerManager &mgr) {
1295   mgr.registerChecker<VariadicMethodTypeChecker>();
1296 }
1297 
1298 void ento::registerObjCLoopChecker(CheckerManager &mgr) {
1299   mgr.registerChecker<ObjCLoopChecker>();
1300 }
1301 
1302 void
1303 ento::registerObjCNonNilReturnValueChecker(CheckerManager &mgr) {
1304   mgr.registerChecker<ObjCNonNilReturnValueChecker>();
1305 }
1306