xref: /aosp_15_r20/external/clang/lib/ARCMigrate/TransARCAssign.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
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 Li void trans::makeAssignARCSafe(MigrationPass &pass) {
76*67e74705SXin Li   ARCAssignChecker assignCheck(pass);
77*67e74705SXin Li   assignCheck.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
78*67e74705SXin Li }
79