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