BasicObjCFoundationChecks.cpp revision 4ba6283f9c7db4513ca2d9cbde7df3a58ba941f7
199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//== BasicObjCFoundationChecks.cpp - Simple Apple-Foundation checks -*- C++ -*--
299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//
399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//                     The LLVM Compiler Infrastructure
499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//
599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek// This file is distributed under the University of Illinois Open Source
699c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek// License. See LICENSE.TXT for details.
799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//
899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//===----------------------------------------------------------------------===//
999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//
1099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//  This file defines BasicObjCFoundationChecks, a class that encapsulates
1199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//  a set of simple checks to run on Objective-C code using Apple's Foundation
1299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//  classes.
1399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//
1499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//===----------------------------------------------------------------------===//
1599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
16527556184b276c545be1355ad596fce29a0400fbTed Kremenek#include "BasicObjCFoundationChecks.h"
17527556184b276c545be1355ad596fce29a0400fbTed Kremenek
1899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
1999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek#include "clang/Analysis/PathSensitive/GRSimpleAPICheck.h"
2099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek#include "clang/Analysis/PathSensitive/ValueState.h"
2199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek#include "clang/Analysis/PathSensitive/AnnotatedPath.h"
2299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek#include "clang/Analysis/PathDiagnostic.h"
2399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek#include "clang/AST/Expr.h"
2499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek#include "clang/AST/ASTContext.h"
2599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek#include "llvm/Support/Compiler.h"
2699c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
2799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek#include <vector>
284ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek#include <sstream>
2999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
3099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenekusing namespace clang;
3199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
3299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremeneknamespace {
3399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
3499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenekclass VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck {
3599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
36e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek  ASTContext &Ctx;
37e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek  ValueStateManager* VMgr;
38e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek
39e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek  typedef std::list<AnnotatedPath<ValueState> > ErrorsTy;
40e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek  ErrorsTy Errors;
4199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
42e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek  RVal GetRVal(ValueState* St, Expr* E) { return VMgr->GetRVal(St, E); }
4399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
44e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek  bool isNSString(ObjCInterfaceType* T, const char* suffix);
45e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek  bool AuditNSString(NodeTy* N, ObjCMessageExpr* ME);
4699c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
474ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  void Warn(NodeTy* N, Expr* E, const std::string& s);
484ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  void WarnNilArg(NodeTy* N, Expr* E);
494ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
504ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  bool CheckNilArg(NodeTy* N, unsigned Arg);
5199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
5299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenekpublic:
5399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  BasicObjCFoundationChecks(ASTContext& ctx, ValueStateManager* vmgr)
5499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek    : Ctx(ctx), VMgr(vmgr) {}
5599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
5699c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  virtual ~BasicObjCFoundationChecks() {}
5799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
5899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  virtual bool Audit(ExplodedNode<ValueState>* N);
59e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek
60e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek  virtual void ReportResults(Diagnostic& D);
61e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek
6299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek};
6399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
6499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek} // end anonymous namespace
6599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
6699c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
67527556184b276c545be1355ad596fce29a0400fbTed KremenekGRSimpleAPICheck*
68527556184b276c545be1355ad596fce29a0400fbTed Kremenekclang::CreateBasicObjCFoundationChecks(ASTContext& Ctx,
69527556184b276c545be1355ad596fce29a0400fbTed Kremenek                                       ValueStateManager* VMgr) {
70527556184b276c545be1355ad596fce29a0400fbTed Kremenek
71527556184b276c545be1355ad596fce29a0400fbTed Kremenek  return new BasicObjCFoundationChecks(Ctx, VMgr);
72527556184b276c545be1355ad596fce29a0400fbTed Kremenek}
73527556184b276c545be1355ad596fce29a0400fbTed Kremenek
744ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenekstatic ObjCInterfaceType* GetReceiverType(ObjCMessageExpr* ME) {
7599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  Expr* Receiver = ME->getReceiver();
7699c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
7799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  if (!Receiver)
784ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    return NULL;
7999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
8099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  assert (Receiver->getType()->isPointerType());
814ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
8299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  const PointerType* T = Receiver->getType()->getAsPointerType();
834ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
844ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  return dyn_cast<ObjCInterfaceType>(T->getPointeeType().getTypePtr());
854ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek}
864ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
874ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenekstatic const char* GetReceiverNameType(ObjCMessageExpr* ME) {
884ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  ObjCInterfaceType* ReceiverType = GetReceiverType(ME);
894ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  return ReceiverType ? ReceiverType->getDecl()->getIdentifier()->getName()
904ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek                      : NULL;
914ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek}
9299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
934ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenekbool BasicObjCFoundationChecks::Audit(ExplodedNode<ValueState>* N) {
944ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
954ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  ObjCMessageExpr* ME =
964ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    cast<ObjCMessageExpr>(cast<PostStmt>(N->getLocation()).getStmt());
974ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
984ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  ObjCInterfaceType* ReceiverType = GetReceiverType(ME);
9999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
10099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  if (!ReceiverType)
1014ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    return NULL;
1024ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
1034ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  const char* name = ReceiverType->getDecl()->getIdentifier()->getName();
10499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
1054ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  if (!name)
1064ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    return false;
10799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
10899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  if (name[0] != 'N' || name[1] != 'S')
10999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek    return false;
11099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
11199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  name += 2;
11299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
11399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  // FIXME: Make all of this faster.
11499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
11599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  if (isNSString(ReceiverType, name))
11699c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek    return AuditNSString(N, ME);
11799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
11899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  return false;
11999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek}
12099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
121e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenekstatic inline bool isNil(RVal X) {
122e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek  return isa<lval::ConcreteInt>(X);
123e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek}
124e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek
12599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//===----------------------------------------------------------------------===//
12699c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek// Error reporting.
12799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//===----------------------------------------------------------------------===//
12899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
12999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
1304ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenekvoid BasicObjCFoundationChecks::Warn(NodeTy* N, Expr* E, const std::string& s) {
13199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  Errors.push_back(AnnotatedPath<ValueState>());
1324ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  Errors.back().push_back(N, s, E);
13399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek}
13499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
135e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenekvoid BasicObjCFoundationChecks::ReportResults(Diagnostic& D) {
136e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek
137e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek  // FIXME: Expand errors into paths.  For now, just issue warnings.
138e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek
139e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek  for (ErrorsTy::iterator I=Errors.begin(), E=Errors.end(); I!=E; ++I) {
140e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek
141e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek    AnnotatedNode<ValueState>& AN = I->back();
142e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek
143e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek    unsigned diag = D.getCustomDiagID(Diagnostic::Warning,
144e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek                                      AN.getString().c_str());
145e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek
146e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek    Stmt* S = cast<PostStmt>(AN.getNode()->getLocation()).getStmt();
147e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek    FullSourceLoc L(S->getLocStart(), Ctx.getSourceManager());
148e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek
149e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek    SourceRange R = AN.getExpr()->getSourceRange();
150e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek
1519b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek    D.Report(L, diag, &AN.getString(), 1, &R, 1);
152e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek  }
153e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek}
154e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek
1554ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenekvoid BasicObjCFoundationChecks::WarnNilArg(NodeTy* N, Expr* E) {
1564ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
1574ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  ObjCMessageExpr* ME =
1584ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    cast<ObjCMessageExpr>(cast<PostStmt>(N->getLocation()).getStmt());
1594ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
1604ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  std::ostringstream os;
1614ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
1624ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  os << "Argument to '" << GetReceiverNameType(ME) << "' method '"
1634ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    << ME->getSelector().getName()
1644ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    << "' cannot be nil.";
1654ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
1664ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  Warn(N, E, os.str());
1674ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek}
1684ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
1694ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenekbool BasicObjCFoundationChecks::CheckNilArg(NodeTy* N, unsigned Arg) {
1704ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  ObjCMessageExpr* ME =
1714ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    cast<ObjCMessageExpr>(cast<PostStmt>(N->getLocation()).getStmt());
1724ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
1734ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  Expr * E = ME->getArg(Arg);
1744ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
1754ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  if (isNil(GetRVal(N->getState(), E))) {
1764ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    WarnNilArg(N, E);
1774ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    return true;
1784ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  }
1794ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
1804ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  return false;
1814ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek}
1824ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
18399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//===----------------------------------------------------------------------===//
18499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek// NSString checking.
18599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//===----------------------------------------------------------------------===//
18699c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
18799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenekbool BasicObjCFoundationChecks::isNSString(ObjCInterfaceType* T,
18899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek                                           const char* suffix) {
18999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
19099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  return !strcmp("String", suffix) || !strcmp("MutableString", suffix);
19199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek}
19299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
19399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenekbool BasicObjCFoundationChecks::AuditNSString(NodeTy* N,
19499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek                                              ObjCMessageExpr* ME) {
19599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
19699c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  Selector S = ME->getSelector();
19799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
19899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  if (S.isUnarySelector())
19999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek    return false;
20099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
20199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  // FIXME: This is going to be really slow doing these checks with
20299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  //  lexical comparisons.
20399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
20499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  std::string name = S.getName();
2059b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek  assert (!name.empty());
2069b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek  const char* cstr = &name[0];
2079b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek  unsigned len = name.size();
2084ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
2099b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek  switch (len) {
2109b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek    default:
2119b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek      break;
2129b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek    case 8:
2134ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
2144ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      if (!strcmp(cstr, "compare:"))
2154ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek        return CheckNilArg(N, 0);
2164ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
2174ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      break;
21899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
2194ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    case 16:
2204ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      if (!strcmp(cstr, "compare:options:"))
2214ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek        return CheckNilArg(N, 0);
2224ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
2234ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      break;
2244ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
2254ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    case 22:
2264ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      if (!strcmp(cstr, "compare:options:range:"))
2274ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek        return CheckNilArg(N, 0);
2284ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
2294ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      break;
2304ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
2314ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    case 23:
2324ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
2334ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      if (!strcmp(cstr, "caseInsensitiveCompare:"))
2344ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek        return CheckNilArg(N, 0);
2359b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek
2369b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek      break;
2374ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
2384ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    case 29:
2394ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      if (!strcmp(cstr, "compare:options:range:locale:"))
2404ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek        return CheckNilArg(N, 0);
2414ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
2424ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      break;
2434ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
2444ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    case 37:
2454ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    if (!strcmp(cstr, "componentsSeparatedByCharactersInSet:"))
2464ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      return CheckNilArg(N, 0);
2474ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
2484ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    break;
24999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  }
25099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
25199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  return false;
25299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek}
253