text: //===--- TransARCAssign.cpp - Transformations 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/AST/ASTContext.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());
  }
  