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 18*f8cbac4bSTed Kremenek #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 19*f8cbac4bSTed Kremenek #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 20*f8cbac4bSTed Kremenek #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" 21d99bd55aSTed Kremenek #include "BasicObjCFoundationChecks.h" 22d99bd55aSTed Kremenek #include "clang/AST/DeclObjC.h" 23d99bd55aSTed Kremenek #include "clang/AST/Decl.h" 24d99bd55aSTed Kremenek 25d99bd55aSTed Kremenek using namespace clang; 26d99bd55aSTed Kremenek using namespace ento; 27d99bd55aSTed Kremenek 28d99bd55aSTed Kremenek namespace { 29d99bd55aSTed Kremenek class NSAutoreleasePoolChecker 30d99bd55aSTed Kremenek : public CheckerVisitor<NSAutoreleasePoolChecker> { 31d99bd55aSTed Kremenek 32d99bd55aSTed Kremenek Selector releaseS; 33d99bd55aSTed Kremenek 34d99bd55aSTed Kremenek public: 35d99bd55aSTed Kremenek NSAutoreleasePoolChecker(Selector release_s) : releaseS(release_s) {} 36d99bd55aSTed Kremenek 37d99bd55aSTed Kremenek static void *getTag() { 38d99bd55aSTed Kremenek static int x = 0; 39d99bd55aSTed Kremenek return &x; 40d99bd55aSTed Kremenek } 41d99bd55aSTed Kremenek 4237ab726dSArgyrios Kyrtzidis void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg); 43d99bd55aSTed Kremenek }; 44d99bd55aSTed Kremenek 45d99bd55aSTed Kremenek } // end anonymous namespace 46d99bd55aSTed Kremenek 47d99bd55aSTed Kremenek 48d99bd55aSTed Kremenek void ento::RegisterNSAutoreleasePoolChecks(ExprEngine &Eng) { 49d99bd55aSTed Kremenek ASTContext &Ctx = Eng.getContext(); 50d99bd55aSTed Kremenek if (Ctx.getLangOptions().getGCMode() != LangOptions::NonGC) { 51d99bd55aSTed Kremenek Eng.registerCheck(new NSAutoreleasePoolChecker(GetNullarySelector("release", 52d99bd55aSTed Kremenek Ctx))); 53d99bd55aSTed Kremenek } 54d99bd55aSTed Kremenek } 55d99bd55aSTed Kremenek 56d99bd55aSTed Kremenek void 5737ab726dSArgyrios Kyrtzidis NSAutoreleasePoolChecker::preVisitObjCMessage(CheckerContext &C, 5837ab726dSArgyrios Kyrtzidis ObjCMessage msg) { 59d99bd55aSTed Kremenek 6037ab726dSArgyrios Kyrtzidis const Expr *receiver = msg.getInstanceReceiver(); 61d99bd55aSTed Kremenek if (!receiver) 62d99bd55aSTed Kremenek return; 63d99bd55aSTed Kremenek 64d99bd55aSTed Kremenek // FIXME: Enhance with value-tracking information instead of consulting 65d99bd55aSTed Kremenek // the type of the expression. 66d99bd55aSTed Kremenek const ObjCObjectPointerType* PT = 67d99bd55aSTed Kremenek receiver->getType()->getAs<ObjCObjectPointerType>(); 68d99bd55aSTed Kremenek 69d99bd55aSTed Kremenek if (!PT) 70d99bd55aSTed Kremenek return; 71d99bd55aSTed Kremenek const ObjCInterfaceDecl* OD = PT->getInterfaceDecl(); 72d99bd55aSTed Kremenek if (!OD) 73d99bd55aSTed Kremenek return; 74d99bd55aSTed Kremenek if (!OD->getIdentifier()->getName().equals("NSAutoreleasePool")) 75d99bd55aSTed Kremenek return; 76d99bd55aSTed Kremenek 77d99bd55aSTed Kremenek // Sending 'release' message? 7837ab726dSArgyrios Kyrtzidis if (msg.getSelector() != releaseS) 79d99bd55aSTed Kremenek return; 80d99bd55aSTed Kremenek 8137ab726dSArgyrios Kyrtzidis SourceRange R = msg.getSourceRange(); 82d99bd55aSTed Kremenek 83d99bd55aSTed Kremenek C.getBugReporter().EmitBasicReport("Use -drain instead of -release", 84d99bd55aSTed Kremenek "API Upgrade (Apple)", 85d99bd55aSTed Kremenek "Use -drain instead of -release when using NSAutoreleasePool " 8637ab726dSArgyrios Kyrtzidis "and garbage collection", R.getBegin(), &R, 1); 87d99bd55aSTed Kremenek } 88