[arcmt] Break apart Transforms.cpp.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133539 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/ARCMigrate/TransARCAssign.cpp b/lib/ARCMigrate/TransARCAssign.cpp
new file mode 100644
index 0000000..8c00df5
--- /dev/null
+++ b/lib/ARCMigrate/TransARCAssign.cpp
@@ -0,0 +1,75 @@
+//===--- 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;
+using llvm::StringRef;
+
+namespace {
+
+class ARCAssignChecker : public RecursiveASTVisitor<ARCAssignChecker> {
+  MigrationPass &Pass;
+  llvm::DenseSet<VarDecl *> ModifiedVars;
+
+public:
+  ARCAssignChecker(MigrationPass &pass) : Pass(pass) { }
+
+  bool VisitBinaryOperator(BinaryOperator *Exp) {
+    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());
+}