1 //===--- TransZeroOutPropsInDealloc.cpp - Tranformations to ARC mode ------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // removeZeroOutPropsInDealloc:
12 // Removes zero'ing out "strong" @synthesized properties in a -dealloc method.
14 //===----------------------------------------------------------------------===//
16 #include "Transforms.h"
17 #include "Internals.h"
19 using namespace clang;
20 using namespace arcmt;
21 using namespace trans;
22 using llvm::StringRef;
26 class ZeroOutInDeallocRemover :
27 public RecursiveASTVisitor<ZeroOutInDeallocRemover> {
28 typedef RecursiveASTVisitor<ZeroOutInDeallocRemover> base;
32 llvm::DenseMap<ObjCPropertyDecl*, ObjCPropertyImplDecl*> SynthesizedProperties;
33 ImplicitParamDecl *SelfD;
37 ZeroOutInDeallocRemover(MigrationPass &pass) : Pass(pass), SelfD(0) { }
39 bool VisitObjCMessageExpr(ObjCMessageExpr *ME) {
40 ASTContext &Ctx = Pass.Ctx;
41 TransformActions &TA = Pass.TA;
43 if (ME->getReceiverKind() != ObjCMessageExpr::Instance)
45 Expr *receiver = ME->getInstanceReceiver();
49 DeclRefExpr *refE = dyn_cast<DeclRefExpr>(receiver->IgnoreParenCasts());
50 if (!refE || refE->getDecl() != SelfD)
53 bool BackedBySynthesizeSetter = false;
54 for (llvm::DenseMap<ObjCPropertyDecl*, ObjCPropertyImplDecl*>::iterator
55 P = SynthesizedProperties.begin(),
56 E = SynthesizedProperties.end(); P != E; ++P) {
57 ObjCPropertyDecl *PropDecl = P->first;
58 if (PropDecl->getSetterName() == ME->getSelector()) {
59 BackedBySynthesizeSetter = true;
63 if (!BackedBySynthesizeSetter)
66 // Remove the setter message if RHS is null
67 Transaction Trans(TA);
68 Expr *RHS = ME->getArg(0);
70 RHS->isNullPointerConstant(Ctx,
71 Expr::NPC_ValueDependentIsNull);
72 if (RHSIsNull && isRemovable(ME))
78 bool VisitBinaryOperator(BinaryOperator *BOE) {
79 if (isZeroingPropIvar(BOE) && isRemovable(BOE)) {
80 Transaction Trans(Pass.TA);
81 Pass.TA.removeStmt(BOE);
87 bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
88 if (D->getMethodFamily() != OMF_dealloc)
93 ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(D->getDeclContext());
97 SelfD = D->getSelfDecl();
98 collectRemovables(D->getBody(), Removables);
100 // For a 'dealloc' method use, find all property implementations in
101 // this class implementation.
102 for (ObjCImplDecl::propimpl_iterator
103 I = IMD->propimpl_begin(), EI = IMD->propimpl_end(); I != EI; ++I) {
104 ObjCPropertyImplDecl *PID = *I;
105 if (PID->getPropertyImplementation() ==
106 ObjCPropertyImplDecl::Synthesize) {
107 ObjCPropertyDecl *PD = PID->getPropertyDecl();
108 ObjCMethodDecl *setterM = PD->getSetterMethodDecl();
109 if (!(setterM && setterM->isDefined())) {
110 ObjCPropertyDecl::PropertyAttributeKind AttrKind =
111 PD->getPropertyAttributes();
113 (ObjCPropertyDecl::OBJC_PR_retain |
114 ObjCPropertyDecl::OBJC_PR_copy |
115 ObjCPropertyDecl::OBJC_PR_strong))
116 SynthesizedProperties[PD] = PID;
121 // Now, remove all zeroing of ivars etc.
122 base::TraverseObjCMethodDecl(D);
124 // clear out for next method.
125 SynthesizedProperties.clear();
131 bool TraverseFunctionDecl(FunctionDecl *D) { return true; }
132 bool TraverseBlockDecl(BlockDecl *block) { return true; }
133 bool TraverseBlockExpr(BlockExpr *block) { return true; }
136 bool isRemovable(Expr *E) const {
137 return Removables.count(E);
140 bool isZeroingPropIvar(Expr *E) {
141 BinaryOperator *BOE = dyn_cast_or_null<BinaryOperator>(E);
142 if (!BOE) return false;
144 if (BOE->getOpcode() == BO_Comma)
145 return isZeroingPropIvar(BOE->getLHS()) &&
146 isZeroingPropIvar(BOE->getRHS());
148 if (BOE->getOpcode() != BO_Assign)
151 ASTContext &Ctx = Pass.Ctx;
153 Expr *LHS = BOE->getLHS();
154 if (ObjCIvarRefExpr *IV = dyn_cast<ObjCIvarRefExpr>(LHS)) {
155 ObjCIvarDecl *IVDecl = IV->getDecl();
156 if (!IVDecl->getType()->isObjCObjectPointerType())
158 bool IvarBacksPropertySynthesis = false;
159 for (llvm::DenseMap<ObjCPropertyDecl*, ObjCPropertyImplDecl*>::iterator
160 P = SynthesizedProperties.begin(),
161 E = SynthesizedProperties.end(); P != E; ++P) {
162 ObjCPropertyImplDecl *PropImpDecl = P->second;
163 if (PropImpDecl && PropImpDecl->getPropertyIvarDecl() == IVDecl) {
164 IvarBacksPropertySynthesis = true;
168 if (!IvarBacksPropertySynthesis)
171 else if (ObjCPropertyRefExpr *PropRefExp = dyn_cast<ObjCPropertyRefExpr>(LHS)) {
172 // TODO: Using implicit property decl.
173 if (PropRefExp->isImplicitProperty())
175 if (ObjCPropertyDecl *PDecl = PropRefExp->getExplicitProperty()) {
176 if (!SynthesizedProperties.count(PDecl))
183 Expr *RHS = BOE->getRHS();
184 bool RHSIsNull = RHS->isNullPointerConstant(Ctx,
185 Expr::NPC_ValueDependentIsNull);
189 return isZeroingPropIvar(RHS);
193 } // anonymous namespace
195 void trans::removeZeroOutPropsInDealloc(MigrationPass &pass) {
196 ZeroOutInDeallocRemover trans(pass);
197 trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());