xref: /llvm-project/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp (revision e359f3caeed5bda3750b989e90461fd074a18816)
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 "clang/AST/ASTContext.h"
18 #include "clang/AST/DeclObjC.h"
19 #include "clang/AST/Expr.h"
20 #include "clang/AST/ExprObjC.h"
21 #include "clang/AST/StmtObjC.h"
22 #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
23 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
24 #include "clang/StaticAnalyzer/Core/Checker.h"
25 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
26 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
27 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
28 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
29 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
30 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
31 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
32 #include "llvm/ADT/SmallString.h"
33 #include "llvm/ADT/StringMap.h"
34 #include "llvm/Support/raw_ostream.h"
35 
36 using namespace clang;
37 using namespace ento;
38 
39 namespace {
40 class APIMisuse : public BugType {
41 public:
42   APIMisuse(const char* name) : BugType(name, "API Misuse (Apple)") {}
43 };
44 } // end anonymous namespace
45 
46 //===----------------------------------------------------------------------===//
47 // Utility functions.
48 //===----------------------------------------------------------------------===//
49 
50 static StringRef GetReceiverInterfaceName(const ObjCMethodCall &msg) {
51   if (const ObjCInterfaceDecl *ID = msg.getReceiverInterface())
52     return ID->getIdentifier()->getName();
53   return StringRef();
54 }
55 
56 enum FoundationClass {
57   FC_None,
58   FC_NSArray,
59   FC_NSDictionary,
60   FC_NSEnumerator,
61   FC_NSOrderedSet,
62   FC_NSSet,
63   FC_NSString
64 };
65 
66 static FoundationClass findKnownClass(const ObjCInterfaceDecl *ID) {
67   static llvm::StringMap<FoundationClass> Classes;
68   if (Classes.empty()) {
69     Classes["NSArray"] = FC_NSArray;
70     Classes["NSDictionary"] = FC_NSDictionary;
71     Classes["NSEnumerator"] = FC_NSEnumerator;
72     Classes["NSOrderedSet"] = FC_NSOrderedSet;
73     Classes["NSSet"] = FC_NSSet;
74     Classes["NSString"] = FC_NSString;
75   }
76 
77   // FIXME: Should we cache this at all?
78   FoundationClass result = Classes.lookup(ID->getIdentifier()->getName());
79   if (result == FC_None)
80     if (const ObjCInterfaceDecl *Super = ID->getSuperClass())
81       return findKnownClass(Super);
82 
83   return result;
84 }
85 
86 static inline bool isNil(SVal X) {
87   return X.getAs<loc::ConcreteInt>();
88 }
89 
90 //===----------------------------------------------------------------------===//
91 // NilArgChecker - Check for prohibited nil arguments to ObjC method calls.
92 //===----------------------------------------------------------------------===//
93 
94 namespace {
95   class NilArgChecker : public Checker<check::PreObjCMessage> {
96     mutable OwningPtr<APIMisuse> BT;
97 
98     void WarnNilArg(CheckerContext &C,
99                     const ObjCMethodCall &msg, unsigned Arg) const;
100 
101   public:
102     void checkPreObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
103   };
104 }
105 
106 void NilArgChecker::WarnNilArg(CheckerContext &C,
107                                const ObjCMethodCall &msg,
108                                unsigned int Arg) const
109 {
110   if (!BT)
111     BT.reset(new APIMisuse("nil argument"));
112 
113   if (ExplodedNode *N = C.generateSink()) {
114     SmallString<128> sbuf;
115     llvm::raw_svector_ostream os(sbuf);
116     os << "Argument to '" << GetReceiverInterfaceName(msg) << "' method '"
117        << msg.getSelector().getAsString() << "' cannot be nil";
118 
119     BugReport *R = new BugReport(*BT, os.str(), N);
120     R->addRange(msg.getArgSourceRange(Arg));
121     C.emitReport(R);
122   }
123 }
124 
125 void NilArgChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
126                                         CheckerContext &C) const {
127   const ObjCInterfaceDecl *ID = msg.getReceiverInterface();
128   if (!ID)
129     return;
130 
131   if (findKnownClass(ID) == FC_NSString) {
132     Selector S = msg.getSelector();
133 
134     if (S.isUnarySelector())
135       return;
136 
137     // FIXME: This is going to be really slow doing these checks with
138     //  lexical comparisons.
139 
140     std::string NameStr = S.getAsString();
141     StringRef Name(NameStr);
142     assert(!Name.empty());
143 
144     // FIXME: Checking for initWithFormat: will not work in most cases
145     //  yet because [NSString alloc] returns id, not NSString*.  We will
146     //  need support for tracking expected-type information in the analyzer
147     //  to find these errors.
148     if (Name == "caseInsensitiveCompare:" ||
149         Name == "compare:" ||
150         Name == "compare:options:" ||
151         Name == "compare:options:range:" ||
152         Name == "compare:options:range:locale:" ||
153         Name == "componentsSeparatedByCharactersInSet:" ||
154         Name == "initWithFormat:") {
155       if (isNil(msg.getArgSVal(0)))
156         WarnNilArg(C, msg, 0);
157     }
158   }
159 }
160 
161 //===----------------------------------------------------------------------===//
162 // Error reporting.
163 //===----------------------------------------------------------------------===//
164 
165 namespace {
166 class CFNumberCreateChecker : public Checker< check::PreStmt<CallExpr> > {
167   mutable OwningPtr<APIMisuse> BT;
168   mutable IdentifierInfo* II;
169 public:
170   CFNumberCreateChecker() : II(0) {}
171 
172   void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
173 
174 private:
175   void EmitError(const TypedRegion* R, const Expr *Ex,
176                 uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind);
177 };
178 } // end anonymous namespace
179 
180 enum CFNumberType {
181   kCFNumberSInt8Type = 1,
182   kCFNumberSInt16Type = 2,
183   kCFNumberSInt32Type = 3,
184   kCFNumberSInt64Type = 4,
185   kCFNumberFloat32Type = 5,
186   kCFNumberFloat64Type = 6,
187   kCFNumberCharType = 7,
188   kCFNumberShortType = 8,
189   kCFNumberIntType = 9,
190   kCFNumberLongType = 10,
191   kCFNumberLongLongType = 11,
192   kCFNumberFloatType = 12,
193   kCFNumberDoubleType = 13,
194   kCFNumberCFIndexType = 14,
195   kCFNumberNSIntegerType = 15,
196   kCFNumberCGFloatType = 16
197 };
198 
199 static Optional<uint64_t> GetCFNumberSize(ASTContext &Ctx, uint64_t i) {
200   static const unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 };
201 
202   if (i < kCFNumberCharType)
203     return FixedSize[i-1];
204 
205   QualType T;
206 
207   switch (i) {
208     case kCFNumberCharType:     T = Ctx.CharTy;     break;
209     case kCFNumberShortType:    T = Ctx.ShortTy;    break;
210     case kCFNumberIntType:      T = Ctx.IntTy;      break;
211     case kCFNumberLongType:     T = Ctx.LongTy;     break;
212     case kCFNumberLongLongType: T = Ctx.LongLongTy; break;
213     case kCFNumberFloatType:    T = Ctx.FloatTy;    break;
214     case kCFNumberDoubleType:   T = Ctx.DoubleTy;   break;
215     case kCFNumberCFIndexType:
216     case kCFNumberNSIntegerType:
217     case kCFNumberCGFloatType:
218       // FIXME: We need a way to map from names to Type*.
219     default:
220       return Optional<uint64_t>();
221   }
222 
223   return Ctx.getTypeSize(T);
224 }
225 
226 #if 0
227 static const char* GetCFNumberTypeStr(uint64_t i) {
228   static const char* Names[] = {
229     "kCFNumberSInt8Type",
230     "kCFNumberSInt16Type",
231     "kCFNumberSInt32Type",
232     "kCFNumberSInt64Type",
233     "kCFNumberFloat32Type",
234     "kCFNumberFloat64Type",
235     "kCFNumberCharType",
236     "kCFNumberShortType",
237     "kCFNumberIntType",
238     "kCFNumberLongType",
239     "kCFNumberLongLongType",
240     "kCFNumberFloatType",
241     "kCFNumberDoubleType",
242     "kCFNumberCFIndexType",
243     "kCFNumberNSIntegerType",
244     "kCFNumberCGFloatType"
245   };
246 
247   return i <= kCFNumberCGFloatType ? Names[i-1] : "Invalid CFNumberType";
248 }
249 #endif
250 
251 void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
252                                          CheckerContext &C) const {
253   ProgramStateRef state = C.getState();
254   const FunctionDecl *FD = C.getCalleeDecl(CE);
255   if (!FD)
256     return;
257 
258   ASTContext &Ctx = C.getASTContext();
259   if (!II)
260     II = &Ctx.Idents.get("CFNumberCreate");
261 
262   if (FD->getIdentifier() != II || CE->getNumArgs() != 3)
263     return;
264 
265   // Get the value of the "theType" argument.
266   const LocationContext *LCtx = C.getLocationContext();
267   SVal TheTypeVal = state->getSVal(CE->getArg(1), LCtx);
268 
269   // FIXME: We really should allow ranges of valid theType values, and
270   //   bifurcate the state appropriately.
271   llvm::Optional<nonloc::ConcreteInt> V =
272       TheTypeVal.getAs<nonloc::ConcreteInt>();
273   if (!V)
274     return;
275 
276   uint64_t NumberKind = V->getValue().getLimitedValue();
277   llvm::Optional<uint64_t> OptTargetSize = GetCFNumberSize(Ctx, NumberKind);
278 
279   // FIXME: In some cases we can emit an error.
280   if (!OptTargetSize)
281     return;
282 
283   uint64_t TargetSize = *OptTargetSize;
284 
285   // Look at the value of the integer being passed by reference.  Essentially
286   // we want to catch cases where the value passed in is not equal to the
287   // size of the type being created.
288   SVal TheValueExpr = state->getSVal(CE->getArg(2), LCtx);
289 
290   // FIXME: Eventually we should handle arbitrary locations.  We can do this
291   //  by having an enhanced memory model that does low-level typing.
292   llvm::Optional<loc::MemRegionVal> LV =
293       TheValueExpr.getAs<loc::MemRegionVal>();
294   if (!LV)
295     return;
296 
297   const TypedValueRegion* R = dyn_cast<TypedValueRegion>(LV->stripCasts());
298   if (!R)
299     return;
300 
301   QualType T = Ctx.getCanonicalType(R->getValueType());
302 
303   // FIXME: If the pointee isn't an integer type, should we flag a warning?
304   //  People can do weird stuff with pointers.
305 
306   if (!T->isIntegerType())
307     return;
308 
309   uint64_t SourceSize = Ctx.getTypeSize(T);
310 
311   // CHECK: is SourceSize == TargetSize
312   if (SourceSize == TargetSize)
313     return;
314 
315   // Generate an error.  Only generate a sink if 'SourceSize < TargetSize';
316   // otherwise generate a regular node.
317   //
318   // FIXME: We can actually create an abstract "CFNumber" object that has
319   //  the bits initialized to the provided values.
320   //
321   if (ExplodedNode *N = SourceSize < TargetSize ? C.generateSink()
322                                                 : C.addTransition()) {
323     SmallString<128> sbuf;
324     llvm::raw_svector_ostream os(sbuf);
325 
326     os << (SourceSize == 8 ? "An " : "A ")
327        << SourceSize << " bit integer is used to initialize a CFNumber "
328                         "object that represents "
329        << (TargetSize == 8 ? "an " : "a ")
330        << TargetSize << " bit integer. ";
331 
332     if (SourceSize < TargetSize)
333       os << (TargetSize - SourceSize)
334       << " bits of the CFNumber value will be garbage." ;
335     else
336       os << (SourceSize - TargetSize)
337       << " bits of the input integer will be lost.";
338 
339     if (!BT)
340       BT.reset(new APIMisuse("Bad use of CFNumberCreate"));
341 
342     BugReport *report = new BugReport(*BT, os.str(), N);
343     report->addRange(CE->getArg(2)->getSourceRange());
344     C.emitReport(report);
345   }
346 }
347 
348 //===----------------------------------------------------------------------===//
349 // CFRetain/CFRelease/CFMakeCollectable checking for null arguments.
350 //===----------------------------------------------------------------------===//
351 
352 namespace {
353 class CFRetainReleaseChecker : public Checker< check::PreStmt<CallExpr> > {
354   mutable OwningPtr<APIMisuse> BT;
355   mutable IdentifierInfo *Retain, *Release, *MakeCollectable;
356 public:
357   CFRetainReleaseChecker(): Retain(0), Release(0), MakeCollectable(0) {}
358   void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
359 };
360 } // end anonymous namespace
361 
362 
363 void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
364                                           CheckerContext &C) const {
365   // If the CallExpr doesn't have exactly 1 argument just give up checking.
366   if (CE->getNumArgs() != 1)
367     return;
368 
369   ProgramStateRef state = C.getState();
370   const FunctionDecl *FD = C.getCalleeDecl(CE);
371   if (!FD)
372     return;
373 
374   if (!BT) {
375     ASTContext &Ctx = C.getASTContext();
376     Retain = &Ctx.Idents.get("CFRetain");
377     Release = &Ctx.Idents.get("CFRelease");
378     MakeCollectable = &Ctx.Idents.get("CFMakeCollectable");
379     BT.reset(
380       new APIMisuse("null passed to CFRetain/CFRelease/CFMakeCollectable"));
381   }
382 
383   // Check if we called CFRetain/CFRelease/CFMakeCollectable.
384   const IdentifierInfo *FuncII = FD->getIdentifier();
385   if (!(FuncII == Retain || FuncII == Release || FuncII == MakeCollectable))
386     return;
387 
388   // FIXME: The rest of this just checks that the argument is non-null.
389   // It should probably be refactored and combined with AttrNonNullChecker.
390 
391   // Get the argument's value.
392   const Expr *Arg = CE->getArg(0);
393   SVal ArgVal = state->getSVal(Arg, C.getLocationContext());
394   llvm::Optional<DefinedSVal> DefArgVal = ArgVal.getAs<DefinedSVal>();
395   if (!DefArgVal)
396     return;
397 
398   // Get a NULL value.
399   SValBuilder &svalBuilder = C.getSValBuilder();
400   DefinedSVal zero =
401       svalBuilder.makeZeroVal(Arg->getType()).castAs<DefinedSVal>();
402 
403   // Make an expression asserting that they're equal.
404   DefinedOrUnknownSVal ArgIsNull = svalBuilder.evalEQ(state, zero, *DefArgVal);
405 
406   // Are they equal?
407   ProgramStateRef stateTrue, stateFalse;
408   llvm::tie(stateTrue, stateFalse) = state->assume(ArgIsNull);
409 
410   if (stateTrue && !stateFalse) {
411     ExplodedNode *N = C.generateSink(stateTrue);
412     if (!N)
413       return;
414 
415     const char *description;
416     if (FuncII == Retain)
417       description = "Null pointer argument in call to CFRetain";
418     else if (FuncII == Release)
419       description = "Null pointer argument in call to CFRelease";
420     else if (FuncII == MakeCollectable)
421       description = "Null pointer argument in call to CFMakeCollectable";
422     else
423       llvm_unreachable("impossible case");
424 
425     BugReport *report = new BugReport(*BT, description, N);
426     report->addRange(Arg->getSourceRange());
427     bugreporter::trackNullOrUndefValue(N, Arg, *report);
428     C.emitReport(report);
429     return;
430   }
431 
432   // From here on, we know the argument is non-null.
433   C.addTransition(stateFalse);
434 }
435 
436 //===----------------------------------------------------------------------===//
437 // Check for sending 'retain', 'release', or 'autorelease' directly to a Class.
438 //===----------------------------------------------------------------------===//
439 
440 namespace {
441 class ClassReleaseChecker : public Checker<check::PreObjCMessage> {
442   mutable Selector releaseS;
443   mutable Selector retainS;
444   mutable Selector autoreleaseS;
445   mutable Selector drainS;
446   mutable OwningPtr<BugType> BT;
447 
448 public:
449   void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
450 };
451 }
452 
453 void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
454                                               CheckerContext &C) const {
455 
456   if (!BT) {
457     BT.reset(new APIMisuse("message incorrectly sent to class instead of class "
458                            "instance"));
459 
460     ASTContext &Ctx = C.getASTContext();
461     releaseS = GetNullarySelector("release", Ctx);
462     retainS = GetNullarySelector("retain", Ctx);
463     autoreleaseS = GetNullarySelector("autorelease", Ctx);
464     drainS = GetNullarySelector("drain", Ctx);
465   }
466 
467   if (msg.isInstanceMessage())
468     return;
469   const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
470   assert(Class);
471 
472   Selector S = msg.getSelector();
473   if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
474     return;
475 
476   if (ExplodedNode *N = C.addTransition()) {
477     SmallString<200> buf;
478     llvm::raw_svector_ostream os(buf);
479 
480     os << "The '" << S.getAsString() << "' message should be sent to instances "
481           "of class '" << Class->getName()
482        << "' and not the class directly";
483 
484     BugReport *report = new BugReport(*BT, os.str(), N);
485     report->addRange(msg.getSourceRange());
486     C.emitReport(report);
487   }
488 }
489 
490 //===----------------------------------------------------------------------===//
491 // Check for passing non-Objective-C types to variadic methods that expect
492 // only Objective-C types.
493 //===----------------------------------------------------------------------===//
494 
495 namespace {
496 class VariadicMethodTypeChecker : public Checker<check::PreObjCMessage> {
497   mutable Selector arrayWithObjectsS;
498   mutable Selector dictionaryWithObjectsAndKeysS;
499   mutable Selector setWithObjectsS;
500   mutable Selector orderedSetWithObjectsS;
501   mutable Selector initWithObjectsS;
502   mutable Selector initWithObjectsAndKeysS;
503   mutable OwningPtr<BugType> BT;
504 
505   bool isVariadicMessage(const ObjCMethodCall &msg) const;
506 
507 public:
508   void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
509 };
510 }
511 
512 /// isVariadicMessage - Returns whether the given message is a variadic message,
513 /// where all arguments must be Objective-C types.
514 bool
515 VariadicMethodTypeChecker::isVariadicMessage(const ObjCMethodCall &msg) const {
516   const ObjCMethodDecl *MD = msg.getDecl();
517 
518   if (!MD || !MD->isVariadic() || isa<ObjCProtocolDecl>(MD->getDeclContext()))
519     return false;
520 
521   Selector S = msg.getSelector();
522 
523   if (msg.isInstanceMessage()) {
524     // FIXME: Ideally we'd look at the receiver interface here, but that's not
525     // useful for init, because alloc returns 'id'. In theory, this could lead
526     // to false positives, for example if there existed a class that had an
527     // initWithObjects: implementation that does accept non-Objective-C pointer
528     // types, but the chance of that happening is pretty small compared to the
529     // gains that this analysis gives.
530     const ObjCInterfaceDecl *Class = MD->getClassInterface();
531 
532     switch (findKnownClass(Class)) {
533     case FC_NSArray:
534     case FC_NSOrderedSet:
535     case FC_NSSet:
536       return S == initWithObjectsS;
537     case FC_NSDictionary:
538       return S == initWithObjectsAndKeysS;
539     default:
540       return false;
541     }
542   } else {
543     const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
544 
545     switch (findKnownClass(Class)) {
546       case FC_NSArray:
547         return S == arrayWithObjectsS;
548       case FC_NSOrderedSet:
549         return S == orderedSetWithObjectsS;
550       case FC_NSSet:
551         return S == setWithObjectsS;
552       case FC_NSDictionary:
553         return S == dictionaryWithObjectsAndKeysS;
554       default:
555         return false;
556     }
557   }
558 }
559 
560 void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
561                                                     CheckerContext &C) const {
562   if (!BT) {
563     BT.reset(new APIMisuse("Arguments passed to variadic method aren't all "
564                            "Objective-C pointer types"));
565 
566     ASTContext &Ctx = C.getASTContext();
567     arrayWithObjectsS = GetUnarySelector("arrayWithObjects", Ctx);
568     dictionaryWithObjectsAndKeysS =
569       GetUnarySelector("dictionaryWithObjectsAndKeys", Ctx);
570     setWithObjectsS = GetUnarySelector("setWithObjects", Ctx);
571     orderedSetWithObjectsS = GetUnarySelector("orderedSetWithObjects", Ctx);
572 
573     initWithObjectsS = GetUnarySelector("initWithObjects", Ctx);
574     initWithObjectsAndKeysS = GetUnarySelector("initWithObjectsAndKeys", Ctx);
575   }
576 
577   if (!isVariadicMessage(msg))
578       return;
579 
580   // We are not interested in the selector arguments since they have
581   // well-defined types, so the compiler will issue a warning for them.
582   unsigned variadicArgsBegin = msg.getSelector().getNumArgs();
583 
584   // We're not interested in the last argument since it has to be nil or the
585   // compiler would have issued a warning for it elsewhere.
586   unsigned variadicArgsEnd = msg.getNumArgs() - 1;
587 
588   if (variadicArgsEnd <= variadicArgsBegin)
589     return;
590 
591   // Verify that all arguments have Objective-C types.
592   llvm::Optional<ExplodedNode*> errorNode;
593   ProgramStateRef state = C.getState();
594 
595   for (unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) {
596     QualType ArgTy = msg.getArgExpr(I)->getType();
597     if (ArgTy->isObjCObjectPointerType())
598       continue;
599 
600     // Block pointers are treaded as Objective-C pointers.
601     if (ArgTy->isBlockPointerType())
602       continue;
603 
604     // Ignore pointer constants.
605     if (msg.getArgSVal(I).getAs<loc::ConcreteInt>())
606       continue;
607 
608     // Ignore pointer types annotated with 'NSObject' attribute.
609     if (C.getASTContext().isObjCNSObjectType(ArgTy))
610       continue;
611 
612     // Ignore CF references, which can be toll-free bridged.
613     if (coreFoundation::isCFObjectRef(ArgTy))
614       continue;
615 
616     // Generate only one error node to use for all bug reports.
617     if (!errorNode.hasValue())
618       errorNode = C.addTransition();
619 
620     if (!errorNode.getValue())
621       continue;
622 
623     SmallString<128> sbuf;
624     llvm::raw_svector_ostream os(sbuf);
625 
626     StringRef TypeName = GetReceiverInterfaceName(msg);
627     if (!TypeName.empty())
628       os << "Argument to '" << TypeName << "' method '";
629     else
630       os << "Argument to method '";
631 
632     os << msg.getSelector().getAsString()
633        << "' should be an Objective-C pointer type, not '";
634     ArgTy.print(os, C.getLangOpts());
635     os << "'";
636 
637     BugReport *R = new BugReport(*BT, os.str(), errorNode.getValue());
638     R->addRange(msg.getArgSourceRange(I));
639     C.emitReport(R);
640   }
641 }
642 
643 //===----------------------------------------------------------------------===//
644 // Improves the modeling of loops over Cocoa collections.
645 //===----------------------------------------------------------------------===//
646 
647 namespace {
648 class ObjCLoopChecker
649   : public Checker<check::PostStmt<ObjCForCollectionStmt> > {
650 
651 public:
652   void checkPostStmt(const ObjCForCollectionStmt *FCS, CheckerContext &C) const;
653 };
654 }
655 
656 static bool isKnownNonNilCollectionType(QualType T) {
657   const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
658   if (!PT)
659     return false;
660 
661   const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
662   if (!ID)
663     return false;
664 
665   switch (findKnownClass(ID)) {
666   case FC_NSArray:
667   case FC_NSDictionary:
668   case FC_NSEnumerator:
669   case FC_NSOrderedSet:
670   case FC_NSSet:
671     return true;
672   default:
673     return false;
674   }
675 }
676 
677 void ObjCLoopChecker::checkPostStmt(const ObjCForCollectionStmt *FCS,
678                                     CheckerContext &C) const {
679   ProgramStateRef State = C.getState();
680 
681   // Check if this is the branch for the end of the loop.
682   SVal CollectionSentinel = State->getSVal(FCS, C.getLocationContext());
683   if (CollectionSentinel.isZeroConstant())
684     return;
685 
686   // See if the collection is one where we /know/ the elements are non-nil.
687   const Expr *Collection = FCS->getCollection();
688   if (!isKnownNonNilCollectionType(Collection->getType()))
689     return;
690 
691   // FIXME: Copied from ExprEngineObjC.
692   const Stmt *Element = FCS->getElement();
693   SVal ElementVar;
694   if (const DeclStmt *DS = dyn_cast<DeclStmt>(Element)) {
695     const VarDecl *ElemDecl = cast<VarDecl>(DS->getSingleDecl());
696     assert(ElemDecl->getInit() == 0);
697     ElementVar = State->getLValue(ElemDecl, C.getLocationContext());
698   } else {
699     ElementVar = State->getSVal(Element, C.getLocationContext());
700   }
701 
702   if (!ElementVar.getAs<Loc>())
703     return;
704 
705   // Go ahead and assume the value is non-nil.
706   SVal Val = State->getSVal(ElementVar.castAs<Loc>());
707   State = State->assume(Val.castAs<DefinedOrUnknownSVal>(), true);
708   C.addTransition(State);
709 }
710 
711 namespace {
712 /// \class ObjCNonNilReturnValueChecker
713 /// \brief The checker restricts the return values of APIs known to
714 /// never (or almost never) return 'nil'.
715 class ObjCNonNilReturnValueChecker
716   : public Checker<check::PostObjCMessage> {
717     mutable bool Initialized;
718     mutable Selector ObjectAtIndex;
719     mutable Selector ObjectAtIndexedSubscript;
720 
721 public:
722   ObjCNonNilReturnValueChecker() : Initialized(false) {}
723   void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
724 };
725 }
726 
727 static ProgramStateRef assumeExprIsNonNull(const Expr *NonNullExpr,
728                                            ProgramStateRef State,
729                                            CheckerContext &C) {
730   SVal Val = State->getSVal(NonNullExpr, C.getLocationContext());
731   if (llvm::Optional<DefinedOrUnknownSVal> DV =
732           Val.getAs<DefinedOrUnknownSVal>())
733     return State->assume(*DV, true);
734   return State;
735 }
736 
737 void ObjCNonNilReturnValueChecker::checkPostObjCMessage(const ObjCMethodCall &M,
738                                                         CheckerContext &C)
739                                                         const {
740   ProgramStateRef State = C.getState();
741 
742   if (!Initialized) {
743     ASTContext &Ctx = C.getASTContext();
744     ObjectAtIndex = GetUnarySelector("objectAtIndex", Ctx);
745     ObjectAtIndexedSubscript = GetUnarySelector("objectAtIndexedSubscript", Ctx);
746   }
747 
748   // Check the receiver type.
749   if (const ObjCInterfaceDecl *Interface = M.getReceiverInterface()) {
750 
751     // Assume that object returned from '[self init]' or '[super init]' is not
752     // 'nil' if we are processing an inlined function/method.
753     //
754     // A defensive callee will (and should) check if the object returned by
755     // '[super init]' is 'nil' before doing it's own initialization. However,
756     // since 'nil' is rarely returned in practice, we should not warn when the
757     // caller to the defensive constructor uses the object in contexts where
758     // 'nil' is not accepted.
759     if (!C.inTopFrame() && M.getDecl() &&
760         M.getDecl()->getMethodFamily() == OMF_init &&
761         M.isReceiverSelfOrSuper()) {
762       State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
763     }
764 
765     // Objects returned from
766     // [NSArray|NSOrderedSet]::[ObjectAtIndex|ObjectAtIndexedSubscript]
767     // are never 'nil'.
768     FoundationClass Cl = findKnownClass(Interface);
769     if (Cl == FC_NSArray || Cl == FC_NSOrderedSet) {
770       Selector Sel = M.getSelector();
771       if (Sel == ObjectAtIndex || Sel == ObjectAtIndexedSubscript) {
772         // Go ahead and assume the value is non-nil.
773         State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
774       }
775     }
776   }
777   C.addTransition(State);
778 }
779 
780 //===----------------------------------------------------------------------===//
781 // Check registration.
782 //===----------------------------------------------------------------------===//
783 
784 void ento::registerNilArgChecker(CheckerManager &mgr) {
785   mgr.registerChecker<NilArgChecker>();
786 }
787 
788 void ento::registerCFNumberCreateChecker(CheckerManager &mgr) {
789   mgr.registerChecker<CFNumberCreateChecker>();
790 }
791 
792 void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
793   mgr.registerChecker<CFRetainReleaseChecker>();
794 }
795 
796 void ento::registerClassReleaseChecker(CheckerManager &mgr) {
797   mgr.registerChecker<ClassReleaseChecker>();
798 }
799 
800 void ento::registerVariadicMethodTypeChecker(CheckerManager &mgr) {
801   mgr.registerChecker<VariadicMethodTypeChecker>();
802 }
803 
804 void ento::registerObjCLoopChecker(CheckerManager &mgr) {
805   mgr.registerChecker<ObjCLoopChecker>();
806 }
807 
808 void ento::registerObjCNonNilReturnValueChecker(CheckerManager &mgr) {
809   mgr.registerChecker<ObjCNonNilReturnValueChecker>();
810 }
811