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