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