aboutsummaryrefslogtreecommitdiff
path: root/lib/ARCMigrate/TransAPIUses.cpp
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-07-18 07:44:45 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-07-18 07:44:45 +0000
commitfd10398c10ffdcbdeb1e3e299c74d70e689f503c (patch)
treec52a8f508e0a075addc538f529bf289bdd61bb09 /lib/ARCMigrate/TransAPIUses.cpp
parentf57ef0516c011237a1b6a5b2585b99caf0396bd7 (diff)
[arcmt] NSInvocation's [get/set]ReturnValue and [get/set]Argument are only safe
with __unsafe_unretained parameters. Emit error for strong/weak ones. rdar://9206226 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@135381 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ARCMigrate/TransAPIUses.cpp')
-rw-r--r--lib/ARCMigrate/TransAPIUses.cpp89
1 files changed, 89 insertions, 0 deletions
diff --git a/lib/ARCMigrate/TransAPIUses.cpp b/lib/ARCMigrate/TransAPIUses.cpp
new file mode 100644
index 0000000000..58fd3d07d0
--- /dev/null
+++ b/lib/ARCMigrate/TransAPIUses.cpp
@@ -0,0 +1,89 @@
+//===--- TransAPIUses.cpp - Tranformations to ARC mode --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// checkAPIUses:
+//
+// Emits error with some API uses that are not safe in ARC mode:
+//
+// - NSInvocation's [get/set]ReturnValue and [get/set]Argument are only safe
+// with __unsafe_unretained objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Transforms.h"
+#include "Internals.h"
+
+using namespace clang;
+using namespace arcmt;
+using namespace trans;
+using llvm::StringRef;
+
+namespace {
+
+class APIChecker : public RecursiveASTVisitor<APIChecker> {
+ MigrationPass &Pass;
+ Selector getReturnValueSel, setReturnValueSel;
+ Selector getArgumentSel, setArgumentSel;
+
+public:
+ APIChecker(MigrationPass &pass) : Pass(pass) {
+ SelectorTable &sels = Pass.Ctx.Selectors;
+ IdentifierTable &ids = Pass.Ctx.Idents;
+ getReturnValueSel = sels.getUnarySelector(&ids.get("getReturnValue"));
+ setReturnValueSel = sels.getUnarySelector(&ids.get("setReturnValue"));
+
+ IdentifierInfo *selIds[2];
+ selIds[0] = &ids.get("getArgument");
+ selIds[1] = &ids.get("atIndex");
+ getArgumentSel = sels.getSelector(2, selIds);
+ selIds[0] = &ids.get("setArgument");
+ setArgumentSel = sels.getSelector(2, selIds);
+ }
+
+ bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
+ if (E->isInstanceMessage() &&
+ E->getReceiverInterface() &&
+ E->getReceiverInterface()->getName() == "NSInvocation") {
+ StringRef selName;
+ if (E->getSelector() == getReturnValueSel)
+ selName = "getReturnValue";
+ else if (E->getSelector() == setReturnValueSel)
+ selName = "setReturnValue";
+ else if (E->getSelector() == getArgumentSel)
+ selName = "getArgument";
+ else if (E->getSelector() == setArgumentSel)
+ selName = "setArgument";
+
+ if (selName.empty())
+ return true;
+
+ Expr *parm = E->getArg(0)->IgnoreParenCasts();
+ QualType pointee = parm->getType()->getPointeeType();
+ if (pointee.isNull())
+ return true;
+
+ if (pointee.getObjCLifetime() > Qualifiers::OCL_ExplicitNone) {
+ std::string err = "NSInvocation's ";
+ err += selName;
+ err += " is not safe to be used with an object with ownership other "
+ "than __unsafe_unretained";
+ Pass.TA.reportError(err, parm->getLocStart(), parm->getSourceRange());
+ }
+ return true;
+ }
+
+ return true;
+ }
+};
+
+} // anonymous namespace
+
+void trans::checkAPIUses(MigrationPass &pass) {
+ APIChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
+}