blob: 48f03a369ed5f2b636a5455d78c17e44186089e9 [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 Kremenek6b676302010-01-25 17:10:22 +000018#include "clang/Checker/BugReporter/BugReporter.h"
Ted Kremenek1309f9a2010-01-25 04:41:41 +000019#include "clang/Checker/PathSensitive/GRExprEngine.h"
20#include "clang/Checker/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;
26
27namespace {
Kovarththanan Rajaratnamba5fb5a2009-11-28 06:07:30 +000028class NSAutoreleasePoolChecker
Ted Kremenek54cb7cc2009-11-03 08:03:59 +000029 : public CheckerVisitor<NSAutoreleasePoolChecker> {
30
31 Selector releaseS;
32
33public:
34 NSAutoreleasePoolChecker(Selector release_s) : releaseS(release_s) {}
35
36 static void *getTag() {
37 static int x = 0;
38 return &x;
39 }
40
41 void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME);
42};
43
44} // end anonymous namespace
45
46
47void clang::RegisterNSAutoreleasePoolChecks(GRExprEngine &Eng) {
48 ASTContext &Ctx = Eng.getContext();
49 if (Ctx.getLangOptions().getGCMode() != LangOptions::NonGC) {
50 Eng.registerCheck(new NSAutoreleasePoolChecker(GetNullarySelector("release",
51 Ctx)));
52 }
53}
54
55void
56NSAutoreleasePoolChecker::PreVisitObjCMessageExpr(CheckerContext &C,
57 const ObjCMessageExpr *ME) {
58
Douglas Gregor04badcf2010-04-21 00:45:42 +000059 const Expr *receiver = ME->getInstanceReceiver();
Ted Kremenek54cb7cc2009-11-03 08:03:59 +000060 if (!receiver)
61 return;
62
63 // FIXME: Enhance with value-tracking information instead of consulting
64 // the type of the expression.
65 const ObjCObjectPointerType* PT =
66 receiver->getType()->getAs<ObjCObjectPointerType>();
Ted Kremenek71a5e282009-11-20 00:12:36 +000067
68 if (!PT)
69 return;
Ted Kremenek54cb7cc2009-11-03 08:03:59 +000070 const ObjCInterfaceDecl* OD = PT->getInterfaceDecl();
71 if (!OD)
72 return;
73 if (!OD->getIdentifier()->getName().equals("NSAutoreleasePool"))
74 return;
75
76 // Sending 'release' message?
77 if (ME->getSelector() != releaseS)
78 return;
79
80 SourceRange R = ME->getSourceRange();
81
82 C.getBugReporter().EmitBasicReport("Use -drain instead of -release",
83 "API Upgrade (Apple)",
84 "Use -drain instead of -release when using NSAutoreleasePool "
85 "and garbage collection", ME->getLocStart(), &R, 1);
86}