clang  6.0.0svn
TransZeroOutPropsInDealloc.cpp
Go to the documentation of this file.
1 //===--- TransZeroOutPropsInDealloc.cpp - Transformations to ARC mode -----===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // removeZeroOutPropsInDealloc:
11 //
12 // Removes zero'ing out "strong" @synthesized properties in a -dealloc method.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "Transforms.h"
17 #include "Internals.h"
18 #include "clang/AST/ASTContext.h"
19 
20 using namespace clang;
21 using namespace arcmt;
22 using namespace trans;
23 
24 namespace {
25 
26 class ZeroOutInDeallocRemover :
27  public RecursiveASTVisitor<ZeroOutInDeallocRemover> {
29 
30  MigrationPass &Pass;
31 
32  llvm::DenseMap<ObjCPropertyDecl*, ObjCPropertyImplDecl*> SynthesizedProperties;
33  ImplicitParamDecl *SelfD;
34  ExprSet Removables;
35  Selector FinalizeSel;
36 
37 public:
38  ZeroOutInDeallocRemover(MigrationPass &pass) : Pass(pass), SelfD(nullptr) {
39  FinalizeSel =
40  Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("finalize"));
41  }
42 
43  bool VisitObjCMessageExpr(ObjCMessageExpr *ME) {
44  ASTContext &Ctx = Pass.Ctx;
45  TransformActions &TA = Pass.TA;
46 
48  return true;
49  Expr *receiver = ME->getInstanceReceiver();
50  if (!receiver)
51  return true;
52 
53  DeclRefExpr *refE = dyn_cast<DeclRefExpr>(receiver->IgnoreParenCasts());
54  if (!refE || refE->getDecl() != SelfD)
55  return true;
56 
57  bool BackedBySynthesizeSetter = false;
58  for (llvm::DenseMap<ObjCPropertyDecl*, ObjCPropertyImplDecl*>::iterator
59  P = SynthesizedProperties.begin(),
60  E = SynthesizedProperties.end(); P != E; ++P) {
61  ObjCPropertyDecl *PropDecl = P->first;
62  if (PropDecl->getSetterName() == ME->getSelector()) {
63  BackedBySynthesizeSetter = true;
64  break;
65  }
66  }
67  if (!BackedBySynthesizeSetter)
68  return true;
69 
70  // Remove the setter message if RHS is null
71  Transaction Trans(TA);
72  Expr *RHS = ME->getArg(0);
73  bool RHSIsNull =
74  RHS->isNullPointerConstant(Ctx,
76  if (RHSIsNull && isRemovable(ME))
77  TA.removeStmt(ME);
78 
79  return true;
80  }
81 
82  bool VisitPseudoObjectExpr(PseudoObjectExpr *POE) {
83  if (isZeroingPropIvar(POE) && isRemovable(POE)) {
84  Transaction Trans(Pass.TA);
85  Pass.TA.removeStmt(POE);
86  }
87 
88  return true;
89  }
90 
91  bool VisitBinaryOperator(BinaryOperator *BOE) {
92  if (isZeroingPropIvar(BOE) && isRemovable(BOE)) {
93  Transaction Trans(Pass.TA);
94  Pass.TA.removeStmt(BOE);
95  }
96 
97  return true;
98  }
99 
100  bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
101  if (D->getMethodFamily() != OMF_dealloc &&
102  !(D->isInstanceMethod() && D->getSelector() == FinalizeSel))
103  return true;
104  if (!D->hasBody())
105  return true;
106 
107  ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(D->getDeclContext());
108  if (!IMD)
109  return true;
110 
111  SelfD = D->getSelfDecl();
112  collectRemovables(D->getBody(), Removables);
113 
114  // For a 'dealloc' method use, find all property implementations in
115  // this class implementation.
116  for (auto *PID : IMD->property_impls()) {
117  if (PID->getPropertyImplementation() ==
119  ObjCPropertyDecl *PD = PID->getPropertyDecl();
120  ObjCMethodDecl *setterM = PD->getSetterMethodDecl();
121  if (!(setterM && setterM->isDefined())) {
123  PD->getPropertyAttributes();
124  if (AttrKind &
128  SynthesizedProperties[PD] = PID;
129  }
130  }
131  }
132 
133  // Now, remove all zeroing of ivars etc.
134  base::TraverseObjCMethodDecl(D);
135 
136  // clear out for next method.
137  SynthesizedProperties.clear();
138  SelfD = nullptr;
139  Removables.clear();
140  return true;
141  }
142 
143  bool TraverseFunctionDecl(FunctionDecl *D) { return true; }
144  bool TraverseBlockDecl(BlockDecl *block) { return true; }
145  bool TraverseBlockExpr(BlockExpr *block) { return true; }
146 
147 private:
148  bool isRemovable(Expr *E) const {
149  return Removables.count(E);
150  }
151 
152  bool isZeroingPropIvar(Expr *E) {
153  E = E->IgnoreParens();
154  if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E))
155  return isZeroingPropIvar(BO);
156  if (PseudoObjectExpr *PO = dyn_cast<PseudoObjectExpr>(E))
157  return isZeroingPropIvar(PO);
158  return false;
159  }
160 
161  bool isZeroingPropIvar(BinaryOperator *BOE) {
162  if (BOE->getOpcode() == BO_Comma)
163  return isZeroingPropIvar(BOE->getLHS()) &&
164  isZeroingPropIvar(BOE->getRHS());
165 
166  if (BOE->getOpcode() != BO_Assign)
167  return false;
168 
169  Expr *LHS = BOE->getLHS();
170  if (ObjCIvarRefExpr *IV = dyn_cast<ObjCIvarRefExpr>(LHS)) {
171  ObjCIvarDecl *IVDecl = IV->getDecl();
172  if (!IVDecl->getType()->isObjCObjectPointerType())
173  return false;
174  bool IvarBacksPropertySynthesis = false;
175  for (llvm::DenseMap<ObjCPropertyDecl*, ObjCPropertyImplDecl*>::iterator
176  P = SynthesizedProperties.begin(),
177  E = SynthesizedProperties.end(); P != E; ++P) {
178  ObjCPropertyImplDecl *PropImpDecl = P->second;
179  if (PropImpDecl && PropImpDecl->getPropertyIvarDecl() == IVDecl) {
180  IvarBacksPropertySynthesis = true;
181  break;
182  }
183  }
184  if (!IvarBacksPropertySynthesis)
185  return false;
186  }
187  else
188  return false;
189 
190  return isZero(BOE->getRHS());
191  }
192 
193  bool isZeroingPropIvar(PseudoObjectExpr *PO) {
194  BinaryOperator *BO = dyn_cast<BinaryOperator>(PO->getSyntacticForm());
195  if (!BO) return false;
196  if (BO->getOpcode() != BO_Assign) return false;
197 
198  ObjCPropertyRefExpr *PropRefExp =
199  dyn_cast<ObjCPropertyRefExpr>(BO->getLHS()->IgnoreParens());
200  if (!PropRefExp) return false;
201 
202  // TODO: Using implicit property decl.
203  if (PropRefExp->isImplicitProperty())
204  return false;
205 
206  if (ObjCPropertyDecl *PDecl = PropRefExp->getExplicitProperty()) {
207  if (!SynthesizedProperties.count(PDecl))
208  return false;
209  }
210 
211  return isZero(cast<OpaqueValueExpr>(BO->getRHS())->getSourceExpr());
212  }
213 
214  bool isZero(Expr *E) {
216  return true;
217 
218  return isZeroingPropIvar(E);
219  }
220 };
221 
222 } // anonymous namespace
223 
225  ZeroOutInDeallocRemover trans(pass);
226  trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
227 }
ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC property.
Definition: ExprObjC.h:539
Defines the clang::ASTContext interface.
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
Definition: Decl.h:1631
The receiver is an object instance.
Definition: ExprObjC.h:1005
Expr * getSyntacticForm()
Return the syntactic form of this expression, i.e.
Definition: Expr.h:5014
Smart pointer class that efficiently represents Objective-C method names.
Selector getSelector() const
Definition: ExprObjC.cpp:306
ObjCIvarDecl * getPropertyIvarDecl() const
Definition: DeclObjC.h:2711
Opcode getOpcode() const
Definition: Expr.h:3027
StringRef P
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:113
ObjCPropertyDecl * getExplicitProperty() const
Definition: ExprObjC.h:633
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:128
bool isDefined() const
Definition: DeclObjC.h:426
ObjCMethodDecl * getSetterMethodDecl() const
Definition: DeclObjC.h:878
IdentifierTable & Idents
Definition: ASTContext.h:515
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
Definition: DeclObjC.cpp:931
Selector getNullarySelector(IdentifierInfo *ID)
PropertyAttributeKind getPropertyAttributes() const
Definition: DeclObjC.h:799
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:2986
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
Definition: Expr.cpp:2462
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
ObjCPropertyImplDecl - Represents implementation declaration of a property in a class or category imp...
Definition: DeclObjC.h:2645
void collectRemovables(Stmt *S, ExprSet &exprs)
Definition: Transforms.cpp:308
BlockDecl - This represents a block literal declaration, which is like an unnamed FunctionDecl...
Definition: Decl.h:3587
Expr - This represents one expression.
Definition: Expr.h:106
Selector getSetterName() const
Definition: DeclObjC.h:868
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Definition: Expr.h:4852
DeclContext * getDeclContext()
Definition: DeclBase.h:416
Specifies that a value-dependent expression of integral or dependent type should be considered a null...
Definition: Expr.h:702
propimpl_range property_impls() const
Definition: DeclObjC.h:2367
An expression that sends a message to the given Objective-C object or class.
Definition: ExprObjC.h:860
bool isInstanceMethod() const
Definition: DeclObjC.h:416
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
Definition: ExprObjC.h:1136
ValueDecl * getDecl()
Definition: Expr.h:1041
Selector getSelector() const
Definition: DeclObjC.h:328
ImplicitParamDecl * getSelfDecl() const
Definition: DeclObjC.h:408
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: ExprObjC.h:1290
SelectorTable & Selectors
Definition: ASTContext.h:516
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
Definition: Expr.h:4970
bool isImplicitProperty() const
Definition: ExprObjC.h:630
NullPointerConstantKind isNullPointerConstant(ASTContext &Ctx, NullPointerConstantValueDependence NPC) const
isNullPointerConstant - C99 6.3.2.3p3 - Test if this reduces down to a Null pointer constant...
Definition: Expr.cpp:3272
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Stmt * getBody() const override
Retrieve the body of this method, if it has one.
Definition: DeclObjC.cpp:793
bool isObjCObjectPointerType() const
Definition: Type.h:5841
Represents one property declaration in an Objective-C interface.
Definition: DeclObjC.h:704
Expr * getLHS() const
Definition: Expr.h:3030
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
Definition: ExprObjC.h:1155
Dataflow Directional Tag Classes.
bool hasBody() const override
Determine whether this method has a body.
Definition: DeclObjC.h:486
void removeZeroOutPropsInDeallocFinalize(MigrationPass &pass)
ObjCIvarRefExpr - A reference to an ObjC instance variable.
Definition: ExprObjC.h:479
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:958
TransformActions & TA
Definition: Internals.h:151
ObjCIvarDecl - Represents an ObjC instance variable.
Definition: DeclObjC.h:1866
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:956
Expr * getRHS() const
Definition: Expr.h:3032
QualType getType() const
Definition: Decl.h:602
Expr * IgnoreParens() LLVM_READONLY
IgnoreParens - Ignore parentheses.
Definition: Expr.cpp:2431