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 12d99bd55aSTed Kremenek // (in it's 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" 19*6a5674ffSArgyrios Kyrtzidis #include "clang/StaticAnalyzer/Core/Checker.h" 20507ff53eSArgyrios Kyrtzidis #include "clang/StaticAnalyzer/Core/CheckerManager.h" 21aad83725SArgyrios Kyrtzidis #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 22f8cbac4bSTed Kremenek #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 23f8cbac4bSTed Kremenek #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 24d99bd55aSTed Kremenek #include "clang/AST/DeclObjC.h" 25d99bd55aSTed Kremenek #include "clang/AST/Decl.h" 26d99bd55aSTed Kremenek 27d99bd55aSTed Kremenek using namespace clang; 28d99bd55aSTed Kremenek using namespace ento; 29d99bd55aSTed Kremenek 30d99bd55aSTed Kremenek namespace { 31d99bd55aSTed Kremenek class NSAutoreleasePoolChecker 32*6a5674ffSArgyrios Kyrtzidis : public Checker<check::PreObjCMessage> { 33d99bd55aSTed Kremenek 34aad83725SArgyrios Kyrtzidis mutable Selector releaseS; 35d99bd55aSTed Kremenek 36d99bd55aSTed Kremenek public: 37aad83725SArgyrios Kyrtzidis void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const; 38d99bd55aSTed Kremenek }; 39d99bd55aSTed Kremenek 40d99bd55aSTed Kremenek } // end anonymous namespace 41d99bd55aSTed Kremenek 42aad83725SArgyrios Kyrtzidis void NSAutoreleasePoolChecker::checkPreObjCMessage(ObjCMessage msg, 43aad83725SArgyrios Kyrtzidis CheckerContext &C) const { 44d99bd55aSTed Kremenek 4537ab726dSArgyrios Kyrtzidis const Expr *receiver = msg.getInstanceReceiver(); 46d99bd55aSTed Kremenek if (!receiver) 47d99bd55aSTed Kremenek return; 48d99bd55aSTed Kremenek 49d99bd55aSTed Kremenek // FIXME: Enhance with value-tracking information instead of consulting 50d99bd55aSTed Kremenek // the type of the expression. 51d99bd55aSTed Kremenek const ObjCObjectPointerType* PT = 52d99bd55aSTed Kremenek receiver->getType()->getAs<ObjCObjectPointerType>(); 53d99bd55aSTed Kremenek 54d99bd55aSTed Kremenek if (!PT) 55d99bd55aSTed Kremenek return; 56d99bd55aSTed Kremenek const ObjCInterfaceDecl* OD = PT->getInterfaceDecl(); 57d99bd55aSTed Kremenek if (!OD) 58d99bd55aSTed Kremenek return; 59d99bd55aSTed Kremenek if (!OD->getIdentifier()->getName().equals("NSAutoreleasePool")) 60d99bd55aSTed Kremenek return; 61d99bd55aSTed Kremenek 62aad83725SArgyrios Kyrtzidis if (releaseS.isNull()) 63aad83725SArgyrios Kyrtzidis releaseS = GetNullarySelector("release", C.getASTContext()); 64d99bd55aSTed Kremenek // Sending 'release' message? 6537ab726dSArgyrios Kyrtzidis if (msg.getSelector() != releaseS) 66d99bd55aSTed Kremenek return; 67d99bd55aSTed Kremenek 6837ab726dSArgyrios Kyrtzidis SourceRange R = msg.getSourceRange(); 69d99bd55aSTed Kremenek 70d99bd55aSTed Kremenek C.getBugReporter().EmitBasicReport("Use -drain instead of -release", 71d99bd55aSTed Kremenek "API Upgrade (Apple)", 72d99bd55aSTed Kremenek "Use -drain instead of -release when using NSAutoreleasePool " 7337ab726dSArgyrios Kyrtzidis "and garbage collection", R.getBegin(), &R, 1); 74d99bd55aSTed Kremenek } 75aad83725SArgyrios Kyrtzidis 76aad83725SArgyrios Kyrtzidis void ento::registerNSAutoreleasePoolChecker(CheckerManager &mgr) { 77aad83725SArgyrios Kyrtzidis if (mgr.getLangOptions().getGCMode() != LangOptions::NonGC) 78aad83725SArgyrios Kyrtzidis mgr.registerChecker<NSAutoreleasePoolChecker>(); 79aad83725SArgyrios Kyrtzidis } 80