summaryrefslogtreecommitdiff
path: root/clang/lib/ARCMigrate/TransARCAssign.cpp
diff options
context:
space:
mode:
authorCarlo Zancanaro <carlo@pc-4w14-0.cs.usyd.edu.au>2012-10-15 17:10:06 +1100
committerCarlo Zancanaro <carlo@pc-4w14-0.cs.usyd.edu.au>2012-10-15 17:10:06 +1100
commitbe1de4be954c80875ad4108e0a33e8e131b2f2c0 (patch)
tree1fbbecf276bf7c7bdcbb4dd446099d6d90eaa516 /clang/lib/ARCMigrate/TransARCAssign.cpp
parentc4626a62754862d20b41e8a46a3574264ea80e6d (diff)
parentf1bd2e48c5324d3f7cda4090c87f8a5b6f463ce2 (diff)
Merge branch 'master' of ssh://bitbucket.org/czan/honours
Diffstat (limited to 'clang/lib/ARCMigrate/TransARCAssign.cpp')
-rw-r--r--clang/lib/ARCMigrate/TransARCAssign.cpp77
1 files changed, 77 insertions, 0 deletions
diff --git a/clang/lib/ARCMigrate/TransARCAssign.cpp b/clang/lib/ARCMigrate/TransARCAssign.cpp
new file mode 100644
index 0000000..cfa6da1
--- /dev/null
+++ b/clang/lib/ARCMigrate/TransARCAssign.cpp
@@ -0,0 +1,77 @@
+//===--- TransARCAssign.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.
+//
+//===----------------------------------------------------------------------===//
+//
+// makeAssignARCSafe:
+//
+// Add '__strong' where appropriate.
+//
+// for (id x in collection) {
+// x = 0;
+// }
+// ---->
+// for (__strong id x in collection) {
+// x = 0;
+// }
+//
+//===----------------------------------------------------------------------===//
+
+#include "Transforms.h"
+#include "Internals.h"
+#include "clang/Sema/SemaDiagnostic.h"
+
+using namespace clang;
+using namespace arcmt;
+using namespace trans;
+
+namespace {
+
+class ARCAssignChecker : public RecursiveASTVisitor<ARCAssignChecker> {
+ MigrationPass &Pass;
+ llvm::DenseSet<VarDecl *> ModifiedVars;
+
+public:
+ ARCAssignChecker(MigrationPass &pass) : Pass(pass) { }
+
+ bool VisitBinaryOperator(BinaryOperator *Exp) {
+ if (Exp->getType()->isDependentType())
+ return true;
+
+ Expr *E = Exp->getLHS();
+ SourceLocation OrigLoc = E->getExprLoc();
+ SourceLocation Loc = OrigLoc;
+ DeclRefExpr *declRef = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts());
+ if (declRef && isa<VarDecl>(declRef->getDecl())) {
+ ASTContext &Ctx = Pass.Ctx;
+ Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(Ctx, &Loc);
+ if (IsLV != Expr::MLV_ConstQualified)
+ return true;
+ VarDecl *var = cast<VarDecl>(declRef->getDecl());
+ if (var->isARCPseudoStrong()) {
+ Transaction Trans(Pass.TA);
+ if (Pass.TA.clearDiagnostic(diag::err_typecheck_arr_assign_enumeration,
+ Exp->getOperatorLoc())) {
+ if (!ModifiedVars.count(var)) {
+ TypeLoc TLoc = var->getTypeSourceInfo()->getTypeLoc();
+ Pass.TA.insert(TLoc.getBeginLoc(), "__strong ");
+ ModifiedVars.insert(var);
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+};
+
+} // anonymous namespace
+
+void trans::makeAssignARCSafe(MigrationPass &pass) {
+ ARCAssignChecker assignCheck(pass);
+ assignCheck.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
+}