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