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