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