1249423Sdim//===--- TransARCAssign.cpp - Transformations to ARC mode -----------------===// 2224135Sdim// 3224135Sdim// The LLVM Compiler Infrastructure 4224135Sdim// 5224135Sdim// This file is distributed under the University of Illinois Open Source 6224135Sdim// License. See LICENSE.TXT for details. 7224135Sdim// 8224135Sdim//===----------------------------------------------------------------------===// 9224135Sdim// 10224135Sdim// makeAssignARCSafe: 11224135Sdim// 12224135Sdim// Add '__strong' where appropriate. 13224135Sdim// 14224135Sdim// for (id x in collection) { 15224135Sdim// x = 0; 16224135Sdim// } 17224135Sdim// ----> 18224135Sdim// for (__strong id x in collection) { 19224135Sdim// x = 0; 20224135Sdim// } 21224135Sdim// 22224135Sdim//===----------------------------------------------------------------------===// 23224135Sdim 24224135Sdim#include "Transforms.h" 25224135Sdim#include "Internals.h" 26239462Sdim#include "clang/AST/ASTContext.h" 27224135Sdim#include "clang/Sema/SemaDiagnostic.h" 28224135Sdim 29224135Sdimusing namespace clang; 30224135Sdimusing namespace arcmt; 31224135Sdimusing namespace trans; 32224135Sdim 33224135Sdimnamespace { 34224135Sdim 35224135Sdimclass ARCAssignChecker : public RecursiveASTVisitor<ARCAssignChecker> { 36224135Sdim MigrationPass &Pass; 37224135Sdim llvm::DenseSet<VarDecl *> ModifiedVars; 38224135Sdim 39224135Sdimpublic: 40224135Sdim ARCAssignChecker(MigrationPass &pass) : Pass(pass) { } 41224135Sdim 42224135Sdim bool VisitBinaryOperator(BinaryOperator *Exp) { 43234353Sdim if (Exp->getType()->isDependentType()) 44234353Sdim return true; 45234353Sdim 46224135Sdim Expr *E = Exp->getLHS(); 47224135Sdim SourceLocation OrigLoc = E->getExprLoc(); 48224135Sdim SourceLocation Loc = OrigLoc; 49224135Sdim DeclRefExpr *declRef = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()); 50224135Sdim if (declRef && isa<VarDecl>(declRef->getDecl())) { 51224135Sdim ASTContext &Ctx = Pass.Ctx; 52224135Sdim Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(Ctx, &Loc); 53224135Sdim if (IsLV != Expr::MLV_ConstQualified) 54224135Sdim return true; 55224135Sdim VarDecl *var = cast<VarDecl>(declRef->getDecl()); 56224135Sdim if (var->isARCPseudoStrong()) { 57224135Sdim Transaction Trans(Pass.TA); 58224135Sdim if (Pass.TA.clearDiagnostic(diag::err_typecheck_arr_assign_enumeration, 59224135Sdim Exp->getOperatorLoc())) { 60224135Sdim if (!ModifiedVars.count(var)) { 61224135Sdim TypeLoc TLoc = var->getTypeSourceInfo()->getTypeLoc(); 62224135Sdim Pass.TA.insert(TLoc.getBeginLoc(), "__strong "); 63224135Sdim ModifiedVars.insert(var); 64224135Sdim } 65224135Sdim } 66224135Sdim } 67224135Sdim } 68224135Sdim 69224135Sdim return true; 70224135Sdim } 71224135Sdim}; 72224135Sdim 73224135Sdim} // anonymous namespace 74224135Sdim 75224135Sdimvoid trans::makeAssignARCSafe(MigrationPass &pass) { 76224135Sdim ARCAssignChecker assignCheck(pass); 77224135Sdim assignCheck.TraverseDecl(pass.Ctx.getTranslationUnitDecl()); 78224135Sdim} 79