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" 23087611edSJordy Rose #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 24f8cbac4bSTed Kremenek #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 25087611edSJordy Rose #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.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: 39aad83725SArgyrios Kyrtzidis void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const; 40d99bd55aSTed Kremenek }; 41d99bd55aSTed Kremenek 42d99bd55aSTed Kremenek } // end anonymous namespace 43d99bd55aSTed Kremenek 44aad83725SArgyrios Kyrtzidis void NSAutoreleasePoolChecker::checkPreObjCMessage(ObjCMessage msg, 45aad83725SArgyrios Kyrtzidis CheckerContext &C) const { 46d99bd55aSTed Kremenek 4737ab726dSArgyrios Kyrtzidis const Expr *receiver = msg.getInstanceReceiver(); 48d99bd55aSTed Kremenek if (!receiver) 49d99bd55aSTed Kremenek return; 50d99bd55aSTed Kremenek 51d99bd55aSTed Kremenek // FIXME: Enhance with value-tracking information instead of consulting 52d99bd55aSTed Kremenek // the type of the expression. 53d99bd55aSTed Kremenek const ObjCObjectPointerType* PT = 54d99bd55aSTed Kremenek receiver->getType()->getAs<ObjCObjectPointerType>(); 55d99bd55aSTed Kremenek 56d99bd55aSTed Kremenek if (!PT) 57d99bd55aSTed Kremenek return; 58d99bd55aSTed Kremenek const ObjCInterfaceDecl *OD = PT->getInterfaceDecl(); 59d99bd55aSTed Kremenek if (!OD) 60d99bd55aSTed Kremenek return; 61d99bd55aSTed Kremenek if (!OD->getIdentifier()->getName().equals("NSAutoreleasePool")) 62d99bd55aSTed Kremenek return; 63d99bd55aSTed Kremenek 64aad83725SArgyrios Kyrtzidis if (releaseS.isNull()) 65aad83725SArgyrios Kyrtzidis releaseS = GetNullarySelector("release", C.getASTContext()); 66d99bd55aSTed Kremenek // Sending 'release' message? 6737ab726dSArgyrios Kyrtzidis if (msg.getSelector() != releaseS) 68d99bd55aSTed Kremenek return; 69d99bd55aSTed Kremenek 706b1c2126SAnna Zaks if (!BT) 716b1c2126SAnna Zaks BT.reset(new BugType("Use -drain instead of -release", 726b1c2126SAnna Zaks "API Upgrade (Apple)")); 736b1c2126SAnna Zaks 746b1c2126SAnna Zaks ExplodedNode *N = C.addTransition(); 756b1c2126SAnna Zaks if (!N) { 766b1c2126SAnna Zaks assert(0); 776b1c2126SAnna Zaks return; 786b1c2126SAnna Zaks } 796b1c2126SAnna Zaks 806b1c2126SAnna Zaks BugReport *Report = new BugReport(*BT, "Use -drain instead of -release when " 816b1c2126SAnna Zaks "using NSAutoreleasePool and garbage collection", N); 826b1c2126SAnna Zaks Report->addRange(msg.getSourceRange()); 836b1c2126SAnna Zaks C.EmitReport(Report); 84d99bd55aSTed Kremenek } 85aad83725SArgyrios Kyrtzidis 86aad83725SArgyrios Kyrtzidis void ento::registerNSAutoreleasePoolChecker(CheckerManager &mgr) { 87*bbafb8a7SDavid Blaikie if (mgr.getLangOpts().getGC() != LangOptions::NonGC) 88aad83725SArgyrios Kyrtzidis mgr.registerChecker<NSAutoreleasePoolChecker>(); 89aad83725SArgyrios Kyrtzidis } 90