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:577
Defines the clang::ASTContext interface.
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
Definition: Decl.h:1698
The receiver is an object instance.
Definition: ExprObjC.h:1054
Expr * getSyntacticForm()
Return the syntactic form of this expression, i.e.
Definition: Expr.h:5013
Smart pointer class that efficiently represents Objective-C method names.
Selector getSelector() const
Definition: ExprObjC.cpp:312
ObjCIvarDecl * getPropertyIvarDecl() const
Definition: DeclObjC.h:2846
Opcode getOpcode() const
Definition: Expr.h:3026
StringRef P
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:139
ObjCPropertyDecl * getExplicitProperty() const
Definition: ExprObjC.h:670
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:149
bool isDefined() const
Definition: DeclObjC.h:462
ObjCMethodDecl * getSetterMethodDecl() const
Definition: DeclObjC.h:942
IdentifierTable & Idents
Definition: ASTContext.h:537
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
Definition: DeclObjC.cpp:943
Selector getNullarySelector(IdentifierInfo *ID)
PropertyAttributeKind getPropertyAttributes() const
Definition: DeclObjC.h:857
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:2985
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
Definition: Expr.cpp:2465
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:2778
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:3689
Expr - This represents one expression.
Definition: Expr.h:106
Selector getSetterName() const
Definition: DeclObjC.h:931
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Definition: Expr.h:4851
DeclContext * getDeclContext()
Definition: DeclBase.h:425
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:2486
An expression that sends a message to the given Objective-C object or class.
Definition: ExprObjC.h:903
bool isInstanceMethod() const
Definition: DeclObjC.h:452
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
Definition: ExprObjC.h:1187
ValueDecl * getDecl()
Definition: Expr.h:1041
Selector getSelector() const
Definition: DeclObjC.h:359
ImplicitParamDecl * getSelfDecl() const
Definition: DeclObjC.h:444
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: ExprObjC.h:1341
SelectorTable & Selectors
Definition: ASTContext.h:538
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
Definition: Expr.h:4969
bool isImplicitProperty() const
Definition: ExprObjC.h:667
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:3275
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:806
bool isObjCObjectPointerType() const
Definition: Type.h:6041
Represents one property declaration in an Objective-C interface.
Definition: DeclObjC.h:746
Expr * getLHS() const
Definition: Expr.h:3029
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
Definition: ExprObjC.h:1206
Dataflow Directional Tag Classes.
bool hasBody() const override
Determine whether this method has a body.
Definition: DeclObjC.h:524
void removeZeroOutPropsInDeallocFinalize(MigrationPass &pass)
ObjCIvarRefExpr - A reference to an ObjC instance variable.
Definition: ExprObjC.h:513
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:989
TransformActions & TA
Definition: Internals.h:151
ObjCIvarDecl - Represents an ObjC instance variable.
Definition: DeclObjC.h:1964
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:956
Expr * getRHS() const
Definition: Expr.h:3031
QualType getType() const
Definition: Decl.h:639
Expr * IgnoreParens() LLVM_READONLY
IgnoreParens - Ignore parentheses.
Definition: Expr.cpp:2434