154cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek//=- NSAutoreleasePoolChecker.cpp --------------------------------*- C++ -*-==// 254cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek// 354cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek// The LLVM Compiler Infrastructure 454cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek// 554cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek// This file is distributed under the University of Illinois Open Source 654cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek// License. See LICENSE.TXT for details. 754cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek// 854cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek//===----------------------------------------------------------------------===// 954cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek// 1054cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek// This file defines a NSAutoreleasePoolChecker, a small checker that warns 1154cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek// about subpar uses of NSAutoreleasePool. Note that while the check itself 12d1e5a89226da79f7e6f43d40facc46abda9e5245Jordy Rose// (in its current form) could be written as a flow-insensitive check, in 1354cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek// can be potentially enhanced in the future with flow-sensitive information. 1454cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek// It is also a good example of the CheckerVisitor interface. 1554cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek// 1654cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek//===----------------------------------------------------------------------===// 1754cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek 180b1ba6227c67d5e04b589ed8a08afa2345a40666Argyrios Kyrtzidis#include "ClangSACheckers.h" 1955fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/Decl.h" 2055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/DeclObjC.h" 219b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 2248468dfeb3ccf099ed51ff5dcb8ae0fe783692fdAnna Zaks#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 2355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/Checker.h" 2455fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/CheckerManager.h" 25f540c54701e3eeb34cb619a3a4eb18f1ac70ef2dJordan Rose#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 26d1e5a89226da79f7e6f43d40facc46abda9e5245Jordy Rose#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 279b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 2854cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek 2954cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenekusing namespace clang; 309ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 3154cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek 3254cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremeneknamespace { 33ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NSAutoreleasePoolChecker 34ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis : public Checker<check::PreObjCMessage> { 35651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines mutable std::unique_ptr<BugType> BT; 3645d9b4e44154939b91d6b8f63e7756feaca547f2Argyrios Kyrtzidis mutable Selector releaseS; 3754cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek 3854cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenekpublic: 39de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const; 4054cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek}; 4154cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek 4254cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek} // end anonymous namespace 4354cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek 44de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rosevoid NSAutoreleasePoolChecker::checkPreObjCMessage(const ObjCMethodCall &msg, 4545d9b4e44154939b91d6b8f63e7756feaca547f2Argyrios Kyrtzidis CheckerContext &C) const { 46de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose if (!msg.isInstanceMessage()) 4754cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek return; 48de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose 49de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose const ObjCInterfaceDecl *OD = msg.getReceiverInterface(); 5054cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek if (!OD) 5154cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek return; 52de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose if (!OD->getIdentifier()->isStr("NSAutoreleasePool")) 5354cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek return; 5445d9b4e44154939b91d6b8f63e7756feaca547f2Argyrios Kyrtzidis 5545d9b4e44154939b91d6b8f63e7756feaca547f2Argyrios Kyrtzidis if (releaseS.isNull()) 5645d9b4e44154939b91d6b8f63e7756feaca547f2Argyrios Kyrtzidis releaseS = GetNullarySelector("release", C.getASTContext()); 5754cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek // Sending 'release' message? 58432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis if (msg.getSelector() != releaseS) 5954cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek return; 6048468dfeb3ccf099ed51ff5dcb8ae0fe783692fdAnna Zaks 6148468dfeb3ccf099ed51ff5dcb8ae0fe783692fdAnna Zaks if (!BT) 62651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines BT.reset(new BugType(this, "Use -drain instead of -release", 6348468dfeb3ccf099ed51ff5dcb8ae0fe783692fdAnna Zaks "API Upgrade (Apple)")); 6448468dfeb3ccf099ed51ff5dcb8ae0fe783692fdAnna Zaks 6548468dfeb3ccf099ed51ff5dcb8ae0fe783692fdAnna Zaks ExplodedNode *N = C.addTransition(); 6648468dfeb3ccf099ed51ff5dcb8ae0fe783692fdAnna Zaks if (!N) { 6748468dfeb3ccf099ed51ff5dcb8ae0fe783692fdAnna Zaks assert(0); 6848468dfeb3ccf099ed51ff5dcb8ae0fe783692fdAnna Zaks return; 6948468dfeb3ccf099ed51ff5dcb8ae0fe783692fdAnna Zaks } 7048468dfeb3ccf099ed51ff5dcb8ae0fe783692fdAnna Zaks 7148468dfeb3ccf099ed51ff5dcb8ae0fe783692fdAnna Zaks BugReport *Report = new BugReport(*BT, "Use -drain instead of -release when " 7248468dfeb3ccf099ed51ff5dcb8ae0fe783692fdAnna Zaks "using NSAutoreleasePool and garbage collection", N); 7348468dfeb3ccf099ed51ff5dcb8ae0fe783692fdAnna Zaks Report->addRange(msg.getSourceRange()); 74785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rose C.emitReport(Report); 7554cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek} 7645d9b4e44154939b91d6b8f63e7756feaca547f2Argyrios Kyrtzidis 7745d9b4e44154939b91d6b8f63e7756feaca547f2Argyrios Kyrtzidisvoid ento::registerNSAutoreleasePoolChecker(CheckerManager &mgr) { 784e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (mgr.getLangOpts().getGC() != LangOptions::NonGC) 7945d9b4e44154939b91d6b8f63e7756feaca547f2Argyrios Kyrtzidis mgr.registerChecker<NSAutoreleasePoolChecker>(); 8045d9b4e44154939b91d6b8f63e7756feaca547f2Argyrios Kyrtzidis} 81