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