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