1d99bd55aSTed Kremenek //=- NSAutoreleasePoolChecker.cpp --------------------------------*- C++ -*-==// 2d99bd55aSTed Kremenek // 3d99bd55aSTed Kremenek // The LLVM Compiler Infrastructure 4d99bd55aSTed Kremenek // 5d99bd55aSTed Kremenek // This file is distributed under the University of Illinois Open Source 6d99bd55aSTed Kremenek // License. See LICENSE.TXT for details. 7d99bd55aSTed Kremenek // 8d99bd55aSTed Kremenek //===----------------------------------------------------------------------===// 9d99bd55aSTed Kremenek // 10d99bd55aSTed Kremenek // This file defines a NSAutoreleasePoolChecker, a small checker that warns 11d99bd55aSTed Kremenek // about subpar uses of NSAutoreleasePool. Note that while the check itself 12087611edSJordy Rose // (in its current form) could be written as a flow-insensitive check, in 13d99bd55aSTed Kremenek // can be potentially enhanced in the future with flow-sensitive information. 14d99bd55aSTed Kremenek // It is also a good example of the CheckerVisitor interface. 15d99bd55aSTed Kremenek // 16d99bd55aSTed Kremenek //===----------------------------------------------------------------------===// 17d99bd55aSTed Kremenek 189d4d4f91SArgyrios Kyrtzidis #include "ClangSACheckers.h" 196a5674ffSArgyrios Kyrtzidis #include "clang/StaticAnalyzer/Core/Checker.h" 20507ff53eSArgyrios Kyrtzidis #include "clang/StaticAnalyzer/Core/CheckerManager.h" 21f8cbac4bSTed Kremenek #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 226b1c2126SAnna Zaks #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 23*4f7df9beSJordan Rose #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 24087611edSJordy Rose #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 25f8cbac4bSTed Kremenek #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 26d99bd55aSTed Kremenek #include "clang/AST/DeclObjC.h" 27d99bd55aSTed Kremenek #include "clang/AST/Decl.h" 28d99bd55aSTed Kremenek 29d99bd55aSTed Kremenek using namespace clang; 30d99bd55aSTed Kremenek using namespace ento; 31d99bd55aSTed Kremenek 32d99bd55aSTed Kremenek namespace { 33d99bd55aSTed Kremenek class NSAutoreleasePoolChecker 346a5674ffSArgyrios Kyrtzidis : public Checker<check::PreObjCMessage> { 35e2778999SDylan Noblesmith mutable OwningPtr<BugType> BT; 36aad83725SArgyrios Kyrtzidis mutable Selector releaseS; 37d99bd55aSTed Kremenek 38d99bd55aSTed Kremenek public: 39547060b3SJordan Rose void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const; 40d99bd55aSTed Kremenek }; 41d99bd55aSTed Kremenek 42d99bd55aSTed Kremenek } // end anonymous namespace 43d99bd55aSTed Kremenek 44547060b3SJordan Rose void NSAutoreleasePoolChecker::checkPreObjCMessage(const ObjCMethodCall &msg, 45aad83725SArgyrios Kyrtzidis CheckerContext &C) const { 46547060b3SJordan Rose if (!msg.isInstanceMessage()) 47d99bd55aSTed Kremenek return; 48d99bd55aSTed Kremenek 49547060b3SJordan Rose const ObjCInterfaceDecl *OD = msg.getReceiverInterface(); 50d99bd55aSTed Kremenek if (!OD) 51d99bd55aSTed Kremenek return; 52547060b3SJordan Rose if (!OD->getIdentifier()->isStr("NSAutoreleasePool")) 53d99bd55aSTed Kremenek return; 54d99bd55aSTed Kremenek 55aad83725SArgyrios Kyrtzidis if (releaseS.isNull()) 56aad83725SArgyrios Kyrtzidis releaseS = GetNullarySelector("release", C.getASTContext()); 57d99bd55aSTed Kremenek // Sending 'release' message? 5837ab726dSArgyrios Kyrtzidis if (msg.getSelector() != releaseS) 59d99bd55aSTed Kremenek return; 60d99bd55aSTed Kremenek 616b1c2126SAnna Zaks if (!BT) 626b1c2126SAnna Zaks BT.reset(new BugType("Use -drain instead of -release", 636b1c2126SAnna Zaks "API Upgrade (Apple)")); 646b1c2126SAnna Zaks 656b1c2126SAnna Zaks ExplodedNode *N = C.addTransition(); 666b1c2126SAnna Zaks if (!N) { 676b1c2126SAnna Zaks assert(0); 686b1c2126SAnna Zaks return; 696b1c2126SAnna Zaks } 706b1c2126SAnna Zaks 716b1c2126SAnna Zaks BugReport *Report = new BugReport(*BT, "Use -drain instead of -release when " 726b1c2126SAnna Zaks "using NSAutoreleasePool and garbage collection", N); 736b1c2126SAnna Zaks Report->addRange(msg.getSourceRange()); 746b1c2126SAnna Zaks C.EmitReport(Report); 75d99bd55aSTed Kremenek } 76aad83725SArgyrios Kyrtzidis 77aad83725SArgyrios Kyrtzidis void ento::registerNSAutoreleasePoolChecker(CheckerManager &mgr) { 78bbafb8a7SDavid Blaikie if (mgr.getLangOpts().getGC() != LangOptions::NonGC) 79aad83725SArgyrios Kyrtzidis mgr.registerChecker<NSAutoreleasePoolChecker>(); 80aad83725SArgyrios Kyrtzidis } 81