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
37using namespace clang;
38using namespace ento;
39
40namespace {
41class APIMisuse : public BugType {
42public:
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
52static StringRef GetReceiverInterfaceName(const ObjCMethodCall &msg) {
53  if (const ObjCInterfaceDecl *ID = msg.getReceiverInterface())
54    return ID->getIdentifier()->getName();
55  return StringRef();
56}
57
58enum 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
69static 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
95namespace {
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
137void 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
149void 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
201void 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
215void 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
320void 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
328void 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
342namespace {
343class CFNumberCreateChecker : public Checker< check::PreStmt<CallExpr> > {
344  mutable std::unique_ptr<APIMisuse> BT;
345  mutable IdentifierInfo* II;
346public:
347  CFNumberCreateChecker() : II(nullptr) {}
348
349  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
350
351private:
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
357enum 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
376static 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
404static 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
428void 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
528namespace {
529class CFRetainReleaseChecker : public Checker< check::PreStmt<CallExpr> > {
530  mutable std::unique_ptr<APIMisuse> BT;
531  mutable IdentifierInfo *Retain, *Release, *MakeCollectable, *Autorelease;
532
533public:
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
541void 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
622namespace {
623class 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
630public:
631  void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
632};
633} // end anonymous namespace
634
635void 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
678namespace {
679class 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
690public:
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.
697bool
698VariadicMethodTypeChecker::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
743void 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.
832REGISTER_MAP_WITH_PROGRAMSTATE(ContainerCountMap, SymbolRef, SymbolRef)
833REGISTER_MAP_WITH_PROGRAMSTATE(ContainerNonEmptyMap, SymbolRef, bool)
834
835namespace {
836class 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
846public:
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
858static 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.
883static 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.
908static 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.)
941static ProgramStateRef
942assumeCollectionNonEmpty(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
972static ProgramStateRef
973assumeCollectionNonEmpty(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.
985static 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
1005void 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
1028bool 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
1040void 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
1082static 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
1120ProgramStateRef
1121ObjCLoopChecker::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
1148void 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
1166namespace {
1167/// \class ObjCNonNilReturnValueChecker
1168/// \brief The checker restricts the return values of APIs known to
1169/// never (or almost never) return 'nil'.
1170class 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
1180public:
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
1204ProgramStateRef
1205ObjCNonNilReturnValueChecker::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
1214void 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
1271void ento::registerNilArgChecker(CheckerManager &mgr) {
1272  mgr.registerChecker<NilArgChecker>();
1273}
1274
1275void ento::registerCFNumberCreateChecker(CheckerManager &mgr) {
1276  mgr.registerChecker<CFNumberCreateChecker>();
1277}
1278
1279void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
1280  mgr.registerChecker<CFRetainReleaseChecker>();
1281}
1282
1283void ento::registerClassReleaseChecker(CheckerManager &mgr) {
1284  mgr.registerChecker<ClassReleaseChecker>();
1285}
1286
1287void ento::registerVariadicMethodTypeChecker(CheckerManager &mgr) {
1288  mgr.registerChecker<VariadicMethodTypeChecker>();
1289}
1290
1291void ento::registerObjCLoopChecker(CheckerManager &mgr) {
1292  mgr.registerChecker<ObjCLoopChecker>();
1293}
1294
1295void
1296ento::registerObjCNonNilReturnValueChecker(CheckerManager &mgr) {
1297  mgr.registerChecker<ObjCNonNilReturnValueChecker>();
1298}
1299