1*67e74705SXin Li //===--- TransARCAssign.cpp - Transformations to ARC mode -----------------===// 2*67e74705SXin Li // 3*67e74705SXin Li // The LLVM Compiler Infrastructure 4*67e74705SXin Li // 5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source 6*67e74705SXin Li // License. See LICENSE.TXT for details. 7*67e74705SXin Li // 8*67e74705SXin Li //===----------------------------------------------------------------------===// 9*67e74705SXin Li // 10*67e74705SXin Li // makeAssignARCSafe: 11*67e74705SXin Li // 12*67e74705SXin Li // Add '__strong' where appropriate. 13*67e74705SXin Li // 14*67e74705SXin Li // for (id x in collection) { 15*67e74705SXin Li // x = 0; 16*67e74705SXin Li // } 17*67e74705SXin Li // ----> 18*67e74705SXin Li // for (__strong id x in collection) { 19*67e74705SXin Li // x = 0; 20*67e74705SXin Li // } 21*67e74705SXin Li // 22*67e74705SXin Li //===----------------------------------------------------------------------===// 23*67e74705SXin Li 24*67e74705SXin Li #include "Transforms.h" 25*67e74705SXin Li #include "Internals.h" 26*67e74705SXin Li #include "clang/AST/ASTContext.h" 27*67e74705SXin Li #include "clang/Sema/SemaDiagnostic.h" 28*67e74705SXin Li 29*67e74705SXin Li using namespace clang; 30*67e74705SXin Li using namespace arcmt; 31*67e74705SXin Li using namespace trans; 32*67e74705SXin Li 33*67e74705SXin Li namespace { 34*67e74705SXin Li 35*67e74705SXin Li class ARCAssignChecker : public RecursiveASTVisitor<ARCAssignChecker> { 36*67e74705SXin Li MigrationPass &Pass; 37*67e74705SXin Li llvm::DenseSet<VarDecl *> ModifiedVars; 38*67e74705SXin Li 39*67e74705SXin Li public: ARCAssignChecker(MigrationPass & pass)40*67e74705SXin Li ARCAssignChecker(MigrationPass &pass) : Pass(pass) { } 41*67e74705SXin Li VisitBinaryOperator(BinaryOperator * Exp)42*67e74705SXin Li bool VisitBinaryOperator(BinaryOperator *Exp) { 43*67e74705SXin Li if (Exp->getType()->isDependentType()) 44*67e74705SXin Li return true; 45*67e74705SXin Li 46*67e74705SXin Li Expr *E = Exp->getLHS(); 47*67e74705SXin Li SourceLocation OrigLoc = E->getExprLoc(); 48*67e74705SXin Li SourceLocation Loc = OrigLoc; 49*67e74705SXin Li DeclRefExpr *declRef = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()); 50*67e74705SXin Li if (declRef && isa<VarDecl>(declRef->getDecl())) { 51*67e74705SXin Li ASTContext &Ctx = Pass.Ctx; 52*67e74705SXin Li Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(Ctx, &Loc); 53*67e74705SXin Li if (IsLV != Expr::MLV_ConstQualified) 54*67e74705SXin Li return true; 55*67e74705SXin Li VarDecl *var = cast<VarDecl>(declRef->getDecl()); 56*67e74705SXin Li if (var->isARCPseudoStrong()) { 57*67e74705SXin Li Transaction Trans(Pass.TA); 58*67e74705SXin Li if (Pass.TA.clearDiagnostic(diag::err_typecheck_arr_assign_enumeration, 59*67e74705SXin Li Exp->getOperatorLoc())) { 60*67e74705SXin Li if (!ModifiedVars.count(var)) { 61*67e74705SXin Li TypeLoc TLoc = var->getTypeSourceInfo()->getTypeLoc(); 62*67e74705SXin Li Pass.TA.insert(TLoc.getBeginLoc(), "__strong "); 63*67e74705SXin Li ModifiedVars.insert(var); 64*67e74705SXin Li } 65*67e74705SXin Li } 66*67e74705SXin Li } 67*67e74705SXin Li } 68*67e74705SXin Li 69*67e74705SXin Li return true; 70*67e74705SXin Li } 71*67e74705SXin Li }; 72*67e74705SXin Li 73*67e74705SXin Li } // anonymous namespace 74*67e74705SXin Li makeAssignARCSafe(MigrationPass & pass)75*67e74705SXin Livoid trans::makeAssignARCSafe(MigrationPass &pass) { 76*67e74705SXin Li ARCAssignChecker assignCheck(pass); 77*67e74705SXin Li assignCheck.TraverseDecl(pass.Ctx.getTranslationUnitDecl()); 78*67e74705SXin Li } 79