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