[analyzer] Refactoring: include/clang/Checker -> include/clang/GR
[clang.git] / lib / Checker / NSAutoreleasePoolChecker.cpp
blobd8225a7e4e70ea2b13d638d1e254ec412efa8723
1 //=- 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.
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;
27 namespace {
28 class NSAutoreleasePoolChecker
29 : public CheckerVisitor<NSAutoreleasePoolChecker> {
31 Selector releaseS;
33 public:
34 NSAutoreleasePoolChecker(Selector release_s) : releaseS(release_s) {}
36 static void *getTag() {
37 static int x = 0;
38 return &x;
41 void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME);
44 } // end anonymous namespace
47 void 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)));
55 void
56 NSAutoreleasePoolChecker::PreVisitObjCMessageExpr(CheckerContext &C,
57 const ObjCMessageExpr *ME) {
59 const Expr *receiver = ME->getInstanceReceiver();
60 if (!receiver)
61 return;
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>();
68 if (!PT)
69 return;
70 const ObjCInterfaceDecl* OD = PT->getInterfaceDecl();
71 if (!OD)
72 return;
73 if (!OD->getIdentifier()->getName().equals("NSAutoreleasePool"))
74 return;
76 // Sending 'release' message?
77 if (ME->getSelector() != releaseS)
78 return;
80 SourceRange R = ME->getSourceRange();
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);