1 //=- NSAutoreleasePoolChecker.cpp --------------------------------*- C++ -*-==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
16 //===----------------------------------------------------------------------===//
18 #include "clang/GR/BugReporter/BugReporter.h"
19 #include "clang/GR/PathSensitive/GRExprEngine.h"
20 #include "clang/GR/PathSensitive/CheckerVisitor.h"
21 #include "BasicObjCFoundationChecks.h"
22 #include "clang/AST/DeclObjC.h"
23 #include "clang/AST/Decl.h"
25 using namespace clang
;
29 class NSAutoreleasePoolChecker
30 : public CheckerVisitor
<NSAutoreleasePoolChecker
> {
35 NSAutoreleasePoolChecker(Selector release_s
) : releaseS(release_s
) {}
37 static void *getTag() {
42 void PreVisitObjCMessageExpr(CheckerContext
&C
, const ObjCMessageExpr
*ME
);
45 } // end anonymous namespace
48 void GR::RegisterNSAutoreleasePoolChecks(GRExprEngine
&Eng
) {
49 ASTContext
&Ctx
= Eng
.getContext();
50 if (Ctx
.getLangOptions().getGCMode() != LangOptions::NonGC
) {
51 Eng
.registerCheck(new NSAutoreleasePoolChecker(GetNullarySelector("release",
57 NSAutoreleasePoolChecker::PreVisitObjCMessageExpr(CheckerContext
&C
,
58 const ObjCMessageExpr
*ME
) {
60 const Expr
*receiver
= ME
->getInstanceReceiver();
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
>();
71 const ObjCInterfaceDecl
* OD
= PT
->getInterfaceDecl();
74 if (!OD
->getIdentifier()->getName().equals("NSAutoreleasePool"))
77 // Sending 'release' message?
78 if (ME
->getSelector() != releaseS
)
81 SourceRange R
= ME
->getSourceRange();
83 C
.getBugReporter().EmitBasicReport("Use -drain instead of -release",
84 "API Upgrade (Apple)",
85 "Use -drain instead of -release when using NSAutoreleasePool "
86 "and garbage collection", ME
->getLocStart(), &R
, 1);