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