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