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