clang  3.9.0
BasicObjCFoundationChecks.cpp
Go to the documentation of this file.
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"
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 
67 };
68 
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 {
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);
212  C.emitReport(std::move(R));
213 }
214 
215 void NilArgChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
216  CheckerContext &C) const {
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 // Error reporting.
340 //===----------------------------------------------------------------------===//
341 
342 namespace {
343 class CFNumberCreateChecker : public Checker< check::PreStmt<CallExpr> > {
344  mutable std::unique_ptr<APIMisuse> BT;
345  mutable IdentifierInfo* II;
346 public:
347  CFNumberCreateChecker() : II(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 
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;
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 CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
429  CheckerContext &C) const {
431  const FunctionDecl *FD = C.getCalleeDecl(CE);
432  if (!FD)
433  return;
434 
435  ASTContext &Ctx = C.getASTContext();
436  if (!II)
437  II = &Ctx.Idents.get("CFNumberCreate");
438 
439  if (FD->getIdentifier() != II || CE->getNumArgs() != 3)
440  return;
441 
442  // Get the value of the "theType" argument.
443  const LocationContext *LCtx = C.getLocationContext();
444  SVal TheTypeVal = state->getSVal(CE->getArg(1), LCtx);
445 
446  // FIXME: We really should allow ranges of valid theType values, and
447  // bifurcate the state appropriately.
448  Optional<nonloc::ConcreteInt> V = TheTypeVal.getAs<nonloc::ConcreteInt>();
449  if (!V)
450  return;
451 
452  uint64_t NumberKind = V->getValue().getLimitedValue();
453  Optional<uint64_t> OptTargetSize = GetCFNumberSize(Ctx, NumberKind);
454 
455  // FIXME: In some cases we can emit an error.
456  if (!OptTargetSize)
457  return;
458 
459  uint64_t TargetSize = *OptTargetSize;
460 
461  // Look at the value of the integer being passed by reference. Essentially
462  // we want to catch cases where the value passed in is not equal to the
463  // size of the type being created.
464  SVal TheValueExpr = state->getSVal(CE->getArg(2), LCtx);
465 
466  // FIXME: Eventually we should handle arbitrary locations. We can do this
467  // by having an enhanced memory model that does low-level typing.
468  Optional<loc::MemRegionVal> LV = TheValueExpr.getAs<loc::MemRegionVal>();
469  if (!LV)
470  return;
471 
472  const TypedValueRegion* R = dyn_cast<TypedValueRegion>(LV->stripCasts());
473  if (!R)
474  return;
475 
476  QualType T = Ctx.getCanonicalType(R->getValueType());
477 
478  // FIXME: If the pointee isn't an integer type, should we flag a warning?
479  // People can do weird stuff with pointers.
480 
481  if (!T->isIntegralOrEnumerationType())
482  return;
483 
484  uint64_t SourceSize = Ctx.getTypeSize(T);
485 
486  // CHECK: is SourceSize == TargetSize
487  if (SourceSize == TargetSize)
488  return;
489 
490  // Generate an error. Only generate a sink error node
491  // if 'SourceSize < TargetSize'; otherwise generate a non-fatal error node.
492  //
493  // FIXME: We can actually create an abstract "CFNumber" object that has
494  // the bits initialized to the provided values.
495  //
496  ExplodedNode *N = SourceSize < TargetSize ? C.generateErrorNode()
498  if (N) {
499  SmallString<128> sbuf;
500  llvm::raw_svector_ostream os(sbuf);
501 
502  os << (SourceSize == 8 ? "An " : "A ")
503  << SourceSize << " bit integer is used to initialize a CFNumber "
504  "object that represents "
505  << (TargetSize == 8 ? "an " : "a ")
506  << TargetSize << " bit integer. ";
507 
508  if (SourceSize < TargetSize)
509  os << (TargetSize - SourceSize)
510  << " bits of the CFNumber value will be garbage." ;
511  else
512  os << (SourceSize - TargetSize)
513  << " bits of the input integer will be lost.";
514 
515  if (!BT)
516  BT.reset(new APIMisuse(this, "Bad use of CFNumberCreate"));
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 = state->getSVal(Arg, C.getLocationContext());
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 
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.
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.
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 
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.
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.
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.
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
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
974  const ObjCForCollectionStmt *FCS,
975  bool Assumption) {
976  if (!State)
977  return nullptr;
978 
979  SymbolRef CollectionS =
980  State->getSVal(FCS->getCollection(), C.getLocationContext()).getAsSymbol();
981  return assumeCollectionNonEmpty(C, State, CollectionS, Assumption);
982 }
983 
984 /// If the fist block edge is a back edge, we are reentering the loop.
986  const ObjCForCollectionStmt *FCS) {
987  if (!N)
988  return false;
989 
990  ProgramPoint P = N->getLocation();
991  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
992  return BE->getSrc()->getLoopTarget() == FCS;
993  }
994 
995  // Keep looking for a block edge.
997  E = N->pred_end(); I != E; ++I) {
999  return true;
1000  }
1001 
1002  return false;
1003 }
1004 
1005 void ObjCLoopChecker::checkPostStmt(const ObjCForCollectionStmt *FCS,
1006  CheckerContext &C) const {
1007  ProgramStateRef State = C.getState();
1008 
1009  // Check if this is the branch for the end of the loop.
1010  SVal CollectionSentinel = C.getSVal(FCS);
1011  if (CollectionSentinel.isZeroConstant()) {
1013  State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/false);
1014 
1015  // Otherwise, this is a branch that goes through the loop body.
1016  } else {
1017  State = checkCollectionNonNil(C, State, FCS);
1018  State = checkElementNonNil(C, State, FCS);
1019  State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/true);
1020  }
1021 
1022  if (!State)
1023  C.generateSink(C.getState(), C.getPredecessor());
1024  else if (State != C.getState())
1025  C.addTransition(State);
1026 }
1027 
1028 bool ObjCLoopChecker::isCollectionCountMethod(const ObjCMethodCall &M,
1029  CheckerContext &C) const {
1030  Selector S = M.getSelector();
1031  // Initialize the identifiers on first use.
1032  if (!CountSelectorII)
1033  CountSelectorII = &C.getASTContext().Idents.get("count");
1034 
1035  // If the method returns collection count, record the value.
1036  return S.isUnarySelector() &&
1037  (S.getIdentifierInfoForSlot(0) == CountSelectorII);
1038 }
1039 
1040 void ObjCLoopChecker::checkPostObjCMessage(const ObjCMethodCall &M,
1041  CheckerContext &C) const {
1042  if (!M.isInstanceMessage())
1043  return;
1044 
1045  const ObjCInterfaceDecl *ClassID = M.getReceiverInterface();
1046  if (!ClassID)
1047  return;
1048 
1049  FoundationClass Class = findKnownClass(ClassID);
1050  if (Class != FC_NSDictionary &&
1051  Class != FC_NSArray &&
1052  Class != FC_NSSet &&
1053  Class != FC_NSOrderedSet)
1054  return;
1055 
1056  SymbolRef ContainerS = M.getReceiverSVal().getAsSymbol();
1057  if (!ContainerS)
1058  return;
1059 
1060  // If we are processing a call to "count", get the symbolic value returned by
1061  // a call to "count" and add it to the map.
1062  if (!isCollectionCountMethod(M, C))
1063  return;
1064 
1065  const Expr *MsgExpr = M.getOriginExpr();
1066  SymbolRef CountS = C.getSVal(MsgExpr).getAsSymbol();
1067  if (CountS) {
1068  ProgramStateRef State = C.getState();
1069 
1070  C.getSymbolManager().addSymbolDependency(ContainerS, CountS);
1071  State = State->set<ContainerCountMap>(ContainerS, CountS);
1072 
1073  if (const bool *NonEmpty = State->get<ContainerNonEmptyMap>(ContainerS)) {
1074  State = State->remove<ContainerNonEmptyMap>(ContainerS);
1075  State = assumeCollectionNonEmpty(C, State, ContainerS, *NonEmpty);
1076  }
1077 
1078  C.addTransition(State);
1079  }
1080 }
1081 
1083  const ObjCMethodCall *Message = dyn_cast_or_null<ObjCMethodCall>(Call);
1084  if (!Message)
1085  return nullptr;
1086 
1087  const ObjCMethodDecl *MD = Message->getDecl();
1088  if (!MD)
1089  return nullptr;
1090 
1091  const ObjCInterfaceDecl *StaticClass;
1092  if (isa<ObjCProtocolDecl>(MD->getDeclContext())) {
1093  // We can't find out where the method was declared without doing more work.
1094  // Instead, see if the receiver is statically typed as a known immutable
1095  // collection.
1096  StaticClass = Message->getOriginExpr()->getReceiverInterface();
1097  } else {
1098  StaticClass = MD->getClassInterface();
1099  }
1100 
1101  if (!StaticClass)
1102  return nullptr;
1103 
1104  switch (findKnownClass(StaticClass, /*IncludeSuper=*/false)) {
1105  case FC_None:
1106  return nullptr;
1107  case FC_NSArray:
1108  case FC_NSDictionary:
1109  case FC_NSEnumerator:
1110  case FC_NSNull:
1111  case FC_NSOrderedSet:
1112  case FC_NSSet:
1113  case FC_NSString:
1114  break;
1115  }
1116 
1117  return Message->getReceiverSVal().getAsSymbol();
1118 }
1119 
1121 ObjCLoopChecker::checkPointerEscape(ProgramStateRef State,
1122  const InvalidatedSymbols &Escaped,
1123  const CallEvent *Call,
1124  PointerEscapeKind Kind) const {
1125  SymbolRef ImmutableReceiver = getMethodReceiverIfKnownImmutable(Call);
1126 
1127  // Remove the invalidated symbols form the collection count map.
1128  for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
1129  E = Escaped.end();
1130  I != E; ++I) {
1131  SymbolRef Sym = *I;
1132 
1133  // Don't invalidate this symbol's count if we know the method being called
1134  // is declared on an immutable class. This isn't completely correct if the
1135  // receiver is also passed as an argument, but in most uses of NSArray,
1136  // NSDictionary, etc. this isn't likely to happen in a dangerous way.
1137  if (Sym == ImmutableReceiver)
1138  continue;
1139 
1140  // The symbol escaped. Pessimistically, assume that the count could have
1141  // changed.
1142  State = State->remove<ContainerCountMap>(Sym);
1143  State = State->remove<ContainerNonEmptyMap>(Sym);
1144  }
1145  return State;
1146 }
1147 
1148 void ObjCLoopChecker::checkDeadSymbols(SymbolReaper &SymReaper,
1149  CheckerContext &C) const {
1150  ProgramStateRef State = C.getState();
1151 
1152  // Remove the dead symbols from the collection count map.
1153  ContainerCountMapTy Tracked = State->get<ContainerCountMap>();
1154  for (ContainerCountMapTy::iterator I = Tracked.begin(),
1155  E = Tracked.end(); I != E; ++I) {
1156  SymbolRef Sym = I->first;
1157  if (SymReaper.isDead(Sym)) {
1158  State = State->remove<ContainerCountMap>(Sym);
1159  State = State->remove<ContainerNonEmptyMap>(Sym);
1160  }
1161  }
1162 
1163  C.addTransition(State);
1164 }
1165 
1166 namespace {
1167 /// \class ObjCNonNilReturnValueChecker
1168 /// \brief The checker restricts the return values of APIs known to
1169 /// never (or almost never) return 'nil'.
1170 class ObjCNonNilReturnValueChecker
1171  : public Checker<check::PostObjCMessage,
1172  check::PostStmt<ObjCArrayLiteral>,
1173  check::PostStmt<ObjCDictionaryLiteral>,
1174  check::PostStmt<ObjCBoxedExpr> > {
1175  mutable bool Initialized;
1176  mutable Selector ObjectAtIndex;
1177  mutable Selector ObjectAtIndexedSubscript;
1178  mutable Selector NullSelector;
1179 
1180 public:
1181  ObjCNonNilReturnValueChecker() : Initialized(false) {}
1182 
1183  ProgramStateRef assumeExprIsNonNull(const Expr *NonNullExpr,
1184  ProgramStateRef State,
1185  CheckerContext &C) const;
1186  void assumeExprIsNonNull(const Expr *E, CheckerContext &C) const {
1187  C.addTransition(assumeExprIsNonNull(E, C.getState(), C));
1188  }
1189 
1190  void checkPostStmt(const ObjCArrayLiteral *E, CheckerContext &C) const {
1191  assumeExprIsNonNull(E, C);
1192  }
1193  void checkPostStmt(const ObjCDictionaryLiteral *E, CheckerContext &C) const {
1194  assumeExprIsNonNull(E, C);
1195  }
1196  void checkPostStmt(const ObjCBoxedExpr *E, CheckerContext &C) const {
1197  assumeExprIsNonNull(E, C);
1198  }
1199 
1200  void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
1201 };
1202 } // end anonymous namespace
1203 
1205 ObjCNonNilReturnValueChecker::assumeExprIsNonNull(const Expr *NonNullExpr,
1206  ProgramStateRef State,
1207  CheckerContext &C) const {
1208  SVal Val = State->getSVal(NonNullExpr, C.getLocationContext());
1209  if (Optional<DefinedOrUnknownSVal> DV = Val.getAs<DefinedOrUnknownSVal>())
1210  return State->assume(*DV, true);
1211  return State;
1212 }
1213 
1214 void ObjCNonNilReturnValueChecker::checkPostObjCMessage(const ObjCMethodCall &M,
1215  CheckerContext &C)
1216  const {
1217  ProgramStateRef State = C.getState();
1218 
1219  if (!Initialized) {
1220  ASTContext &Ctx = C.getASTContext();
1221  ObjectAtIndex = GetUnarySelector("objectAtIndex", Ctx);
1222  ObjectAtIndexedSubscript = GetUnarySelector("objectAtIndexedSubscript", Ctx);
1223  NullSelector = GetNullarySelector("null", Ctx);
1224  }
1225 
1226  // Check the receiver type.
1227  if (const ObjCInterfaceDecl *Interface = M.getReceiverInterface()) {
1228 
1229  // Assume that object returned from '[self init]' or '[super init]' is not
1230  // 'nil' if we are processing an inlined function/method.
1231  //
1232  // A defensive callee will (and should) check if the object returned by
1233  // '[super init]' is 'nil' before doing it's own initialization. However,
1234  // since 'nil' is rarely returned in practice, we should not warn when the
1235  // caller to the defensive constructor uses the object in contexts where
1236  // 'nil' is not accepted.
1237  if (!C.inTopFrame() && M.getDecl() &&
1238  M.getDecl()->getMethodFamily() == OMF_init &&
1239  M.isReceiverSelfOrSuper()) {
1240  State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1241  }
1242 
1243  FoundationClass Cl = findKnownClass(Interface);
1244 
1245  // Objects returned from
1246  // [NSArray|NSOrderedSet]::[ObjectAtIndex|ObjectAtIndexedSubscript]
1247  // are never 'nil'.
1248  if (Cl == FC_NSArray || Cl == FC_NSOrderedSet) {
1249  Selector Sel = M.getSelector();
1250  if (Sel == ObjectAtIndex || Sel == ObjectAtIndexedSubscript) {
1251  // Go ahead and assume the value is non-nil.
1252  State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1253  }
1254  }
1255 
1256  // Objects returned from [NSNull null] are not nil.
1257  if (Cl == FC_NSNull) {
1258  if (M.getSelector() == NullSelector) {
1259  // Go ahead and assume the value is non-nil.
1260  State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1261  }
1262  }
1263  }
1264  C.addTransition(State);
1265 }
1266 
1267 //===----------------------------------------------------------------------===//
1268 // Check registration.
1269 //===----------------------------------------------------------------------===//
1270 
1271 void ento::registerNilArgChecker(CheckerManager &mgr) {
1272  mgr.registerChecker<NilArgChecker>();
1273 }
1274 
1275 void ento::registerCFNumberCreateChecker(CheckerManager &mgr) {
1276  mgr.registerChecker<CFNumberCreateChecker>();
1277 }
1278 
1279 void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
1280  mgr.registerChecker<CFRetainReleaseChecker>();
1281 }
1282 
1283 void ento::registerClassReleaseChecker(CheckerManager &mgr) {
1284  mgr.registerChecker<ClassReleaseChecker>();
1285 }
1286 
1287 void ento::registerVariadicMethodTypeChecker(CheckerManager &mgr) {
1288  mgr.registerChecker<VariadicMethodTypeChecker>();
1289 }
1290 
1291 void ento::registerObjCLoopChecker(CheckerManager &mgr) {
1292  mgr.registerChecker<ObjCLoopChecker>();
1293 }
1294 
1295 void
1296 ento::registerObjCNonNilReturnValueChecker(CheckerManager &mgr) {
1297  mgr.registerChecker<ObjCNonNilReturnValueChecker>();
1298 }
Defines the clang::ASTContext interface.
static Selector GetNullarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing a nullary selector.
Definition: ASTContext.h:2605
CanQualType LongLongTy
Definition: ASTContext.h:901
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
Definition: Decl.h:1561
TypedValueRegion - An abstract class representing regions having a typed value.
Definition: MemRegion.h:494
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
Definition: SValBuilder.h:237
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:237
Smart pointer class that efficiently represents Objective-C method names.
A (possibly-)qualified type.
Definition: Type.h:598
ExplodedNode * generateErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:2217
ObjCInterfaceDecl * getClassInterface()
Definition: DeclObjC.cpp:1071
bool isInstanceMessage() const
Definition: CallEvent.h:917
static Selector GetUnarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing an unary selector.
Definition: ASTContext.h:2611
static ProgramStateRef assumeCollectionNonEmpty(CheckerContext &C, ProgramStateRef State, SymbolRef CollectionS, bool Assumption)
Returns NULL state if the collection is known to contain elements (or is known not to contain element...
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
Definition: Decl.h:232
The argument acts as if has been passed to CFMakeCollectable, which transfers the object to the Garba...
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
virtual QualType getValueType() const =0
StringRef P
static StringRef GetReceiverInterfaceName(const ObjCMethodCall &msg)
CanQualType LongTy
Definition: ASTContext.h:901
const Expr * getInit() const
Definition: Decl.h:1139
SourceRange getSourceRange() const override
Definition: CallEvent.cpp:741
static Selector getKeywordSelector(ASTContext &Ctx, va_list argp)
bool isBlockPointerType() const
Definition: Type.h:5488
Value representing integer constant.
Definition: SVals.h:341
static ProgramStateRef checkCollectionNonNil(CheckerContext &C, ProgramStateRef State, const ObjCForCollectionStmt *FCS)
Assumes that the collection is non-nil.
ObjCDictionaryElement getKeyValueElement(unsigned Index) const
Definition: ExprObjC.h:309
VarDecl - An instance of this class is created to represent a variable declaration or definition...
Definition: Decl.h:768
bool isReceiverSelfOrSuper() const
Checks if the receiver refers to 'self' or 'super'.
Definition: CallEvent.cpp:728
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:1813
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:113
ExplodedNode * getPredecessor()
Returns the previous node in the exploded graph, which includes the state of the program before the c...
Defines the Objective-C statement AST node classes.
bool isZeroConstant() const
Definition: SVals.cpp:186
Symbolic value.
Definition: SymExpr.h:29
const ObjCInterfaceDecl * getReceiverInterface() const
Get the interface for the receiver.
Definition: CallEvent.h:939
One of these records is kept for each identifier that is lexed.
An element in an Objective-C dictionary literal.
Definition: ExprObjC.h:212
IdentifierInfo * getIdentifierInfoForSlot(unsigned argIndex) const
Retrieve the identifier at a given position in the selector.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:92
const FunctionDecl * getCalleeDecl(const CallExpr *CE) const
Get the declaration of the called function (path-sensitive).
LineState State
The argument is treated as if an -autorelease message had been sent to the referenced object...
static ProgramStateRef checkElementNonNil(CheckerContext &C, ProgramStateRef State, const ObjCForCollectionStmt *FCS)
Assumes that the collection elements are non-nil.
void addSymbolDependency(const SymbolRef Primary, const SymbolRef Dependent)
Add artificial symbol dependency.
ObjCArrayLiteral - used for objective-c array containers; as in: @["Hello", NSApp, [NSNumber numberWithInt:42]];.
Definition: ExprObjC.h:144
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
IdentifierTable & Idents
Definition: ASTContext.h:459
Represents any expression that calls an Objective-C method.
Definition: CallEvent.h:881
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
Definition: CallEvent.cpp:712
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
Definition: DeclObjC.cpp:913
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
Definition: Type.h:934
Expr * Key
The key for the dictionary element.
Definition: ExprObjC.h:214
void print(llvm::raw_ostream &OS) const
Prints the full selector name (e.g. "foo:bar:").
#define UINT_MAX
Definition: limits.h:72
Represents an ObjC class declaration.
Definition: DeclObjC.h:1091
detail::InMemoryDirectory::const_iterator I
static SymbolRef getMethodReceiverIfKnownImmutable(const CallEvent *Call)
static bool isKnownNonNilCollectionType(QualType T)
The return type of classify().
Definition: Expr.h:299
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
bool isUnarySelector() const
bool inTopFrame() const
Return true if the current LocationContext has no caller context.
bool isDead(SymbolRef sym) const
Returns whether or not a symbol has been confirmed dead.
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
Definition: SValBuilder.cpp:32
Expr - This represents one expression.
Definition: Expr.h:105
static FoundationClass findKnownClass(const ObjCInterfaceDecl *ID, bool IncludeSuperclasses=true)
StringRef getName() const
Return the actual identifier string.
const ProgramStateRef & getState() const
pred_iterator pred_end()
unsigned getNumArgs() const
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:86
ObjCDictionaryLiteral - AST node to represent objective-c dictionary literals; as in:"name" : NSUserN...
Definition: ExprObjC.h:257
ObjCInterfaceDecl * getReceiverInterface() const
Retrieve the Objective-C interface to which this message is being directed, if known.
Definition: ExprObjC.cpp:327
CanQualType ShortTy
Definition: ASTContext.h:901
SymbolManager & getSymbolManager()
unsigned getNumElements() const
getNumElements - Return number of elements of objective-c array literal.
Definition: ExprObjC.h:184
Expr * getElement(unsigned Index)
getExpr - Return the Expr at the specified index.
Definition: ExprObjC.h:187
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
ExplodedNode * generateNonFatalErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
QualType getConditionType() const
Definition: SValBuilder.h:131
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
#define false
Definition: stdbool.h:33
Kind
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:5730
CHECKER * registerChecker()
Used to register checkers.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
const TemplateArgument * iterator
Definition: Type.h:4233
ExplodedNode * generateSink(ProgramStateRef State, ExplodedNode *Pred, const ProgramPointTag *Tag=nullptr)
Generate a sink node.
const std::string ID
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Definition: Stmt.h:443
bool isVariadic() const
Definition: DeclObjC.h:416
CanQualType FloatTy
Definition: ASTContext.h:904
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:46
Selector getSelector() const
Definition: CallEvent.h:923
A class responsible for cleaning up unused symbols.
ObjCBoxedExpr - used for generalized expression boxing.
Definition: ExprObjC.h:94
const ObjCMethodDecl * getDecl() const override
Definition: CallEvent.h:907
Expr * Value
The value of the dictionary element.
Definition: ExprObjC.h:217
QualType getType() const
Definition: Expr.h:126
CanQualType CharTy
Definition: ASTContext.h:895
static bool alreadyExecutedAtLeastOneLoopIteration(const ExplodedNode *N, const ObjCForCollectionStmt *FCS)
If the fist block edge is a back edge, we are reentering the loop.
Represents symbolic expression.
Definition: SVals.h:315
detail::InMemoryDirectory::const_iterator E
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:2205
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:1966
Represents an abstract call to a function or method along a particular path.
Definition: CallEvent.h:138
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
Definition: ProgramPoint.h:150
ObjCMessageKind getMessageKind() const
Returns how the message was written in the source (property access, subscript, or explicit message se...
Definition: CallEvent.cpp:772
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
Represents a pointer to an Objective C object.
Definition: Type.h:4991
const LangOptions & getLangOpts() const
const ExplodedNode *const * const_pred_iterator
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:5818
Represents Objective-C's collection statement.
Definition: StmtObjC.h:24
ObjCInterfaceDecl * getInterfaceDecl() const
If this pointer points to an Objective @interface type, gets the declaration for that interface...
Definition: Type.h:5046
unsigned getNumArgs() const override
Definition: CallEvent.h:910
const Expr * getArgExpr(unsigned Index) const override
Definition: CallEvent.h:913
DefinedOrUnknownSVal evalEQ(ProgramStateRef state, DefinedOrUnknownSVal lhs, DefinedOrUnknownSVal rhs)
bool isObjCObjectPointerType() const
Definition: Type.h:5554
bool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R, bool IsArg=false, bool EnableNullFPSuppression=true)
Attempts to add visitors to trace a null or undefined value back to its point of origin, whether it is a symbol constrained to null or an explicit assignment.
pred_iterator pred_begin()
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
Definition: SVals.cpp:111
SValBuilder & getSValBuilder()
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2148
ObjCInterfaceDecl * getSuperClass() const
Definition: DeclObjC.cpp:314
static Optional< uint64_t > GetCFNumberSize(ASTContext &Ctx, uint64_t i)
CanQualType IntTy
Definition: ASTContext.h:901
A trivial tuple used to represent a source range.
CanQualType DoubleTy
Definition: ASTContext.h:904
static bool isObjCNSObjectType(QualType Ty)
Return true if this is an NSObject object with its NSObject attribute set.
Definition: ASTContext.h:1793
virtual const ObjCMessageExpr * getOriginExpr() const
Definition: CallEvent.h:904
const llvm::APSInt & getValue() const
Definition: SVals.h:345
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Definition: SVals.h:75
unsigned getNumElements() const
getNumElements - Return number of elements of objective-c dictionary literal.
Definition: ExprObjC.h:307
TypedRegion - An abstract class representing regions that are typed.
Definition: MemRegion.h:472
const LocationContext * getLocationContext() const
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.