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