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 isa<loc::ConcreteInt>(X);
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 namespace {
200   template<typename T>
201   class Optional {
202     bool IsKnown;
203     T Val;
204   public:
205     Optional() : IsKnown(false), Val(0) {}
206     Optional(const T& val) : IsKnown(true), Val(val) {}
207 
208     bool isKnown() const { return IsKnown; }
209 
210     const T& getValue() const {
211       assert (isKnown());
212       return Val;
213     }
214 
215     operator const T&() const {
216       return getValue();
217     }
218   };
219 }
220 
221 static Optional<uint64_t> GetCFNumberSize(ASTContext &Ctx, uint64_t i) {
222   static const unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 };
223 
224   if (i < kCFNumberCharType)
225     return FixedSize[i-1];
226 
227   QualType T;
228 
229   switch (i) {
230     case kCFNumberCharType:     T = Ctx.CharTy;     break;
231     case kCFNumberShortType:    T = Ctx.ShortTy;    break;
232     case kCFNumberIntType:      T = Ctx.IntTy;      break;
233     case kCFNumberLongType:     T = Ctx.LongTy;     break;
234     case kCFNumberLongLongType: T = Ctx.LongLongTy; break;
235     case kCFNumberFloatType:    T = Ctx.FloatTy;    break;
236     case kCFNumberDoubleType:   T = Ctx.DoubleTy;   break;
237     case kCFNumberCFIndexType:
238     case kCFNumberNSIntegerType:
239     case kCFNumberCGFloatType:
240       // FIXME: We need a way to map from names to Type*.
241     default:
242       return Optional<uint64_t>();
243   }
244 
245   return Ctx.getTypeSize(T);
246 }
247 
248 #if 0
249 static const char* GetCFNumberTypeStr(uint64_t i) {
250   static const char* Names[] = {
251     "kCFNumberSInt8Type",
252     "kCFNumberSInt16Type",
253     "kCFNumberSInt32Type",
254     "kCFNumberSInt64Type",
255     "kCFNumberFloat32Type",
256     "kCFNumberFloat64Type",
257     "kCFNumberCharType",
258     "kCFNumberShortType",
259     "kCFNumberIntType",
260     "kCFNumberLongType",
261     "kCFNumberLongLongType",
262     "kCFNumberFloatType",
263     "kCFNumberDoubleType",
264     "kCFNumberCFIndexType",
265     "kCFNumberNSIntegerType",
266     "kCFNumberCGFloatType"
267   };
268 
269   return i <= kCFNumberCGFloatType ? Names[i-1] : "Invalid CFNumberType";
270 }
271 #endif
272 
273 void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
274                                          CheckerContext &C) const {
275   ProgramStateRef state = C.getState();
276   const FunctionDecl *FD = C.getCalleeDecl(CE);
277   if (!FD)
278     return;
279 
280   ASTContext &Ctx = C.getASTContext();
281   if (!II)
282     II = &Ctx.Idents.get("CFNumberCreate");
283 
284   if (FD->getIdentifier() != II || CE->getNumArgs() != 3)
285     return;
286 
287   // Get the value of the "theType" argument.
288   const LocationContext *LCtx = C.getLocationContext();
289   SVal TheTypeVal = state->getSVal(CE->getArg(1), LCtx);
290 
291   // FIXME: We really should allow ranges of valid theType values, and
292   //   bifurcate the state appropriately.
293   nonloc::ConcreteInt* V = dyn_cast<nonloc::ConcreteInt>(&TheTypeVal);
294   if (!V)
295     return;
296 
297   uint64_t NumberKind = V->getValue().getLimitedValue();
298   Optional<uint64_t> TargetSize = GetCFNumberSize(Ctx, NumberKind);
299 
300   // FIXME: In some cases we can emit an error.
301   if (!TargetSize.isKnown())
302     return;
303 
304   // Look at the value of the integer being passed by reference.  Essentially
305   // we want to catch cases where the value passed in is not equal to the
306   // size of the type being created.
307   SVal TheValueExpr = state->getSVal(CE->getArg(2), LCtx);
308 
309   // FIXME: Eventually we should handle arbitrary locations.  We can do this
310   //  by having an enhanced memory model that does low-level typing.
311   loc::MemRegionVal* LV = dyn_cast<loc::MemRegionVal>(&TheValueExpr);
312   if (!LV)
313     return;
314 
315   const TypedValueRegion* R = dyn_cast<TypedValueRegion>(LV->stripCasts());
316   if (!R)
317     return;
318 
319   QualType T = Ctx.getCanonicalType(R->getValueType());
320 
321   // FIXME: If the pointee isn't an integer type, should we flag a warning?
322   //  People can do weird stuff with pointers.
323 
324   if (!T->isIntegerType())
325     return;
326 
327   uint64_t SourceSize = Ctx.getTypeSize(T);
328 
329   // CHECK: is SourceSize == TargetSize
330   if (SourceSize == TargetSize)
331     return;
332 
333   // Generate an error.  Only generate a sink if 'SourceSize < TargetSize';
334   // otherwise generate a regular node.
335   //
336   // FIXME: We can actually create an abstract "CFNumber" object that has
337   //  the bits initialized to the provided values.
338   //
339   if (ExplodedNode *N = SourceSize < TargetSize ? C.generateSink()
340                                                 : C.addTransition()) {
341     SmallString<128> sbuf;
342     llvm::raw_svector_ostream os(sbuf);
343 
344     os << (SourceSize == 8 ? "An " : "A ")
345        << SourceSize << " bit integer is used to initialize a CFNumber "
346                         "object that represents "
347        << (TargetSize == 8 ? "an " : "a ")
348        << TargetSize << " bit integer. ";
349 
350     if (SourceSize < TargetSize)
351       os << (TargetSize - SourceSize)
352       << " bits of the CFNumber value will be garbage." ;
353     else
354       os << (SourceSize - TargetSize)
355       << " bits of the input integer will be lost.";
356 
357     if (!BT)
358       BT.reset(new APIMisuse("Bad use of CFNumberCreate"));
359 
360     BugReport *report = new BugReport(*BT, os.str(), N);
361     report->addRange(CE->getArg(2)->getSourceRange());
362     C.emitReport(report);
363   }
364 }
365 
366 //===----------------------------------------------------------------------===//
367 // CFRetain/CFRelease/CFMakeCollectable checking for null arguments.
368 //===----------------------------------------------------------------------===//
369 
370 namespace {
371 class CFRetainReleaseChecker : public Checker< check::PreStmt<CallExpr> > {
372   mutable OwningPtr<APIMisuse> BT;
373   mutable IdentifierInfo *Retain, *Release, *MakeCollectable;
374 public:
375   CFRetainReleaseChecker(): Retain(0), Release(0), MakeCollectable(0) {}
376   void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
377 };
378 } // end anonymous namespace
379 
380 
381 void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
382                                           CheckerContext &C) const {
383   // If the CallExpr doesn't have exactly 1 argument just give up checking.
384   if (CE->getNumArgs() != 1)
385     return;
386 
387   ProgramStateRef state = C.getState();
388   const FunctionDecl *FD = C.getCalleeDecl(CE);
389   if (!FD)
390     return;
391 
392   if (!BT) {
393     ASTContext &Ctx = C.getASTContext();
394     Retain = &Ctx.Idents.get("CFRetain");
395     Release = &Ctx.Idents.get("CFRelease");
396     MakeCollectable = &Ctx.Idents.get("CFMakeCollectable");
397     BT.reset(
398       new APIMisuse("null passed to CFRetain/CFRelease/CFMakeCollectable"));
399   }
400 
401   // Check if we called CFRetain/CFRelease/CFMakeCollectable.
402   const IdentifierInfo *FuncII = FD->getIdentifier();
403   if (!(FuncII == Retain || FuncII == Release || FuncII == MakeCollectable))
404     return;
405 
406   // FIXME: The rest of this just checks that the argument is non-null.
407   // It should probably be refactored and combined with AttrNonNullChecker.
408 
409   // Get the argument's value.
410   const Expr *Arg = CE->getArg(0);
411   SVal ArgVal = state->getSVal(Arg, C.getLocationContext());
412   DefinedSVal *DefArgVal = dyn_cast<DefinedSVal>(&ArgVal);
413   if (!DefArgVal)
414     return;
415 
416   // Get a NULL value.
417   SValBuilder &svalBuilder = C.getSValBuilder();
418   DefinedSVal zero = cast<DefinedSVal>(svalBuilder.makeZeroVal(Arg->getType()));
419 
420   // Make an expression asserting that they're equal.
421   DefinedOrUnknownSVal ArgIsNull = svalBuilder.evalEQ(state, zero, *DefArgVal);
422 
423   // Are they equal?
424   ProgramStateRef stateTrue, stateFalse;
425   llvm::tie(stateTrue, stateFalse) = state->assume(ArgIsNull);
426 
427   if (stateTrue && !stateFalse) {
428     ExplodedNode *N = C.generateSink(stateTrue);
429     if (!N)
430       return;
431 
432     const char *description;
433     if (FuncII == Retain)
434       description = "Null pointer argument in call to CFRetain";
435     else if (FuncII == Release)
436       description = "Null pointer argument in call to CFRelease";
437     else if (FuncII == MakeCollectable)
438       description = "Null pointer argument in call to CFMakeCollectable";
439     else
440       llvm_unreachable("impossible case");
441 
442     BugReport *report = new BugReport(*BT, description, N);
443     report->addRange(Arg->getSourceRange());
444     bugreporter::trackNullOrUndefValue(N, Arg, *report);
445     C.emitReport(report);
446     return;
447   }
448 
449   // From here on, we know the argument is non-null.
450   C.addTransition(stateFalse);
451 }
452 
453 //===----------------------------------------------------------------------===//
454 // Check for sending 'retain', 'release', or 'autorelease' directly to a Class.
455 //===----------------------------------------------------------------------===//
456 
457 namespace {
458 class ClassReleaseChecker : public Checker<check::PreObjCMessage> {
459   mutable Selector releaseS;
460   mutable Selector retainS;
461   mutable Selector autoreleaseS;
462   mutable Selector drainS;
463   mutable OwningPtr<BugType> BT;
464 
465 public:
466   void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
467 };
468 }
469 
470 void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
471                                               CheckerContext &C) const {
472 
473   if (!BT) {
474     BT.reset(new APIMisuse("message incorrectly sent to class instead of class "
475                            "instance"));
476 
477     ASTContext &Ctx = C.getASTContext();
478     releaseS = GetNullarySelector("release", Ctx);
479     retainS = GetNullarySelector("retain", Ctx);
480     autoreleaseS = GetNullarySelector("autorelease", Ctx);
481     drainS = GetNullarySelector("drain", Ctx);
482   }
483 
484   if (msg.isInstanceMessage())
485     return;
486   const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
487   assert(Class);
488 
489   Selector S = msg.getSelector();
490   if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
491     return;
492 
493   if (ExplodedNode *N = C.addTransition()) {
494     SmallString<200> buf;
495     llvm::raw_svector_ostream os(buf);
496 
497     os << "The '" << S.getAsString() << "' message should be sent to instances "
498           "of class '" << Class->getName()
499        << "' and not the class directly";
500 
501     BugReport *report = new BugReport(*BT, os.str(), N);
502     report->addRange(msg.getSourceRange());
503     C.emitReport(report);
504   }
505 }
506 
507 //===----------------------------------------------------------------------===//
508 // Check for passing non-Objective-C types to variadic methods that expect
509 // only Objective-C types.
510 //===----------------------------------------------------------------------===//
511 
512 namespace {
513 class VariadicMethodTypeChecker : public Checker<check::PreObjCMessage> {
514   mutable Selector arrayWithObjectsS;
515   mutable Selector dictionaryWithObjectsAndKeysS;
516   mutable Selector setWithObjectsS;
517   mutable Selector orderedSetWithObjectsS;
518   mutable Selector initWithObjectsS;
519   mutable Selector initWithObjectsAndKeysS;
520   mutable OwningPtr<BugType> BT;
521 
522   bool isVariadicMessage(const ObjCMethodCall &msg) const;
523 
524 public:
525   void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
526 };
527 }
528 
529 /// isVariadicMessage - Returns whether the given message is a variadic message,
530 /// where all arguments must be Objective-C types.
531 bool
532 VariadicMethodTypeChecker::isVariadicMessage(const ObjCMethodCall &msg) const {
533   const ObjCMethodDecl *MD = msg.getDecl();
534 
535   if (!MD || !MD->isVariadic() || isa<ObjCProtocolDecl>(MD->getDeclContext()))
536     return false;
537 
538   Selector S = msg.getSelector();
539 
540   if (msg.isInstanceMessage()) {
541     // FIXME: Ideally we'd look at the receiver interface here, but that's not
542     // useful for init, because alloc returns 'id'. In theory, this could lead
543     // to false positives, for example if there existed a class that had an
544     // initWithObjects: implementation that does accept non-Objective-C pointer
545     // types, but the chance of that happening is pretty small compared to the
546     // gains that this analysis gives.
547     const ObjCInterfaceDecl *Class = MD->getClassInterface();
548 
549     switch (findKnownClass(Class)) {
550     case FC_NSArray:
551     case FC_NSOrderedSet:
552     case FC_NSSet:
553       return S == initWithObjectsS;
554     case FC_NSDictionary:
555       return S == initWithObjectsAndKeysS;
556     default:
557       return false;
558     }
559   } else {
560     const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
561 
562     switch (findKnownClass(Class)) {
563       case FC_NSArray:
564         return S == arrayWithObjectsS;
565       case FC_NSOrderedSet:
566         return S == orderedSetWithObjectsS;
567       case FC_NSSet:
568         return S == setWithObjectsS;
569       case FC_NSDictionary:
570         return S == dictionaryWithObjectsAndKeysS;
571       default:
572         return false;
573     }
574   }
575 }
576 
577 void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
578                                                     CheckerContext &C) const {
579   if (!BT) {
580     BT.reset(new APIMisuse("Arguments passed to variadic method aren't all "
581                            "Objective-C pointer types"));
582 
583     ASTContext &Ctx = C.getASTContext();
584     arrayWithObjectsS = GetUnarySelector("arrayWithObjects", Ctx);
585     dictionaryWithObjectsAndKeysS =
586       GetUnarySelector("dictionaryWithObjectsAndKeys", Ctx);
587     setWithObjectsS = GetUnarySelector("setWithObjects", Ctx);
588     orderedSetWithObjectsS = GetUnarySelector("orderedSetWithObjects", Ctx);
589 
590     initWithObjectsS = GetUnarySelector("initWithObjects", Ctx);
591     initWithObjectsAndKeysS = GetUnarySelector("initWithObjectsAndKeys", Ctx);
592   }
593 
594   if (!isVariadicMessage(msg))
595       return;
596 
597   // We are not interested in the selector arguments since they have
598   // well-defined types, so the compiler will issue a warning for them.
599   unsigned variadicArgsBegin = msg.getSelector().getNumArgs();
600 
601   // We're not interested in the last argument since it has to be nil or the
602   // compiler would have issued a warning for it elsewhere.
603   unsigned variadicArgsEnd = msg.getNumArgs() - 1;
604 
605   if (variadicArgsEnd <= variadicArgsBegin)
606     return;
607 
608   // Verify that all arguments have Objective-C types.
609   llvm::Optional<ExplodedNode*> errorNode;
610   ProgramStateRef state = C.getState();
611 
612   for (unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) {
613     QualType ArgTy = msg.getArgExpr(I)->getType();
614     if (ArgTy->isObjCObjectPointerType())
615       continue;
616 
617     // Block pointers are treaded as Objective-C pointers.
618     if (ArgTy->isBlockPointerType())
619       continue;
620 
621     // Ignore pointer constants.
622     if (isa<loc::ConcreteInt>(msg.getArgSVal(I)))
623       continue;
624 
625     // Ignore pointer types annotated with 'NSObject' attribute.
626     if (C.getASTContext().isObjCNSObjectType(ArgTy))
627       continue;
628 
629     // Ignore CF references, which can be toll-free bridged.
630     if (coreFoundation::isCFObjectRef(ArgTy))
631       continue;
632 
633     // Generate only one error node to use for all bug reports.
634     if (!errorNode.hasValue())
635       errorNode = C.addTransition();
636 
637     if (!errorNode.getValue())
638       continue;
639 
640     SmallString<128> sbuf;
641     llvm::raw_svector_ostream os(sbuf);
642 
643     StringRef TypeName = GetReceiverInterfaceName(msg);
644     if (!TypeName.empty())
645       os << "Argument to '" << TypeName << "' method '";
646     else
647       os << "Argument to method '";
648 
649     os << msg.getSelector().getAsString()
650        << "' should be an Objective-C pointer type, not '";
651     ArgTy.print(os, C.getLangOpts());
652     os << "'";
653 
654     BugReport *R = new BugReport(*BT, os.str(), errorNode.getValue());
655     R->addRange(msg.getArgSourceRange(I));
656     C.emitReport(R);
657   }
658 }
659 
660 //===----------------------------------------------------------------------===//
661 // Improves the modeling of loops over Cocoa collections.
662 //===----------------------------------------------------------------------===//
663 
664 namespace {
665 class ObjCLoopChecker
666   : public Checker<check::PostStmt<ObjCForCollectionStmt> > {
667 
668 public:
669   void checkPostStmt(const ObjCForCollectionStmt *FCS, CheckerContext &C) const;
670 };
671 }
672 
673 static bool isKnownNonNilCollectionType(QualType T) {
674   const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
675   if (!PT)
676     return false;
677 
678   const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
679   if (!ID)
680     return false;
681 
682   switch (findKnownClass(ID)) {
683   case FC_NSArray:
684   case FC_NSDictionary:
685   case FC_NSEnumerator:
686   case FC_NSOrderedSet:
687   case FC_NSSet:
688     return true;
689   default:
690     return false;
691   }
692 }
693 
694 void ObjCLoopChecker::checkPostStmt(const ObjCForCollectionStmt *FCS,
695                                     CheckerContext &C) const {
696   ProgramStateRef State = C.getState();
697 
698   // Check if this is the branch for the end of the loop.
699   SVal CollectionSentinel = State->getSVal(FCS, C.getLocationContext());
700   if (CollectionSentinel.isZeroConstant())
701     return;
702 
703   // See if the collection is one where we /know/ the elements are non-nil.
704   const Expr *Collection = FCS->getCollection();
705   if (!isKnownNonNilCollectionType(Collection->getType()))
706     return;
707 
708   // FIXME: Copied from ExprEngineObjC.
709   const Stmt *Element = FCS->getElement();
710   SVal ElementVar;
711   if (const DeclStmt *DS = dyn_cast<DeclStmt>(Element)) {
712     const VarDecl *ElemDecl = cast<VarDecl>(DS->getSingleDecl());
713     assert(ElemDecl->getInit() == 0);
714     ElementVar = State->getLValue(ElemDecl, C.getLocationContext());
715   } else {
716     ElementVar = State->getSVal(Element, C.getLocationContext());
717   }
718 
719   if (!isa<Loc>(ElementVar))
720     return;
721 
722   // Go ahead and assume the value is non-nil.
723   SVal Val = State->getSVal(cast<Loc>(ElementVar));
724   State = State->assume(cast<DefinedOrUnknownSVal>(Val), true);
725   C.addTransition(State);
726 }
727 
728 namespace {
729 /// \class ObjCNonNilReturnValueChecker
730 /// \brief The checker restricts the return values of APIs known to
731 /// never (or almost never) return 'nil'.
732 class ObjCNonNilReturnValueChecker
733   : public Checker<check::PostObjCMessage> {
734     mutable bool Initialized;
735     mutable Selector ObjectAtIndex;
736     mutable Selector ObjectAtIndexedSubscript;
737 
738 public:
739   ObjCNonNilReturnValueChecker() : Initialized(false) {}
740   void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
741 };
742 }
743 
744 static ProgramStateRef assumeExprIsNonNull(const Expr *NonNullExpr,
745                                            ProgramStateRef State,
746                                            CheckerContext &C) {
747   SVal Val = State->getSVal(NonNullExpr, C.getLocationContext());
748   if (DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&Val))
749     return State->assume(*DV, true);
750   return State;
751 }
752 
753 void ObjCNonNilReturnValueChecker::checkPostObjCMessage(const ObjCMethodCall &M,
754                                                         CheckerContext &C)
755                                                         const {
756   ProgramStateRef State = C.getState();
757 
758   if (!Initialized) {
759     ASTContext &Ctx = C.getASTContext();
760     ObjectAtIndex = GetUnarySelector("objectAtIndex", Ctx);
761     ObjectAtIndexedSubscript = GetUnarySelector("objectAtIndexedSubscript", Ctx);
762   }
763 
764   // Check the receiver type.
765   if (const ObjCInterfaceDecl *Interface = M.getReceiverInterface()) {
766 
767     // Assume that object returned from '[self init]' or '[super init]' is not
768     // 'nil' if we are processing an inlined function/method.
769     //
770     // A defensive callee will (and should) check if the object returned by
771     // '[super init]' is 'nil' before doing it's own initialization. However,
772     // since 'nil' is rarely returned in practice, we should not warn when the
773     // caller to the defensive constructor uses the object in contexts where
774     // 'nil' is not accepted.
775     if (!C.inTopFrame() && M.getDecl() &&
776         M.getDecl()->getMethodFamily() == OMF_init &&
777         M.isReceiverSelfOrSuper()) {
778       State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
779     }
780 
781     // Objects returned from
782     // [NSArray|NSOrderedSet]::[ObjectAtIndex|ObjectAtIndexedSubscript]
783     // are never 'nil'.
784     FoundationClass Cl = findKnownClass(Interface);
785     if (Cl == FC_NSArray || Cl == FC_NSOrderedSet) {
786       Selector Sel = M.getSelector();
787       if (Sel == ObjectAtIndex || Sel == ObjectAtIndexedSubscript) {
788         // Go ahead and assume the value is non-nil.
789         State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
790       }
791     }
792   }
793   C.addTransition(State);
794 }
795 
796 //===----------------------------------------------------------------------===//
797 // Check registration.
798 //===----------------------------------------------------------------------===//
799 
800 void ento::registerNilArgChecker(CheckerManager &mgr) {
801   mgr.registerChecker<NilArgChecker>();
802 }
803 
804 void ento::registerCFNumberCreateChecker(CheckerManager &mgr) {
805   mgr.registerChecker<CFNumberCreateChecker>();
806 }
807 
808 void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
809   mgr.registerChecker<CFRetainReleaseChecker>();
810 }
811 
812 void ento::registerClassReleaseChecker(CheckerManager &mgr) {
813   mgr.registerChecker<ClassReleaseChecker>();
814 }
815 
816 void ento::registerVariadicMethodTypeChecker(CheckerManager &mgr) {
817   mgr.registerChecker<VariadicMethodTypeChecker>();
818 }
819 
820 void ento::registerObjCLoopChecker(CheckerManager &mgr) {
821   mgr.registerChecker<ObjCLoopChecker>();
822 }
823 
824 void ento::registerObjCNonNilReturnValueChecker(CheckerManager &mgr) {
825   mgr.registerChecker<ObjCNonNilReturnValueChecker>();
826 }
827