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