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