summaryrefslogtreecommitdiffstats
path: root/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-06-21 20:20:39 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-06-21 20:20:39 +0000
commite5b475c6881ff8ce6de1f4bc42e452c1d8059d83 (patch)
treeaacf2978c9e15c890120372eff7abfe5578d4079 /clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
parente1ba3123c1a8f1e9cc36df7282b44887bab5bdde (diff)
downloadbcm5719-llvm-e5b475c6881ff8ce6de1f4bc42e452c1d8059d83.tar.gz
bcm5719-llvm-e5b475c6881ff8ce6de1f4bc42e452c1d8059d83.zip
[arcmt] Break apart Transforms.cpp.
llvm-svn: 133539
Diffstat (limited to 'clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp')
-rw-r--r--clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp142
1 files changed, 142 insertions, 0 deletions
diff --git a/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
new file mode 100644
index 00000000000..f03ab5a6f4b
--- /dev/null
+++ b/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
@@ -0,0 +1,142 @@
+//===--- TransRetainReleaseDealloc.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.
+//
+//===----------------------------------------------------------------------===//
+//
+// removeRetainReleaseDealloc:
+//
+// Removes retain/release/autorelease/dealloc messages.
+//
+// return [[foo retain] autorelease];
+// ---->
+// return foo;
+//
+//===----------------------------------------------------------------------===//
+
+#include "Transforms.h"
+#include "Internals.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/AST/ParentMap.h"
+
+using namespace clang;
+using namespace arcmt;
+using namespace trans;
+using llvm::StringRef;
+
+namespace {
+
+class RetainReleaseDeallocRemover :
+ public RecursiveASTVisitor<RetainReleaseDeallocRemover> {
+ Decl *Dcl;
+ Stmt *Body;
+ MigrationPass &Pass;
+
+ ExprSet Removables;
+ llvm::OwningPtr<ParentMap> StmtMap;
+
+public:
+ RetainReleaseDeallocRemover(Decl *D, MigrationPass &pass)
+ : Dcl(D), Body(0), Pass(pass) { }
+
+ void transformBody(Stmt *body) {
+ Body = body;
+ collectRemovables(body, Removables);
+ StmtMap.reset(new ParentMap(body));
+ TraverseStmt(body);
+ }
+
+ bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
+ switch (E->getMethodFamily()) {
+ default:
+ return true;
+ case OMF_retain:
+ case OMF_release:
+ case OMF_autorelease:
+ if (E->getReceiverKind() == ObjCMessageExpr::Instance)
+ if (Expr *rec = E->getInstanceReceiver()) {
+ rec = rec->IgnoreParenImpCasts();
+ if (rec->getType().getObjCLifetime() == Qualifiers::OCL_ExplicitNone){
+ std::string err = "It is not safe to remove '";
+ err += E->getSelector().getAsString() + "' message on "
+ "an __unsafe_unretained type";
+ Pass.TA.reportError(err, rec->getLocStart());
+ return true;
+ }
+ }
+ case OMF_dealloc:
+ break;
+ }
+
+ switch (E->getReceiverKind()) {
+ default:
+ return true;
+ case ObjCMessageExpr::SuperInstance: {
+ Transaction Trans(Pass.TA);
+ Pass.TA.clearDiagnostic(diag::err_arc_illegal_explicit_message,
+ diag::err_unavailable,
+ diag::err_unavailable_message,
+ E->getSuperLoc());
+ if (tryRemoving(E))
+ return true;
+ Pass.TA.replace(E->getSourceRange(), "self");
+ return true;
+ }
+ case ObjCMessageExpr::Instance:
+ break;
+ }
+
+ Expr *rec = E->getInstanceReceiver();
+ if (!rec) return true;
+
+ Transaction Trans(Pass.TA);
+ Pass.TA.clearDiagnostic(diag::err_arc_illegal_explicit_message,
+ diag::err_unavailable,
+ diag::err_unavailable_message,
+ rec->getExprLoc());
+ if (!hasSideEffects(E, Pass.Ctx)) {
+ if (tryRemoving(E))
+ return true;
+ }
+ Pass.TA.replace(E->getSourceRange(), rec->getSourceRange());
+
+ return true;
+ }
+
+private:
+ bool isRemovable(Expr *E) const {
+ return Removables.count(E);
+ }
+
+ bool tryRemoving(Expr *E) const {
+ if (isRemovable(E)) {
+ Pass.TA.removeStmt(E);
+ return true;
+ }
+
+ if (ParenExpr *parenE = dyn_cast_or_null<ParenExpr>(StmtMap->getParent(E)))
+ return tryRemoving(parenE);
+
+ if (BinaryOperator *
+ bopE = dyn_cast_or_null<BinaryOperator>(StmtMap->getParent(E))) {
+ if (bopE->getOpcode() == BO_Comma && bopE->getLHS() == E &&
+ isRemovable(bopE)) {
+ Pass.TA.replace(bopE->getSourceRange(), bopE->getRHS()->getSourceRange());
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+};
+
+} // anonymous namespace
+
+void trans::removeRetainReleaseDealloc(MigrationPass &pass) {
+ BodyTransform<RetainReleaseDeallocRemover> trans(pass);
+ trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
+}
OpenPOWER on IntegriCloud