clang  7.0.0svn
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.
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"),
237  getKeywordSelector(Ctx, "compare"),
238  getKeywordSelector(Ctx, "compare", "options"),
239  getKeywordSelector(Ctx, "compare", "options", "range"),
240  getKeywordSelector(Ctx, "compare", "options", "range", "locale"),
241  getKeywordSelector(Ctx, "componentsSeparatedByCharactersInSet"),
242  getKeywordSelector(Ctx, "initWithFormat"),
243  getKeywordSelector(Ctx, "localizedCaseInsensitiveCompare"),
244  getKeywordSelector(Ctx, "localizedCompare"),
245  getKeywordSelector(Ctx, "localizedStandardCompare"),
246  };
247  for (Selector KnownSel : Sels)
248  StringSelectors[KnownSel] = 0;
249  }
250  auto I = StringSelectors.find(S);
251  if (I == StringSelectors.end())
252  return;
253  Arg = I->second;
254  } else if (Class == FC_NSArray) {
255  Selector S = msg.getSelector();
256 
257  if (S.isUnarySelector())
258  return;
259 
260  if (ArrayWithObjectSel.isNull()) {
261  ASTContext &Ctx = C.getASTContext();
262  ArrayWithObjectSel = getKeywordSelector(Ctx, "arrayWithObject");
263  AddObjectSel = getKeywordSelector(Ctx, "addObject");
264  InsertObjectAtIndexSel =
265  getKeywordSelector(Ctx, "insertObject", "atIndex");
266  ReplaceObjectAtIndexWithObjectSel =
267  getKeywordSelector(Ctx, "replaceObjectAtIndex", "withObject");
268  SetObjectAtIndexedSubscriptSel =
269  getKeywordSelector(Ctx, "setObject", "atIndexedSubscript");
270  ArrayByAddingObjectSel = getKeywordSelector(Ctx, "arrayByAddingObject");
271  }
272 
273  if (S == ArrayWithObjectSel || S == AddObjectSel ||
274  S == InsertObjectAtIndexSel || S == ArrayByAddingObjectSel) {
275  Arg = 0;
276  } else if (S == SetObjectAtIndexedSubscriptSel) {
277  Arg = 0;
278  CanBeSubscript = true;
279  } else if (S == ReplaceObjectAtIndexWithObjectSel) {
280  Arg = 1;
281  }
282  } else if (Class == FC_NSDictionary) {
283  Selector S = msg.getSelector();
284 
285  if (S.isUnarySelector())
286  return;
287 
288  if (DictionaryWithObjectForKeySel.isNull()) {
289  ASTContext &Ctx = C.getASTContext();
290  DictionaryWithObjectForKeySel =
291  getKeywordSelector(Ctx, "dictionaryWithObject", "forKey");
292  SetObjectForKeySel = getKeywordSelector(Ctx, "setObject", "forKey");
293  SetObjectForKeyedSubscriptSel =
294  getKeywordSelector(Ctx, "setObject", "forKeyedSubscript");
295  RemoveObjectForKeySel = getKeywordSelector(Ctx, "removeObjectForKey");
296  }
297 
298  if (S == DictionaryWithObjectForKeySel || S == SetObjectForKeySel) {
299  Arg = 0;
300  warnIfNilArg(C, msg, /* Arg */1, Class);
301  } else if (S == SetObjectForKeyedSubscriptSel) {
302  CanBeSubscript = true;
303  Arg = 1;
304  } else if (S == RemoveObjectForKeySel) {
305  Arg = 0;
306  }
307  }
308 
309  // If argument is '0', report a warning.
310  if ((Arg != InvalidArgIndex))
311  warnIfNilArg(C, msg, Arg, Class, CanBeSubscript);
312 }
313 
314 void NilArgChecker::checkPostStmt(const ObjCArrayLiteral *AL,
315  CheckerContext &C) const {
316  unsigned NumOfElements = AL->getNumElements();
317  for (unsigned i = 0; i < NumOfElements; ++i) {
318  warnIfNilExpr(AL->getElement(i), "Array element cannot be nil", C);
319  }
320 }
321 
322 void NilArgChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
323  CheckerContext &C) const {
324  unsigned NumOfElements = DL->getNumElements();
325  for (unsigned i = 0; i < NumOfElements; ++i) {
326  ObjCDictionaryElement Element = DL->getKeyValueElement(i);
327  warnIfNilExpr(Element.Key, "Dictionary key cannot be nil", C);
328  warnIfNilExpr(Element.Value, "Dictionary value cannot be nil", C);
329  }
330 }
331 
332 //===----------------------------------------------------------------------===//
333 // Checking for mismatched types passed to CFNumberCreate/CFNumberGetValue.
334 //===----------------------------------------------------------------------===//
335 
336 namespace {
337 class CFNumberChecker : public Checker< check::PreStmt<CallExpr> > {
338  mutable std::unique_ptr<APIMisuse> BT;
339  mutable IdentifierInfo *ICreate, *IGetValue;
340 public:
341  CFNumberChecker() : ICreate(nullptr), IGetValue(nullptr) {}
342 
343  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
344 
345 private:
346  void EmitError(const TypedRegion* R, const Expr *Ex,
347  uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind);
348 };
349 } // end anonymous namespace
350 
368 };
369 
371  static const unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 };
372 
373  if (i < kCFNumberCharType)
374  return FixedSize[i-1];
375 
376  QualType T;
377 
378  switch (i) {
379  case kCFNumberCharType: T = Ctx.CharTy; break;
380  case kCFNumberShortType: T = Ctx.ShortTy; break;
381  case kCFNumberIntType: T = Ctx.IntTy; break;
382  case kCFNumberLongType: T = Ctx.LongTy; break;
383  case kCFNumberLongLongType: T = Ctx.LongLongTy; break;
384  case kCFNumberFloatType: T = Ctx.FloatTy; break;
385  case kCFNumberDoubleType: T = Ctx.DoubleTy; break;
389  // FIXME: We need a way to map from names to Type*.
390  default:
391  return None;
392  }
393 
394  return Ctx.getTypeSize(T);
395 }
396 
397 #if 0
398 static const char* GetCFNumberTypeStr(uint64_t i) {
399  static const char* Names[] = {
400  "kCFNumberSInt8Type",
401  "kCFNumberSInt16Type",
402  "kCFNumberSInt32Type",
403  "kCFNumberSInt64Type",
404  "kCFNumberFloat32Type",
405  "kCFNumberFloat64Type",
406  "kCFNumberCharType",
407  "kCFNumberShortType",
408  "kCFNumberIntType",
409  "kCFNumberLongType",
410  "kCFNumberLongLongType",
411  "kCFNumberFloatType",
412  "kCFNumberDoubleType",
413  "kCFNumberCFIndexType",
414  "kCFNumberNSIntegerType",
415  "kCFNumberCGFloatType"
416  };
417 
418  return i <= kCFNumberCGFloatType ? Names[i-1] : "Invalid CFNumberType";
419 }
420 #endif
421 
422 void CFNumberChecker::checkPreStmt(const CallExpr *CE,
423  CheckerContext &C) const {
425  const FunctionDecl *FD = C.getCalleeDecl(CE);
426  if (!FD)
427  return;
428 
429  ASTContext &Ctx = C.getASTContext();
430  if (!ICreate) {
431  ICreate = &Ctx.Idents.get("CFNumberCreate");
432  IGetValue = &Ctx.Idents.get("CFNumberGetValue");
433  }
434  if (!(FD->getIdentifier() == ICreate || FD->getIdentifier() == IGetValue) ||
435  CE->getNumArgs() != 3)
436  return;
437 
438  // Get the value of the "theType" argument.
439  SVal TheTypeVal = C.getSVal(CE->getArg(1));
440 
441  // FIXME: We really should allow ranges of valid theType values, and
442  // bifurcate the state appropriately.
444  if (!V)
445  return;
446 
447  uint64_t NumberKind = V->getValue().getLimitedValue();
448  Optional<uint64_t> OptCFNumberSize = GetCFNumberSize(Ctx, NumberKind);
449 
450  // FIXME: In some cases we can emit an error.
451  if (!OptCFNumberSize)
452  return;
453 
454  uint64_t CFNumberSize = *OptCFNumberSize;
455 
456  // Look at the value of the integer being passed by reference. Essentially
457  // we want to catch cases where the value passed in is not equal to the
458  // size of the type being created.
459  SVal TheValueExpr = C.getSVal(CE->getArg(2));
460 
461  // FIXME: Eventually we should handle arbitrary locations. We can do this
462  // by having an enhanced memory model that does low-level typing.
464  if (!LV)
465  return;
466 
467  const TypedValueRegion* R = dyn_cast<TypedValueRegion>(LV->stripCasts());
468  if (!R)
469  return;
470 
472 
473  // FIXME: If the pointee isn't an integer type, should we flag a warning?
474  // People can do weird stuff with pointers.
475 
476  if (!T->isIntegralOrEnumerationType())
477  return;
478 
479  uint64_t PrimitiveTypeSize = Ctx.getTypeSize(T);
480 
481  if (PrimitiveTypeSize == CFNumberSize)
482  return;
483 
484  // FIXME: We can actually create an abstract "CFNumber" object that has
485  // the bits initialized to the provided values.
487  if (N) {
488  SmallString<128> sbuf;
489  llvm::raw_svector_ostream os(sbuf);
490  bool isCreate = (FD->getIdentifier() == ICreate);
491 
492  if (isCreate) {
493  os << (PrimitiveTypeSize == 8 ? "An " : "A ")
494  << PrimitiveTypeSize << "-bit integer is used to initialize a "
495  << "CFNumber object that represents "
496  << (CFNumberSize == 8 ? "an " : "a ")
497  << CFNumberSize << "-bit integer; ";
498  } else {
499  os << "A CFNumber object that represents "
500  << (CFNumberSize == 8 ? "an " : "a ")
501  << CFNumberSize << "-bit integer is used to initialize "
502  << (PrimitiveTypeSize == 8 ? "an " : "a ")
503  << PrimitiveTypeSize << "-bit integer; ";
504  }
505 
506  if (PrimitiveTypeSize < CFNumberSize)
507  os << (CFNumberSize - PrimitiveTypeSize)
508  << " bits of the CFNumber value will "
509  << (isCreate ? "be garbage." : "overwrite adjacent storage.");
510  else
511  os << (PrimitiveTypeSize - CFNumberSize)
512  << " bits of the integer value will be "
513  << (isCreate ? "lost." : "garbage.");
514 
515  if (!BT)
516  BT.reset(new APIMisuse(this, "Bad use of CFNumber APIs"));
517 
518  auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
519  report->addRange(CE->getArg(2)->getSourceRange());
520  C.emitReport(std::move(report));
521  }
522 }
523 
524 //===----------------------------------------------------------------------===//
525 // CFRetain/CFRelease/CFMakeCollectable/CFAutorelease checking for null arguments.
526 //===----------------------------------------------------------------------===//
527 
528 namespace {
529 class CFRetainReleaseChecker : public Checker< check::PreStmt<CallExpr> > {
530  mutable std::unique_ptr<APIMisuse> BT;
531  mutable IdentifierInfo *Retain, *Release, *MakeCollectable, *Autorelease;
532 
533 public:
534  CFRetainReleaseChecker()
535  : Retain(nullptr), Release(nullptr), MakeCollectable(nullptr),
536  Autorelease(nullptr) {}
537  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
538 };
539 } // end anonymous namespace
540 
541 void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
542  CheckerContext &C) const {
543  // If the CallExpr doesn't have exactly 1 argument just give up checking.
544  if (CE->getNumArgs() != 1)
545  return;
546 
548  const FunctionDecl *FD = C.getCalleeDecl(CE);
549  if (!FD)
550  return;
551 
552  if (!BT) {
553  ASTContext &Ctx = C.getASTContext();
554  Retain = &Ctx.Idents.get("CFRetain");
555  Release = &Ctx.Idents.get("CFRelease");
556  MakeCollectable = &Ctx.Idents.get("CFMakeCollectable");
557  Autorelease = &Ctx.Idents.get("CFAutorelease");
558  BT.reset(new APIMisuse(
559  this, "null passed to CF memory management function"));
560  }
561 
562  // Check if we called CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
563  const IdentifierInfo *FuncII = FD->getIdentifier();
564  if (!(FuncII == Retain || FuncII == Release || FuncII == MakeCollectable ||
565  FuncII == Autorelease))
566  return;
567 
568  // FIXME: The rest of this just checks that the argument is non-null.
569  // It should probably be refactored and combined with NonNullParamChecker.
570 
571  // Get the argument's value.
572  const Expr *Arg = CE->getArg(0);
573  SVal ArgVal = C.getSVal(Arg);
574  Optional<DefinedSVal> DefArgVal = ArgVal.getAs<DefinedSVal>();
575  if (!DefArgVal)
576  return;
577 
578  // Get a NULL value.
579  SValBuilder &svalBuilder = C.getSValBuilder();
580  DefinedSVal zero =
581  svalBuilder.makeZeroVal(Arg->getType()).castAs<DefinedSVal>();
582 
583  // Make an expression asserting that they're equal.
584  DefinedOrUnknownSVal ArgIsNull = svalBuilder.evalEQ(state, zero, *DefArgVal);
585 
586  // Are they equal?
587  ProgramStateRef stateTrue, stateFalse;
588  std::tie(stateTrue, stateFalse) = state->assume(ArgIsNull);
589 
590  if (stateTrue && !stateFalse) {
591  ExplodedNode *N = C.generateErrorNode(stateTrue);
592  if (!N)
593  return;
594 
595  const char *description;
596  if (FuncII == Retain)
597  description = "Null pointer argument in call to CFRetain";
598  else if (FuncII == Release)
599  description = "Null pointer argument in call to CFRelease";
600  else if (FuncII == MakeCollectable)
601  description = "Null pointer argument in call to CFMakeCollectable";
602  else if (FuncII == Autorelease)
603  description = "Null pointer argument in call to CFAutorelease";
604  else
605  llvm_unreachable("impossible case");
606 
607  auto report = llvm::make_unique<BugReport>(*BT, description, N);
608  report->addRange(Arg->getSourceRange());
609  bugreporter::trackNullOrUndefValue(N, Arg, *report);
610  C.emitReport(std::move(report));
611  return;
612  }
613 
614  // From here on, we know the argument is non-null.
615  C.addTransition(stateFalse);
616 }
617 
618 //===----------------------------------------------------------------------===//
619 // Check for sending 'retain', 'release', or 'autorelease' directly to a Class.
620 //===----------------------------------------------------------------------===//
621 
622 namespace {
623 class ClassReleaseChecker : public Checker<check::PreObjCMessage> {
624  mutable Selector releaseS;
625  mutable Selector retainS;
626  mutable Selector autoreleaseS;
627  mutable Selector drainS;
628  mutable std::unique_ptr<BugType> BT;
629 
630 public:
631  void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
632 };
633 } // end anonymous namespace
634 
635 void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
636  CheckerContext &C) const {
637  if (!BT) {
638  BT.reset(new APIMisuse(
639  this, "message incorrectly sent to class instead of class instance"));
640 
641  ASTContext &Ctx = C.getASTContext();
642  releaseS = GetNullarySelector("release", Ctx);
643  retainS = GetNullarySelector("retain", Ctx);
644  autoreleaseS = GetNullarySelector("autorelease", Ctx);
645  drainS = GetNullarySelector("drain", Ctx);
646  }
647 
648  if (msg.isInstanceMessage())
649  return;
650  const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
651  assert(Class);
652 
653  Selector S = msg.getSelector();
654  if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
655  return;
656 
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.
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.
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 = C.getSVal(FCS->getCollection()).getAsSymbol();
980  return assumeCollectionNonEmpty(C, State, CollectionS, Assumption);
981 }
982 
983 /// If the fist block edge is a back edge, we are reentering the loop.
985  const ObjCForCollectionStmt *FCS) {
986  if (!N)
987  return false;
988 
989  ProgramPoint P = N->getLocation();
990  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
991  return BE->getSrc()->getLoopTarget() == FCS;
992  }
993 
994  // Keep looking for a block edge.
996  E = N->pred_end(); I != E; ++I) {
998  return true;
999  }
1000 
1001  return false;
1002 }
1003 
1004 void ObjCLoopChecker::checkPostStmt(const ObjCForCollectionStmt *FCS,
1005  CheckerContext &C) const {
1007 
1008  // Check if this is the branch for the end of the loop.
1009  SVal CollectionSentinel = C.getSVal(FCS);
1010  if (CollectionSentinel.isZeroConstant()) {
1012  State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/false);
1013 
1014  // Otherwise, this is a branch that goes through the loop body.
1015  } else {
1016  State = checkCollectionNonNil(C, State, FCS);
1017  State = checkElementNonNil(C, State, FCS);
1018  State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/true);
1019  }
1020 
1021  if (!State)
1022  C.generateSink(C.getState(), C.getPredecessor());
1023  else if (State != C.getState())
1024  C.addTransition(State);
1025 }
1026 
1027 bool ObjCLoopChecker::isCollectionCountMethod(const ObjCMethodCall &M,
1028  CheckerContext &C) const {
1029  Selector S = M.getSelector();
1030  // Initialize the identifiers on first use.
1031  if (!CountSelectorII)
1032  CountSelectorII = &C.getASTContext().Idents.get("count");
1033 
1034  // If the method returns collection count, record the value.
1035  return S.isUnarySelector() &&
1036  (S.getIdentifierInfoForSlot(0) == CountSelectorII);
1037 }
1038 
1039 void ObjCLoopChecker::checkPostObjCMessage(const ObjCMethodCall &M,
1040  CheckerContext &C) const {
1041  if (!M.isInstanceMessage())
1042  return;
1043 
1044  const ObjCInterfaceDecl *ClassID = M.getReceiverInterface();
1045  if (!ClassID)
1046  return;
1047 
1048  FoundationClass Class = findKnownClass(ClassID);
1049  if (Class != FC_NSDictionary &&
1050  Class != FC_NSArray &&
1051  Class != FC_NSSet &&
1052  Class != FC_NSOrderedSet)
1053  return;
1054 
1055  SymbolRef ContainerS = M.getReceiverSVal().getAsSymbol();
1056  if (!ContainerS)
1057  return;
1058 
1059  // If we are processing a call to "count", get the symbolic value returned by
1060  // a call to "count" and add it to the map.
1061  if (!isCollectionCountMethod(M, C))
1062  return;
1063 
1064  const Expr *MsgExpr = M.getOriginExpr();
1065  SymbolRef CountS = C.getSVal(MsgExpr).getAsSymbol();
1066  if (CountS) {
1068 
1069  C.getSymbolManager().addSymbolDependency(ContainerS, CountS);
1070  State = State->set<ContainerCountMap>(ContainerS, CountS);
1071 
1072  if (const bool *NonEmpty = State->get<ContainerNonEmptyMap>(ContainerS)) {
1073  State = State->remove<ContainerNonEmptyMap>(ContainerS);
1074  State = assumeCollectionNonEmpty(C, State, ContainerS, *NonEmpty);
1075  }
1076 
1077  C.addTransition(State);
1078  }
1079 }
1080 
1082  const ObjCMethodCall *Message = dyn_cast_or_null<ObjCMethodCall>(Call);
1083  if (!Message)
1084  return nullptr;
1085 
1086  const ObjCMethodDecl *MD = Message->getDecl();
1087  if (!MD)
1088  return nullptr;
1089 
1090  const ObjCInterfaceDecl *StaticClass;
1091  if (isa<ObjCProtocolDecl>(MD->getDeclContext())) {
1092  // We can't find out where the method was declared without doing more work.
1093  // Instead, see if the receiver is statically typed as a known immutable
1094  // collection.
1095  StaticClass = Message->getOriginExpr()->getReceiverInterface();
1096  } else {
1097  StaticClass = MD->getClassInterface();
1098  }
1099 
1100  if (!StaticClass)
1101  return nullptr;
1102 
1103  switch (findKnownClass(StaticClass, /*IncludeSuper=*/false)) {
1104  case FC_None:
1105  return nullptr;
1106  case FC_NSArray:
1107  case FC_NSDictionary:
1108  case FC_NSEnumerator:
1109  case FC_NSNull:
1110  case FC_NSOrderedSet:
1111  case FC_NSSet:
1112  case FC_NSString:
1113  break;
1114  }
1115 
1116  return Message->getReceiverSVal().getAsSymbol();
1117 }
1118 
1120 ObjCLoopChecker::checkPointerEscape(ProgramStateRef State,
1121  const InvalidatedSymbols &Escaped,
1122  const CallEvent *Call,
1123  PointerEscapeKind Kind) const {
1124  SymbolRef ImmutableReceiver = getMethodReceiverIfKnownImmutable(Call);
1125 
1126  // Remove the invalidated symbols form the collection count map.
1127  for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
1128  E = Escaped.end();
1129  I != E; ++I) {
1130  SymbolRef Sym = *I;
1131 
1132  // Don't invalidate this symbol's count if we know the method being called
1133  // is declared on an immutable class. This isn't completely correct if the
1134  // receiver is also passed as an argument, but in most uses of NSArray,
1135  // NSDictionary, etc. this isn't likely to happen in a dangerous way.
1136  if (Sym == ImmutableReceiver)
1137  continue;
1138 
1139  // The symbol escaped. Pessimistically, assume that the count could have
1140  // changed.
1141  State = State->remove<ContainerCountMap>(Sym);
1142  State = State->remove<ContainerNonEmptyMap>(Sym);
1143  }
1144  return State;
1145 }
1146 
1147 void ObjCLoopChecker::checkDeadSymbols(SymbolReaper &SymReaper,
1148  CheckerContext &C) const {
1149  ProgramStateRef State = C.getState();
1150 
1151  // Remove the dead symbols from the collection count map.
1152  ContainerCountMapTy Tracked = State->get<ContainerCountMap>();
1153  for (ContainerCountMapTy::iterator I = Tracked.begin(),
1154  E = Tracked.end(); I != E; ++I) {
1155  SymbolRef Sym = I->first;
1156  if (SymReaper.isDead(Sym)) {
1157  State = State->remove<ContainerCountMap>(Sym);
1158  State = State->remove<ContainerNonEmptyMap>(Sym);
1159  }
1160  }
1161 
1162  C.addTransition(State);
1163 }
1164 
1165 namespace {
1166 /// \class ObjCNonNilReturnValueChecker
1167 /// \brief The checker restricts the return values of APIs known to
1168 /// never (or almost never) return 'nil'.
1169 class ObjCNonNilReturnValueChecker
1170  : public Checker<check::PostObjCMessage,
1171  check::PostStmt<ObjCArrayLiteral>,
1172  check::PostStmt<ObjCDictionaryLiteral>,
1173  check::PostStmt<ObjCBoxedExpr> > {
1174  mutable bool Initialized;
1175  mutable Selector ObjectAtIndex;
1176  mutable Selector ObjectAtIndexedSubscript;
1177  mutable Selector NullSelector;
1178 
1179 public:
1180  ObjCNonNilReturnValueChecker() : Initialized(false) {}
1181 
1182  ProgramStateRef assumeExprIsNonNull(const Expr *NonNullExpr,
1183  ProgramStateRef State,
1184  CheckerContext &C) const;
1185  void assumeExprIsNonNull(const Expr *E, CheckerContext &C) const {
1186  C.addTransition(assumeExprIsNonNull(E, C.getState(), C));
1187  }
1188 
1189  void checkPostStmt(const ObjCArrayLiteral *E, CheckerContext &C) const {
1190  assumeExprIsNonNull(E, C);
1191  }
1192  void checkPostStmt(const ObjCDictionaryLiteral *E, CheckerContext &C) const {
1193  assumeExprIsNonNull(E, C);
1194  }
1195  void checkPostStmt(const ObjCBoxedExpr *E, CheckerContext &C) const {
1196  assumeExprIsNonNull(E, C);
1197  }
1198 
1199  void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
1200 };
1201 } // end anonymous namespace
1202 
1204 ObjCNonNilReturnValueChecker::assumeExprIsNonNull(const Expr *NonNullExpr,
1205  ProgramStateRef State,
1206  CheckerContext &C) const {
1207  SVal Val = C.getSVal(NonNullExpr);
1209  return State->assume(*DV, true);
1210  return State;
1211 }
1212 
1213 void ObjCNonNilReturnValueChecker::checkPostObjCMessage(const ObjCMethodCall &M,
1214  CheckerContext &C)
1215  const {
1216  ProgramStateRef State = C.getState();
1217 
1218  if (!Initialized) {
1219  ASTContext &Ctx = C.getASTContext();
1220  ObjectAtIndex = GetUnarySelector("objectAtIndex", Ctx);
1221  ObjectAtIndexedSubscript = GetUnarySelector("objectAtIndexedSubscript", Ctx);
1222  NullSelector = GetNullarySelector("null", Ctx);
1223  }
1224 
1225  // Check the receiver type.
1226  if (const ObjCInterfaceDecl *Interface = M.getReceiverInterface()) {
1227 
1228  // Assume that object returned from '[self init]' or '[super init]' is not
1229  // 'nil' if we are processing an inlined function/method.
1230  //
1231  // A defensive callee will (and should) check if the object returned by
1232  // '[super init]' is 'nil' before doing it's own initialization. However,
1233  // since 'nil' is rarely returned in practice, we should not warn when the
1234  // caller to the defensive constructor uses the object in contexts where
1235  // 'nil' is not accepted.
1236  if (!C.inTopFrame() && M.getDecl() &&
1237  M.getDecl()->getMethodFamily() == OMF_init &&
1238  M.isReceiverSelfOrSuper()) {
1239  State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1240  }
1241 
1242  FoundationClass Cl = findKnownClass(Interface);
1243 
1244  // Objects returned from
1245  // [NSArray|NSOrderedSet]::[ObjectAtIndex|ObjectAtIndexedSubscript]
1246  // are never 'nil'.
1247  if (Cl == FC_NSArray || Cl == FC_NSOrderedSet) {
1248  Selector Sel = M.getSelector();
1249  if (Sel == ObjectAtIndex || Sel == ObjectAtIndexedSubscript) {
1250  // Go ahead and assume the value is non-nil.
1251  State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1252  }
1253  }
1254 
1255  // Objects returned from [NSNull null] are not nil.
1256  if (Cl == FC_NSNull) {
1257  if (M.getSelector() == NullSelector) {
1258  // Go ahead and assume the value is non-nil.
1259  State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
1260  }
1261  }
1262  }
1263  C.addTransition(State);
1264 }
1265 
1266 //===----------------------------------------------------------------------===//
1267 // Check registration.
1268 //===----------------------------------------------------------------------===//
1269 
1270 void ento::registerNilArgChecker(CheckerManager &mgr) {
1271  mgr.registerChecker<NilArgChecker>();
1272 }
1273 
1274 void ento::registerCFNumberChecker(CheckerManager &mgr) {
1275  mgr.registerChecker<CFNumberChecker>();
1276 }
1277 
1278 void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
1279  mgr.registerChecker<CFRetainReleaseChecker>();
1280 }
1281 
1282 void ento::registerClassReleaseChecker(CheckerManager &mgr) {
1283  mgr.registerChecker<ClassReleaseChecker>();
1284 }
1285 
1286 void ento::registerVariadicMethodTypeChecker(CheckerManager &mgr) {
1287  mgr.registerChecker<VariadicMethodTypeChecker>();
1288 }
1289 
1290 void ento::registerObjCLoopChecker(CheckerManager &mgr) {
1291  mgr.registerChecker<ObjCLoopChecker>();
1292 }
1293 
1294 void
1295 ento::registerObjCNonNilReturnValueChecker(CheckerManager &mgr) {
1296  mgr.registerChecker<ObjCNonNilReturnValueChecker>();
1297 }
Defines the clang::ASTContext interface.
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
Definition: CallEvent.cpp:753
CanQualType LongLongTy
Definition: ASTContext.h:1004
An instance of this class is created to represent a function declaration or definition.
Definition: Decl.h:1697
TypedValueRegion - An abstract class representing regions having a typed value.
Definition: MemRegion.h:512
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
Definition: SValBuilder.h:261
ObjCDictionaryElement getKeyValueElement(unsigned Index) const
Definition: ExprObjC.h:344
Smart pointer class that efficiently represents Objective-C method names.
A (possibly-)qualified type.
Definition: Type.h:653
bool isBlockPointerType() const
Definition: Type.h:5950
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:2287
ObjCInterfaceDecl * getClassInterface()
Definition: DeclObjC.cpp:1101
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
Definition: Type.h:989
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...
Stmt - This represents one statement.
Definition: Stmt.h:66
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:2275
ObjCInterfaceDecl * getReceiverInterface() const
Retrieve the Objective-C interface to which this message is being directed, if known.
Definition: ExprObjC.cpp:333
The argument acts as if has been passed to CFMakeCollectable, which transfers the object to the Garba...
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:1004
SourceRange getSourceRange() const override
Definition: CallEvent.cpp:782
Value representing integer constant.
Definition: SVals.h:353
static ProgramStateRef checkCollectionNonNil(CheckerContext &C, ProgramStateRef State, const ObjCForCollectionStmt *FCS)
Assumes that the collection is non-nil.
VarDecl - An instance of this class is created to represent a variable declaration or definition...
Definition: Decl.h:806
const T * getAs() const
Member-template getAs<specific type>&#39;.
Definition: Type.h:6305
const FunctionDecl * getCalleeDecl(const CallExpr *CE) const
Get the declaration of the called function (path-sensitive).
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:139
bool isDead(SymbolRef sym) const
Returns whether or not a symbol has been confirmed dead.
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.
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.
Symbolic value.
Definition: SymExpr.h:29
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
Definition: Decl.h:265
One of these records is kept for each identifier that is lexed.
An element in an Objective-C dictionary literal.
Definition: ExprObjC.h:239
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:149
static Selector getKeywordSelector(ASTContext &Ctx, IdentifierInfos *... IIs)
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.
const ObjCInterfaceDecl * getReceiverInterface() const
Get the interface for the receiver.
Definition: CallEvent.h:928
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:171
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
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:6219
IdentifierTable & Idents
Definition: ASTContext.h:537
bool isUnarySelector() const
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
Definition: DeclObjC.cpp:943
Represents any expression that calls an Objective-C method.
Definition: CallEvent.h:870
Selector GetNullarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing a nullary selector.
Definition: ASTContext.h:2858
Expr * Key
The key for the dictionary element.
Definition: ExprObjC.h:241
#define UINT_MAX
Definition: limits.h:72
Represents an ObjC class declaration.
Definition: DeclObjC.h:1191
static SymbolRef getMethodReceiverIfKnownImmutable(const CallEvent *Call)
static bool isKnownNonNilCollectionType(QualType T)
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
Definition: SVals.cpp:116
bool isReceiverSelfOrSuper() const
Checks if the receiver refers to &#39;self&#39; or &#39;super&#39;.
Definition: CallEvent.cpp:769
The return type of classify().
Definition: Expr.h:302
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing &#39;0&#39; for the specified type.
Definition: SValBuilder.cpp:32
Expr - This represents one expression.
Definition: Expr.h:106
static FoundationClass findKnownClass(const ObjCInterfaceDecl *ID, bool IncludeSuperclasses=true)
pred_iterator pred_end()
const FunctionProtoType * T
ObjCDictionaryLiteral - AST node to represent objective-c dictionary literals; as in:"name" : NSUserN...
Definition: ExprObjC.h:288
DeclContext * getDeclContext()
Definition: DeclBase.h:425
QualType getConditionType() const
Definition: SValBuilder.h:143
ObjCInterfaceDecl * getSuperClass() const
Definition: DeclObjC.cpp:330
CanQualType ShortTy
Definition: ASTContext.h:1004
SymbolManager & getSymbolManager()
void print(llvm::raw_ostream &OS) const
Prints the full selector name (e.g. "foo:bar:").
QualType getType() const
Definition: Expr.h:128
Expr * getElement(unsigned Index)
getElement - Return the Element at the specified index.
Definition: ExprObjC.h:213
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
unsigned getNumArgs() const
ExplodedNode * generateNonFatalErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:100
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
Kind
CHECKER * registerChecker()
Used to register checkers.
IdentifierInfo * getIdentifierInfoForSlot(unsigned argIndex) const
Retrieve the identifier at a given position in the selector.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
ExplodedNode * generateSink(ProgramStateRef State, ExplodedNode *Pred, const ProgramPointTag *Tag=nullptr)
Generate a sink node.
unsigned getNumElements() const
getNumElements - Return number of elements of objective-c dictionary literal.
Definition: ExprObjC.h:342
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Definition: Stmt.h:487
CanQualType FloatTy
Definition: ASTContext.h:1007
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:63
bool isObjCObjectPointerType() const
Definition: Type.h:6039
A class responsible for cleaning up unused symbols.
ObjCBoxedExpr - used for generalized expression boxing.
Definition: ExprObjC.h:117
const ObjCMethodDecl * getDecl() const override
Definition: CallEvent.h:896
Expr * Value
The value of the dictionary element.
Definition: ExprObjC.h:244
StringRef getName() const
Return the actual identifier string.
virtual const ObjCMessageExpr * getOriginExpr() const
Definition: CallEvent.h:893
CanQualType CharTy
Definition: ASTContext.h:998
Selector getSelector() const
Definition: CallEvent.h:912
Dataflow Directional Tag Classes.
bool isZeroConstant() const
Definition: SVals.cpp:219
static bool alreadyExecutedAtLeastOneLoopIteration(const ExplodedNode *N, const ObjCForCollectionStmt *FCS)
If the fist block edge is a back edge, we are reentering the loop.
const Expr * getInit() const
Definition: Decl.h:1212
SVal evalEQ(ProgramStateRef state, SVal lhs, SVal rhs)
Represents symbolic expression.
Definition: SVals.h:327
Represents an abstract call to a function or method along a particular path.
Definition: CallEvent.h:140
ObjCMessageKind getMessageKind() const
Returns how the message was written in the source (property access, subscript, or explicit message se...
Definition: CallEvent.cpp:813
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
Represents a pointer to an Objective C object.
Definition: Type.h:5440
bool isInstanceMessage() const
Definition: CallEvent.h:906
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Definition: SVals.h:92
const ExplodedNode *const * const_pred_iterator
ObjCInterfaceDecl * getInterfaceDecl() const
If this pointer points to an Objective @interface type, gets the declaration for that interface...
Definition: Type.h:5496
unsigned getNumElements() const
getNumElements - Return number of elements of objective-c array literal.
Definition: ExprObjC.h:210
Represents Objective-C&#39;s collection statement.
Definition: StmtObjC.h:24
const ProgramStateRef & getState() const
unsigned getNumArgs() const override
Definition: CallEvent.h:899
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2014
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2181
const Expr * getArgExpr(unsigned Index) const override
Definition: CallEvent.h:902
Selector GetUnarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing an unary selector.
Definition: ASTContext.h:2864
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()
bool isVariadic() const
Definition: DeclObjC.h:454
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:265
SValBuilder & getSValBuilder()
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2218
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:270
static Optional< uint64_t > GetCFNumberSize(ASTContext &Ctx, uint64_t i)
CanQualType IntTy
Definition: ASTContext.h:1004
A trivial tuple used to represent a source range.
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
Definition: ProgramPoint.h:152
bool inTopFrame() const
Return true if the current LocationContext has no caller context.
CanQualType DoubleTy
Definition: ASTContext.h:1007
static bool isObjCNSObjectType(QualType Ty)
Return true if this is an NSObject object with its NSObject attribute set.
Definition: ASTContext.h:1994
const LocationContext * getLocationContext() const
const LangOptions & getLangOpts() const
TypedRegion - An abstract class representing regions that are typed.
Definition: MemRegion.h:488