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