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
160b1ba6227c67d5e04b589ed8a08afa2345a40666Argyrios Kyrtzidis#include "ClangSACheckers.h"
17928c415d5dde89b7c01e41f0dfa8a782cbfa8e7dTed Kremenek#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
18ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h"
19695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h"
20983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
219b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
229b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
23d1e5a89226da79f7e6f43d40facc46abda9e5245Jordy Rose#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
2418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
259b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
269b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
27c4a1dea2dc56bd1357ec91b829a0b9e68229a13eDaniel Dunbar#include "clang/AST/DeclObjC.h"
2899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek#include "clang/AST/Expr.h"
29f494b579b22f9950f5af021f0bf9879a91bb8b41Steve Naroff#include "clang/AST/ExprObjC.h"
3099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek#include "clang/AST/ASTContext.h"
318fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer#include "llvm/ADT/SmallString.h"
3299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
3399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenekusing namespace clang;
349ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
35f1ae705460552655fe7275327804444c62e86baeTed Kremenek
362ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremeneknamespace {
372ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenekclass APIMisuse : public BugType {
382ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenekpublic:
392ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek  APIMisuse(const char* name) : BugType(name, "API Misuse (Apple)") {}
402ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek};
412ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek} // end anonymous namespace
422ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek
432ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek//===----------------------------------------------------------------------===//
442ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek// Utility functions.
452ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek//===----------------------------------------------------------------------===//
462ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek
47b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlssonstatic const char* GetReceiverNameType(const ObjCMessage &msg) {
48432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis  if (const ObjCInterfaceDecl *ID = msg.getReceiverInterface())
49b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson    return ID->getIdentifier()->getNameStart();
50b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson  return 0;
51f1ae705460552655fe7275327804444c62e86baeTed Kremenek}
52f1ae705460552655fe7275327804444c62e86baeTed Kremenek
53b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlssonstatic bool isReceiverClassOrSuperclass(const ObjCInterfaceDecl *ID,
545f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                                        StringRef ClassName) {
55b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson  if (ID->getIdentifier()->getName() == ClassName)
56b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson    return true;
57b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson
58b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson  if (const ObjCInterfaceDecl *Super = ID->getSuperClass())
59b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson    return isReceiverClassOrSuperclass(Super, ClassName);
60f1ae705460552655fe7275327804444c62e86baeTed Kremenek
61b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson  return false;
622ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek}
631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
642ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenekstatic inline bool isNil(SVal X) {
652ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek  return isa<loc::ConcreteInt>(X);
662ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek}
671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
682ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek//===----------------------------------------------------------------------===//
692ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek// NilArgChecker - Check for prohibited nil arguments to ObjC method calls.
702ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek//===----------------------------------------------------------------------===//
7199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
72cb9c07418b699bd2b8384d31ff4392df7d76eb7cBenjamin Kramernamespace {
73ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis  class NilArgChecker : public Checker<check::PreObjCMessage> {
746f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith    mutable OwningPtr<APIMisuse> BT;
7574eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis
7674eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis    void WarnNilArg(CheckerContext &C,
7774eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis                    const ObjCMessage &msg, unsigned Arg) const;
7874eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis
79cb9c07418b699bd2b8384d31ff4392df7d76eb7cBenjamin Kramer  public:
8074eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis    void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
81cb9c07418b699bd2b8384d31ff4392df7d76eb7cBenjamin Kramer  };
82cb9c07418b699bd2b8384d31ff4392df7d76eb7cBenjamin Kramer}
831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
842ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenekvoid NilArgChecker::WarnNilArg(CheckerContext &C,
85432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis                               const ObjCMessage &msg,
8674eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis                               unsigned int Arg) const
872ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek{
882ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek  if (!BT)
8974eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis    BT.reset(new APIMisuse("nil argument"));
902ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek
91d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek  if (ExplodedNode *N = C.generateSink()) {
92f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith    SmallString<128> sbuf;
932ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    llvm::raw_svector_ostream os(sbuf);
94432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis    os << "Argument to '" << GetReceiverNameType(msg) << "' method '"
95432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis       << msg.getSelector().getAsString() << "' cannot be nil";
961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
97e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    BugReport *R = new BugReport(*BT, os.str(), N);
98432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis    R->addRange(msg.getArgSourceRange(Arg));
992ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    C.EmitReport(R);
100f1ae705460552655fe7275327804444c62e86baeTed Kremenek  }
101527556184b276c545be1355ad596fce29a0400fbTed Kremenek}
102527556184b276c545be1355ad596fce29a0400fbTed Kremenek
10374eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidisvoid NilArgChecker::checkPreObjCMessage(ObjCMessage msg,
10474eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis                                        CheckerContext &C) const {
105b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson  const ObjCInterfaceDecl *ID = msg.getReceiverInterface();
106b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson  if (!ID)
1072ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    return;
1082ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek
109b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson  if (isReceiverClassOrSuperclass(ID, "NSString")) {
110432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis    Selector S = msg.getSelector();
1112ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek
1122ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    if (S.isUnarySelector())
1132ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek      return;
1142ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek
1152ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    // FIXME: This is going to be really slow doing these checks with
1162ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    //  lexical comparisons.
1172ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek
1182ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    std::string NameStr = S.getAsString();
1195f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    StringRef Name(NameStr);
1202ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    assert(!Name.empty());
1212ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek
1222ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    // FIXME: Checking for initWithFormat: will not work in most cases
1232ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    //  yet because [NSString alloc] returns id, not NSString*.  We will
1242ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    //  need support for tracking expected-type information in the analyzer
1252ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    //  to find these errors.
1262ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    if (Name == "caseInsensitiveCompare:" ||
1272ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek        Name == "compare:" ||
1282ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek        Name == "compare:options:" ||
1292ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek        Name == "compare:options:range:" ||
1302ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek        Name == "compare:options:range:locale:" ||
1312ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek        Name == "componentsSeparatedByCharactersInSet:" ||
1322ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek        Name == "initWithFormat:") {
1335eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek      if (isNil(msg.getArgSVal(0, C.getLocationContext(), C.getState())))
134432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis        WarnNilArg(C, msg, 0);
1352ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    }
1364ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  }
13799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek}
13804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
13904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek//===----------------------------------------------------------------------===//
14004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek// Error reporting.
14104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek//===----------------------------------------------------------------------===//
14204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
14304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremeneknamespace {
144ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass CFNumberCreateChecker : public Checker< check::PreStmt<CallExpr> > {
1456f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  mutable OwningPtr<APIMisuse> BT;
14674eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis  mutable IdentifierInfo* II;
14704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenekpublic:
14874eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis  CFNumberCreateChecker() : II(0) {}
14974eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis
15074eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
15174eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis
15204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenekprivate:
1539c378f705405d37f49795d5e915989de774fe11fTed Kremenek  void EmitError(const TypedRegion* R, const Expr *Ex,
1541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind);
15504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek};
15604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek} // end anonymous namespace
15704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
15804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenekenum CFNumberType {
15904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberSInt8Type = 1,
16004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberSInt16Type = 2,
16104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberSInt32Type = 3,
16204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberSInt64Type = 4,
16304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberFloat32Type = 5,
16404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberFloat64Type = 6,
16504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberCharType = 7,
16604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberShortType = 8,
16704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberIntType = 9,
16804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberLongType = 10,
16904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberLongLongType = 11,
17004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberFloatType = 12,
17104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberDoubleType = 13,
17204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberCFIndexType = 14,
17304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberNSIntegerType = 15,
17404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberCGFloatType = 16
17504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek};
17604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
17704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremeneknamespace {
17804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  template<typename T>
17904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  class Optional {
18004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    bool IsKnown;
18104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    T Val;
18204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  public:
18304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    Optional() : IsKnown(false), Val(0) {}
18404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    Optional(const T& val) : IsKnown(true), Val(val) {}
1851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
18604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    bool isKnown() const { return IsKnown; }
18704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
18804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    const T& getValue() const {
18904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek      assert (isKnown());
19004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek      return Val;
19104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    }
19204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
19304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    operator const T&() const {
19404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek      return getValue();
19504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    }
19604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  };
19704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek}
19804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
1999c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic Optional<uint64_t> GetCFNumberSize(ASTContext &Ctx, uint64_t i) {
2002550d70aabb5f603e8f74cc5fb6a69a7af5b51f3Nuno Lopes  static const unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 };
2011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
20204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  if (i < kCFNumberCharType)
20304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    return FixedSize[i-1];
2041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
20504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  QualType T;
2061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
20704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  switch (i) {
20804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberCharType:     T = Ctx.CharTy;     break;
20904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberShortType:    T = Ctx.ShortTy;    break;
21004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberIntType:      T = Ctx.IntTy;      break;
21104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberLongType:     T = Ctx.LongTy;     break;
21204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberLongLongType: T = Ctx.LongLongTy; break;
21304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberFloatType:    T = Ctx.FloatTy;    break;
21404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberDoubleType:   T = Ctx.DoubleTy;   break;
21504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberCFIndexType:
21604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberNSIntegerType:
21704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberCGFloatType:
2181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      // FIXME: We need a way to map from names to Type*.
21904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    default:
22004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek      return Optional<uint64_t>();
22104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  }
2221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
22304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  return Ctx.getTypeSize(T);
22404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek}
22504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
22604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek#if 0
22704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenekstatic const char* GetCFNumberTypeStr(uint64_t i) {
22804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  static const char* Names[] = {
22904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberSInt8Type",
23004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberSInt16Type",
23104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberSInt32Type",
23204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberSInt64Type",
23304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberFloat32Type",
23404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberFloat64Type",
23504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberCharType",
23604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberShortType",
23704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberIntType",
23804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberLongType",
23904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberLongLongType",
24004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberFloatType",
24104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberDoubleType",
24204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberCFIndexType",
24304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberNSIntegerType",
24404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberCGFloatType"
24504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  };
2461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
24704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  return i <= kCFNumberCGFloatType ? Names[i-1] : "Invalid CFNumberType";
24804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek}
24904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek#endif
25004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
25174eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidisvoid CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
25274eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis                                         CheckerContext &C) const {
2538bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek  ProgramStateRef state = C.getState();
254b805c8ff133ef0c62df032fa711d6b13c5afd7f4Anna Zaks  const FunctionDecl *FD = C.getCalleeDecl(CE);
2552ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek  if (!FD)
2562ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    return;
2572ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek
2582ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek  ASTContext &Ctx = C.getASTContext();
2592ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek  if (!II)
2602ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    II = &Ctx.Idents.get("CFNumberCreate");
2612ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek
2622ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek  if (FD->getIdentifier() != II || CE->getNumArgs() != 3)
2632ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    return;
2641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
26504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // Get the value of the "theType" argument.
2665eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek  const LocationContext *LCtx = C.getLocationContext();
2675eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek  SVal TheTypeVal = state->getSVal(CE->getArg(1), LCtx);
2681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2692ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek  // FIXME: We really should allow ranges of valid theType values, and
2702ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek  //   bifurcate the state appropriately.
2711c96b24285d05c0eac455ae96d7c9ff43d42bc96Zhongxing Xu  nonloc::ConcreteInt* V = dyn_cast<nonloc::ConcreteInt>(&TheTypeVal);
27204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  if (!V)
2732ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    return;
2741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
27504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  uint64_t NumberKind = V->getValue().getLimitedValue();
27604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  Optional<uint64_t> TargetSize = GetCFNumberSize(Ctx, NumberKind);
2771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
27804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // FIXME: In some cases we can emit an error.
27904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  if (!TargetSize.isKnown())
2802ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    return;
2811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
28204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // Look at the value of the integer being passed by reference.  Essentially
28304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // we want to catch cases where the value passed in is not equal to the
28404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // size of the type being created.
2855eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek  SVal TheValueExpr = state->getSVal(CE->getArg(2), LCtx);
2861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
28704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // FIXME: Eventually we should handle arbitrary locations.  We can do this
28804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  //  by having an enhanced memory model that does low-level typing.
2891c96b24285d05c0eac455ae96d7c9ff43d42bc96Zhongxing Xu  loc::MemRegionVal* LV = dyn_cast<loc::MemRegionVal>(&TheValueExpr);
29004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  if (!LV)
2912ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    return;
2921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2939697934650354bed2e509d8e7e44f21a1fb00f76Ted Kremenek  const TypedValueRegion* R = dyn_cast<TypedValueRegion>(LV->stripCasts());
2945e77ebae47099d76020e84e604b33bb33c9006c3Ted Kremenek  if (!R)
2952ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    return;
2965e77ebae47099d76020e84e604b33bb33c9006c3Ted Kremenek
297018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu  QualType T = Ctx.getCanonicalType(R->getValueType());
2981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
29904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // FIXME: If the pointee isn't an integer type, should we flag a warning?
30004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  //  People can do weird stuff with pointers.
3011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (!T->isIntegerType())
3032ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    return;
3041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
30504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  uint64_t SourceSize = Ctx.getTypeSize(T);
3061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
30704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // CHECK: is SourceSize == TargetSize
30804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  if (SourceSize == TargetSize)
3092ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    return;
3101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3112ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek  // Generate an error.  Only generate a sink if 'SourceSize < TargetSize';
3122ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek  // otherwise generate a regular node.
3132ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek  //
31404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // FIXME: We can actually create an abstract "CFNumber" object that has
31504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  //  the bits initialized to the provided values.
3162ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek  //
317d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek  if (ExplodedNode *N = SourceSize < TargetSize ? C.generateSink()
3180bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks                                                : C.addTransition()) {
319f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith    SmallString<128> sbuf;
3202ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    llvm::raw_svector_ostream os(sbuf);
3212ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek
3222ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    os << (SourceSize == 8 ? "An " : "A ")
3232ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek       << SourceSize << " bit integer is used to initialize a CFNumber "
3242ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek                        "object that represents "
3252ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek       << (TargetSize == 8 ? "an " : "a ")
3262ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek       << TargetSize << " bit integer. ";
3272ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek
3282ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    if (SourceSize < TargetSize)
3292ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek      os << (TargetSize - SourceSize)
3302ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek      << " bits of the CFNumber value will be garbage." ;
3312ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    else
3322ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek      os << (SourceSize - TargetSize)
3332ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek      << " bits of the input integer will be lost.";
33404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
3352ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    if (!BT)
33674eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis      BT.reset(new APIMisuse("Bad use of CFNumberCreate"));
3372ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek
338e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    BugReport *report = new BugReport(*BT, os.str(), N);
3392ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    report->addRange(CE->getArg(2)->getSourceRange());
3402ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    C.EmitReport(report);
3412ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek  }
34204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek}
34304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
34478d46242e3351484c2b773f5610beba5d316914bTed Kremenek//===----------------------------------------------------------------------===//
34561fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose// CFRetain/CFRelease checking for null arguments.
34679b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek//===----------------------------------------------------------------------===//
34779b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek
34879b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremeneknamespace {
349ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass CFRetainReleaseChecker : public Checker< check::PreStmt<CallExpr> > {
3506f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  mutable OwningPtr<APIMisuse> BT;
35174eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis  mutable IdentifierInfo *Retain, *Release;
35279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenekpublic:
35374eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis  CFRetainReleaseChecker(): Retain(0), Release(0) {}
3549c378f705405d37f49795d5e915989de774fe11fTed Kremenek  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
35579b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek};
35679b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek} // end anonymous namespace
35779b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek
35879b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek
3599c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
3609c378f705405d37f49795d5e915989de774fe11fTed Kremenek                                          CheckerContext &C) const {
36179b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  // If the CallExpr doesn't have exactly 1 argument just give up checking.
36279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  if (CE->getNumArgs() != 1)
36361fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose    return;
3641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3658bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek  ProgramStateRef state = C.getState();
366b805c8ff133ef0c62df032fa711d6b13c5afd7f4Anna Zaks  const FunctionDecl *FD = C.getCalleeDecl(CE);
36779b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  if (!FD)
36861fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose    return;
3692ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek
3702ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek  if (!BT) {
3712ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    ASTContext &Ctx = C.getASTContext();
3722ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    Retain = &Ctx.Idents.get("CFRetain");
3732ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    Release = &Ctx.Idents.get("CFRelease");
37474eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis    BT.reset(new APIMisuse("null passed to CFRetain/CFRelease"));
3752ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek  }
3761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
37761fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose  // Check if we called CFRetain/CFRelease.
3781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const IdentifierInfo *FuncII = FD->getIdentifier();
37979b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  if (!(FuncII == Retain || FuncII == Release))
38061fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose    return;
38161fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose
38261fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose  // FIXME: The rest of this just checks that the argument is non-null.
38361fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose  // It should probably be refactored and combined with AttrNonNullChecker.
38461fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose
38561fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose  // Get the argument's value.
38661fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose  const Expr *Arg = CE->getArg(0);
3875eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek  SVal ArgVal = state->getSVal(Arg, C.getLocationContext());
38861fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose  DefinedSVal *DefArgVal = dyn_cast<DefinedSVal>(&ArgVal);
38961fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose  if (!DefArgVal)
39061fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose    return;
39161fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose
39261fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose  // Get a NULL value.
393c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek  SValBuilder &svalBuilder = C.getSValBuilder();
394c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek  DefinedSVal zero = cast<DefinedSVal>(svalBuilder.makeZeroVal(Arg->getType()));
39561fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose
39661fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose  // Make an expression asserting that they're equal.
397c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek  DefinedOrUnknownSVal ArgIsNull = svalBuilder.evalEQ(state, zero, *DefArgVal);
39861fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose
39961fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose  // Are they equal?
4008bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek  ProgramStateRef stateTrue, stateFalse;
40128f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek  llvm::tie(stateTrue, stateFalse) = state->assume(ArgIsNull);
40261fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose
40361fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose  if (stateTrue && !stateFalse) {
404d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek    ExplodedNode *N = C.generateSink(stateTrue);
40561fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose    if (!N)
40661fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose      return;
4071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
40879b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    const char *description = (FuncII == Retain)
40979b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek                            ? "Null pointer argument in call to CFRetain"
41079b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek                            : "Null pointer argument in call to CFRelease";
41179b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek
412e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    BugReport *report = new BugReport(*BT, description, N);
41361fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose    report->addRange(Arg->getSourceRange());
41476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek    report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Arg,
41576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek                                                                    report));
41661fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose    C.EmitReport(report);
41761fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose    return;
41861fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose  }
4191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
42061fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose  // From here on, we know the argument is non-null.
4210bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks  C.addTransition(stateFalse);
42279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek}
42379b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek
42479b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek//===----------------------------------------------------------------------===//
42550e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek// Check for sending 'retain', 'release', or 'autorelease' directly to a Class.
42650e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek//===----------------------------------------------------------------------===//
42750e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
42850e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremeneknamespace {
429ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass ClassReleaseChecker : public Checker<check::PreObjCMessage> {
43074eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis  mutable Selector releaseS;
43174eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis  mutable Selector retainS;
43274eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis  mutable Selector autoreleaseS;
43374eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis  mutable Selector drainS;
4346f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  mutable OwningPtr<BugType> BT;
43550e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
43674eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidispublic:
43774eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis  void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
43850e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek};
43950e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek}
44050e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
44174eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidisvoid ClassReleaseChecker::checkPreObjCMessage(ObjCMessage msg,
44274eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis                                              CheckerContext &C) const {
4432ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek
4442ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek  if (!BT) {
44574eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis    BT.reset(new APIMisuse("message incorrectly sent to class instead of class "
44674eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis                           "instance"));
4472ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek
4482ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    ASTContext &Ctx = C.getASTContext();
4492ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    releaseS = GetNullarySelector("release", Ctx);
4502ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    retainS = GetNullarySelector("retain", Ctx);
4512ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    autoreleaseS = GetNullarySelector("autorelease", Ctx);
4522ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    drainS = GetNullarySelector("drain", Ctx);
4532ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek  }
4542ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek
455432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis  if (msg.isInstanceMessage())
45650e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek    return;
457432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis  const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
458432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis  assert(Class);
45904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor
460432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis  Selector S = msg.getSelector();
461921ddc4e7ef35d77965205d91582c356cb54f5efBenjamin Kramer  if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
46250e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek    return;
46350e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
4640bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks  if (ExplodedNode *N = C.addTransition()) {
465f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith    SmallString<200> buf;
4662ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    llvm::raw_svector_ostream os(buf);
46750e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
4682ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    os << "The '" << S.getAsString() << "' message should be sent to instances "
4692ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek          "of class '" << Class->getName()
4702ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek       << "' and not the class directly";
47150e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
472e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    BugReport *report = new BugReport(*BT, os.str(), N);
473432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis    report->addRange(msg.getSourceRange());
4742ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek    C.EmitReport(report);
4752ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek  }
47650e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek}
47750e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
47850e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek//===----------------------------------------------------------------------===//
4794597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson// Check for passing non-Objective-C types to variadic methods that expect
4804597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson// only Objective-C types.
4814597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson//===----------------------------------------------------------------------===//
4824597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
4834597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlssonnamespace {
4844597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlssonclass VariadicMethodTypeChecker : public Checker<check::PreObjCMessage> {
4854597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  mutable Selector arrayWithObjectsS;
4864597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  mutable Selector dictionaryWithObjectsAndKeysS;
4874597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  mutable Selector setWithObjectsS;
488f439e00c7055d2d51b88141f63ebfc893af10951Jordy Rose  mutable Selector orderedSetWithObjectsS;
4894597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  mutable Selector initWithObjectsS;
4904597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  mutable Selector initWithObjectsAndKeysS;
4916f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  mutable OwningPtr<BugType> BT;
4924597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
4934597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  bool isVariadicMessage(const ObjCMessage &msg) const;
4944597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
4954597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlssonpublic:
4964597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
4974597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson};
4984597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson}
4994597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
5004597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson/// isVariadicMessage - Returns whether the given message is a variadic message,
5014597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson/// where all arguments must be Objective-C types.
5024597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlssonbool
5034597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders CarlssonVariadicMethodTypeChecker::isVariadicMessage(const ObjCMessage &msg) const {
5044597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  const ObjCMethodDecl *MD = msg.getMethodDecl();
5059281efe614741f3742ebf8196a703f6c923c6ff0Ted Kremenek
5069281efe614741f3742ebf8196a703f6c923c6ff0Ted Kremenek  if (!MD || !MD->isVariadic() || isa<ObjCProtocolDecl>(MD->getDeclContext()))
5074597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    return false;
5084597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
5094597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  Selector S = msg.getSelector();
5104597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
5114597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  if (msg.isInstanceMessage()) {
5124597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    // FIXME: Ideally we'd look at the receiver interface here, but that's not
5134597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    // useful for init, because alloc returns 'id'. In theory, this could lead
5144597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    // to false positives, for example if there existed a class that had an
5154597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    // initWithObjects: implementation that does accept non-Objective-C pointer
5164597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    // types, but the chance of that happening is pretty small compared to the
5174597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    // gains that this analysis gives.
5184597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    const ObjCInterfaceDecl *Class = MD->getClassInterface();
5194597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
5204597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    // -[NSArray initWithObjects:]
5214597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    if (isReceiverClassOrSuperclass(Class, "NSArray") &&
5224597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson        S == initWithObjectsS)
5234597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson      return true;
5244597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
5254597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    // -[NSDictionary initWithObjectsAndKeys:]
5264597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    if (isReceiverClassOrSuperclass(Class, "NSDictionary") &&
5274597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson        S == initWithObjectsAndKeysS)
5284597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson      return true;
5294597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
5304597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    // -[NSSet initWithObjects:]
5314597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    if (isReceiverClassOrSuperclass(Class, "NSSet") &&
5324597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson        S == initWithObjectsS)
5334597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson      return true;
534f439e00c7055d2d51b88141f63ebfc893af10951Jordy Rose
535f439e00c7055d2d51b88141f63ebfc893af10951Jordy Rose    // -[NSOrderedSet initWithObjects:]
536f439e00c7055d2d51b88141f63ebfc893af10951Jordy Rose    if (isReceiverClassOrSuperclass(Class, "NSOrderedSet") &&
537f439e00c7055d2d51b88141f63ebfc893af10951Jordy Rose        S == initWithObjectsS)
538f439e00c7055d2d51b88141f63ebfc893af10951Jordy Rose      return true;
5394597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  } else {
5404597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
5414597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
5424597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    // -[NSArray arrayWithObjects:]
5434597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    if (isReceiverClassOrSuperclass(Class, "NSArray") &&
5444597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson        S == arrayWithObjectsS)
5454597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson      return true;
5464597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
5474597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    // -[NSDictionary dictionaryWithObjectsAndKeys:]
5484597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    if (isReceiverClassOrSuperclass(Class, "NSDictionary") &&
5494597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson        S == dictionaryWithObjectsAndKeysS)
5504597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson      return true;
5514597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
5524597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    // -[NSSet setWithObjects:]
5534597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    if (isReceiverClassOrSuperclass(Class, "NSSet") &&
5544597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson        S == setWithObjectsS)
5554597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson      return true;
556f439e00c7055d2d51b88141f63ebfc893af10951Jordy Rose
557f439e00c7055d2d51b88141f63ebfc893af10951Jordy Rose    // -[NSOrderedSet orderedSetWithObjects:]
558f439e00c7055d2d51b88141f63ebfc893af10951Jordy Rose    if (isReceiverClassOrSuperclass(Class, "NSOrderedSet") &&
559f439e00c7055d2d51b88141f63ebfc893af10951Jordy Rose        S == orderedSetWithObjectsS)
560f439e00c7055d2d51b88141f63ebfc893af10951Jordy Rose      return true;
5614597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  }
5624597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
5634597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  return false;
5644597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson}
5654597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
5664597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlssonvoid VariadicMethodTypeChecker::checkPreObjCMessage(ObjCMessage msg,
5674597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson                                                    CheckerContext &C) const {
5684597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  if (!BT) {
5694597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    BT.reset(new APIMisuse("Arguments passed to variadic method aren't all "
5704597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson                           "Objective-C pointer types"));
5714597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
5724597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    ASTContext &Ctx = C.getASTContext();
5734597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    arrayWithObjectsS = GetUnarySelector("arrayWithObjects", Ctx);
5744597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    dictionaryWithObjectsAndKeysS =
5754597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson      GetUnarySelector("dictionaryWithObjectsAndKeys", Ctx);
5764597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    setWithObjectsS = GetUnarySelector("setWithObjects", Ctx);
577f439e00c7055d2d51b88141f63ebfc893af10951Jordy Rose    orderedSetWithObjectsS = GetUnarySelector("orderedSetWithObjects", Ctx);
5784597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
5794597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    initWithObjectsS = GetUnarySelector("initWithObjects", Ctx);
5804597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    initWithObjectsAndKeysS = GetUnarySelector("initWithObjectsAndKeys", Ctx);
5814597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  }
5824597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
5834597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  if (!isVariadicMessage(msg))
5844597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson      return;
5854597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
5864597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  // We are not interested in the selector arguments since they have
5874597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  // well-defined types, so the compiler will issue a warning for them.
5884597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  unsigned variadicArgsBegin = msg.getSelector().getNumArgs();
5894597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
5904597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  // We're not interested in the last argument since it has to be nil or the
5914597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  // compiler would have issued a warning for it elsewhere.
5924597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  unsigned variadicArgsEnd = msg.getNumArgs() - 1;
5934597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
5944597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  if (variadicArgsEnd <= variadicArgsBegin)
5954597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    return;
5964597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
5974597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  // Verify that all arguments have Objective-C types.
5986fb5c1facaf36795a8c1050cd901e0e829ac1a64Ted Kremenek  llvm::Optional<ExplodedNode*> errorNode;
5998bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek  ProgramStateRef state = C.getState();
6006fb5c1facaf36795a8c1050cd901e0e829ac1a64Ted Kremenek
6014597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  for (unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) {
6024597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    QualType ArgTy = msg.getArgType(I);
6034597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    if (ArgTy->isObjCObjectPointerType())
6044597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson      continue;
6054597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
606f05982b5f8f69a1d618c3bd844ab6efd3a6e2953Anders Carlsson    // Block pointers are treaded as Objective-C pointers.
607f05982b5f8f69a1d618c3bd844ab6efd3a6e2953Anders Carlsson    if (ArgTy->isBlockPointerType())
608f05982b5f8f69a1d618c3bd844ab6efd3a6e2953Anders Carlsson      continue;
609f05982b5f8f69a1d618c3bd844ab6efd3a6e2953Anders Carlsson
610d5fde2106af8e78cc1b97d6369ad0de5d0875491Ted Kremenek    // Ignore pointer constants.
6115eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    if (isa<loc::ConcreteInt>(msg.getArgSVal(I, C.getLocationContext(),
6125eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek                                             state)))
613d5fde2106af8e78cc1b97d6369ad0de5d0875491Ted Kremenek      continue;
614928c415d5dde89b7c01e41f0dfa8a782cbfa8e7dTed Kremenek
615f3f929386254a53c398fa884848738113a73ca23Ted Kremenek    // Ignore pointer types annotated with 'NSObject' attribute.
616f3f929386254a53c398fa884848738113a73ca23Ted Kremenek    if (C.getASTContext().isObjCNSObjectType(ArgTy))
617f3f929386254a53c398fa884848738113a73ca23Ted Kremenek      continue;
618f3f929386254a53c398fa884848738113a73ca23Ted Kremenek
619928c415d5dde89b7c01e41f0dfa8a782cbfa8e7dTed Kremenek    // Ignore CF references, which can be toll-free bridged.
6200556048ae8ff743d0abb9fa88a0d0ee8e9123742Ted Kremenek    if (coreFoundation::isCFObjectRef(ArgTy))
621928c415d5dde89b7c01e41f0dfa8a782cbfa8e7dTed Kremenek      continue;
622d5fde2106af8e78cc1b97d6369ad0de5d0875491Ted Kremenek
6236fb5c1facaf36795a8c1050cd901e0e829ac1a64Ted Kremenek    // Generate only one error node to use for all bug reports.
6246fb5c1facaf36795a8c1050cd901e0e829ac1a64Ted Kremenek    if (!errorNode.hasValue()) {
6250bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks      errorNode = C.addTransition();
6266fb5c1facaf36795a8c1050cd901e0e829ac1a64Ted Kremenek    }
6276fb5c1facaf36795a8c1050cd901e0e829ac1a64Ted Kremenek
6286fb5c1facaf36795a8c1050cd901e0e829ac1a64Ted Kremenek    if (!errorNode.getValue())
6294597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson      continue;
6304597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
631f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith    SmallString<128> sbuf;
6324597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    llvm::raw_svector_ostream os(sbuf);
6334597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
6344597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    if (const char *TypeName = GetReceiverNameType(msg))
6354597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson      os << "Argument to '" << TypeName << "' method '";
6364597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    else
6374597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson      os << "Argument to method '";
6384597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
6394597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    os << msg.getSelector().getAsString()
6404597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson      << "' should be an Objective-C pointer type, not '"
6414597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson      << ArgTy.getAsString() << "'";
6424597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
643e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    BugReport *R = new BugReport(*BT, os.str(),
6446fb5c1facaf36795a8c1050cd901e0e829ac1a64Ted Kremenek                                             errorNode.getValue());
6454597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    R->addRange(msg.getArgSourceRange(I));
6464597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson    C.EmitReport(R);
6474597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  }
6484597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson}
6494597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
6504597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson//===----------------------------------------------------------------------===//
65178d46242e3351484c2b773f5610beba5d316914bTed Kremenek// Check registration.
65279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek//===----------------------------------------------------------------------===//
6530b1ba6227c67d5e04b589ed8a08afa2345a40666Argyrios Kyrtzidis
654695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidisvoid ento::registerNilArgChecker(CheckerManager &mgr) {
65574eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis  mgr.registerChecker<NilArgChecker>();
6560b1ba6227c67d5e04b589ed8a08afa2345a40666Argyrios Kyrtzidis}
6570b1ba6227c67d5e04b589ed8a08afa2345a40666Argyrios Kyrtzidis
658695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidisvoid ento::registerCFNumberCreateChecker(CheckerManager &mgr) {
65974eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis  mgr.registerChecker<CFNumberCreateChecker>();
6600b1ba6227c67d5e04b589ed8a08afa2345a40666Argyrios Kyrtzidis}
6610b1ba6227c67d5e04b589ed8a08afa2345a40666Argyrios Kyrtzidis
662695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidisvoid ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
66374eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis  mgr.registerChecker<CFRetainReleaseChecker>();
66478d46242e3351484c2b773f5610beba5d316914bTed Kremenek}
665695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis
666695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidisvoid ento::registerClassReleaseChecker(CheckerManager &mgr) {
66774eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis  mgr.registerChecker<ClassReleaseChecker>();
668695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis}
6694597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson
6704597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlssonvoid ento::registerVariadicMethodTypeChecker(CheckerManager &mgr) {
6714597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson  mgr.registerChecker<VariadicMethodTypeChecker>();
6724597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson}
673