blob: 9b1ff168443d6d724699491356c3ac4437a53001 [file] [log] [blame]
Ted Kremenek54cb7cc2009-11-03 08:03:59 +00001//=- NSAutoreleasePoolChecker.cpp --------------------------------*- C++ -*-==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines a NSAutoreleasePoolChecker, a small checker that warns
11// about subpar uses of NSAutoreleasePool. Note that while the check itself
12// (in it's current form) could be written as a flow-insensitive check, in
13// can be potentially enhanced in the future with flow-sensitive information.
14// It is also a good example of the CheckerVisitor interface.
15//
16//===----------------------------------------------------------------------===//
17
Ted Kremenek9b663712011-02-10 01:03:03 +000018#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
19#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
20#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
Ted Kremenek54cb7cc2009-11-03 08:03:59 +000021#include "BasicObjCFoundationChecks.h"
Ted Kremenek54cb7cc2009-11-03 08:03:59 +000022#include "clang/AST/DeclObjC.h"
23#include "clang/AST/Decl.h"
24
25using namespace clang;
Ted Kremenek9ef65372010-12-23 07:20:52 +000026using namespace ento;
Ted Kremenek54cb7cc2009-11-03 08:03:59 +000027
28namespace {
Kovarththanan Rajaratnamba5fb5a2009-11-28 06:07:30 +000029class NSAutoreleasePoolChecker
Ted Kremenek54cb7cc2009-11-03 08:03:59 +000030 : public CheckerVisitor<NSAutoreleasePoolChecker> {
31
32 Selector releaseS;
33
34public:
35 NSAutoreleasePoolChecker(Selector release_s) : releaseS(release_s) {}
36
37 static void *getTag() {
38 static int x = 0;
39 return &x;
40 }
41
Argyrios Kyrtzidis432424d2011-01-25 00:03:53 +000042 void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg);
Ted Kremenek54cb7cc2009-11-03 08:03:59 +000043};
44
45} // end anonymous namespace
46
47
Ted Kremenek9ef65372010-12-23 07:20:52 +000048void ento::RegisterNSAutoreleasePoolChecks(ExprEngine &Eng) {
Ted Kremenek54cb7cc2009-11-03 08:03:59 +000049 ASTContext &Ctx = Eng.getContext();
50 if (Ctx.getLangOptions().getGCMode() != LangOptions::NonGC) {
51 Eng.registerCheck(new NSAutoreleasePoolChecker(GetNullarySelector("release",
52 Ctx)));
53 }
54}
55
56void
Argyrios Kyrtzidis432424d2011-01-25 00:03:53 +000057NSAutoreleasePoolChecker::preVisitObjCMessage(CheckerContext &C,
58 ObjCMessage msg) {
Ted Kremenek54cb7cc2009-11-03 08:03:59 +000059
Argyrios Kyrtzidis432424d2011-01-25 00:03:53 +000060 const Expr *receiver = msg.getInstanceReceiver();
Ted Kremenek54cb7cc2009-11-03 08:03:59 +000061 if (!receiver)
62 return;
63
64 // FIXME: Enhance with value-tracking information instead of consulting
65 // the type of the expression.
66 const ObjCObjectPointerType* PT =
67 receiver->getType()->getAs<ObjCObjectPointerType>();
Ted Kremenek71a5e282009-11-20 00:12:36 +000068
69 if (!PT)
70 return;
Ted Kremenek54cb7cc2009-11-03 08:03:59 +000071 const ObjCInterfaceDecl* OD = PT->getInterfaceDecl();
72 if (!OD)
73 return;
74 if (!OD->getIdentifier()->getName().equals("NSAutoreleasePool"))
75 return;
76
77 // Sending 'release' message?
Argyrios Kyrtzidis432424d2011-01-25 00:03:53 +000078 if (msg.getSelector() != releaseS)
Ted Kremenek54cb7cc2009-11-03 08:03:59 +000079 return;
80
Argyrios Kyrtzidis432424d2011-01-25 00:03:53 +000081 SourceRange R = msg.getSourceRange();
Ted Kremenek54cb7cc2009-11-03 08:03:59 +000082
83 C.getBugReporter().EmitBasicReport("Use -drain instead of -release",
84 "API Upgrade (Apple)",
85 "Use -drain instead of -release when using NSAutoreleasePool "
Argyrios Kyrtzidis432424d2011-01-25 00:03:53 +000086 "and garbage collection", R.getBegin(), &R, 1);
Ted Kremenek54cb7cc2009-11-03 08:03:59 +000087}