blob: b6ddc43dd69fd9b8f02d63e399e8111f8ebc9b53 [file] [log] [blame]
Benjamin Krameraccaf192012-11-14 15:08:31 +00001//===--- TransProperties.cpp - Transformations to ARC mode ----------------===//
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +00002//
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//
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +000010// rewriteProperties:
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000011//
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +000012// - Adds strong/weak/unsafe_unretained ownership specifier to properties that
13// are missing one.
14// - Migrates properties from (retain) to (strong) and (assign) to
15// (unsafe_unretained/weak).
16// - If a property is synthesized, adds the ownership specifier in the ivar
17// backing the property.
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000018//
19// @interface Foo : NSObject {
20// NSObject *x;
21// }
22// @property (assign) id x;
23// @end
24// ---->
25// @interface Foo : NSObject {
26// NSObject *__weak x;
27// }
28// @property (weak) id x;
29// @end
30//
31//===----------------------------------------------------------------------===//
32
33#include "Transforms.h"
34#include "Internals.h"
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000035#include "clang/Basic/SourceManager.h"
36#include "clang/Lex/Lexer.h"
Chandler Carruth55fc8732012-12-04 09:13:33 +000037#include "clang/Sema/SemaDiagnostic.h"
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +000038#include <map>
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000039
40using namespace clang;
41using namespace arcmt;
42using namespace trans;
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000043
44namespace {
45
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +000046class PropertiesRewriter {
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +000047 MigrationContext &MigrateCtx;
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000048 MigrationPass &Pass;
Argyrios Kyrtzidis18fd0c62011-07-27 05:28:18 +000049 ObjCImplementationDecl *CurImplD;
Argyrios Kyrtzidis44679012011-10-18 19:49:19 +000050
51 enum PropActionKind {
52 PropAction_None,
Fariborz Jahanian86f96012012-01-20 19:15:02 +000053 PropAction_RetainReplacedWithStrong,
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +000054 PropAction_AssignRemoved,
Argyrios Kyrtzidis44679012011-10-18 19:49:19 +000055 PropAction_AssignRewritten,
Argyrios Kyrtzidis44679012011-10-18 19:49:19 +000056 PropAction_MaybeAddWeakOrUnsafe
57 };
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +000058
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000059 struct PropData {
60 ObjCPropertyDecl *PropD;
61 ObjCIvarDecl *IvarD;
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +000062 ObjCPropertyImplDecl *ImplD;
63
64 PropData(ObjCPropertyDecl *propD) : PropD(propD), IvarD(0), ImplD(0) { }
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000065 };
66
Chris Lattner5f9e2722011-07-23 10:55:15 +000067 typedef SmallVector<PropData, 2> PropsTy;
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +000068 typedef std::map<unsigned, PropsTy> AtPropDeclsTy;
69 AtPropDeclsTy AtProps;
Argyrios Kyrtzidis44679012011-10-18 19:49:19 +000070 llvm::DenseMap<IdentifierInfo *, PropActionKind> ActionOnProp;
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000071
72public:
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +000073 explicit PropertiesRewriter(MigrationContext &MigrateCtx)
74 : MigrateCtx(MigrateCtx), Pass(MigrateCtx.Pass) { }
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000075
Argyrios Kyrtzidis0fd4a682012-03-29 01:10:31 +000076 static void collectProperties(ObjCContainerDecl *D, AtPropDeclsTy &AtProps,
77 AtPropDeclsTy *PrevAtProps = 0) {
Argyrios Kyrtzidis44679012011-10-18 19:49:19 +000078 for (ObjCInterfaceDecl::prop_iterator
79 propI = D->prop_begin(),
80 propE = D->prop_end(); propI != propE; ++propI) {
81 if (propI->getAtLoc().isInvalid())
82 continue;
Argyrios Kyrtzidis0fd4a682012-03-29 01:10:31 +000083 unsigned RawLoc = propI->getAtLoc().getRawEncoding();
84 if (PrevAtProps)
85 if (PrevAtProps->find(RawLoc) != PrevAtProps->end())
86 continue;
87 PropsTy &props = AtProps[RawLoc];
David Blaikie581deb32012-06-06 20:45:41 +000088 props.push_back(*propI);
Argyrios Kyrtzidis44679012011-10-18 19:49:19 +000089 }
90 }
91
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000092 void doTransform(ObjCImplementationDecl *D) {
Argyrios Kyrtzidis18fd0c62011-07-27 05:28:18 +000093 CurImplD = D;
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +000094 ObjCInterfaceDecl *iface = D->getClassInterface();
95 if (!iface)
96 return;
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000097
Argyrios Kyrtzidis44679012011-10-18 19:49:19 +000098 collectProperties(iface, AtProps);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000099
100 typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl>
101 prop_impl_iterator;
102 for (prop_impl_iterator
103 I = prop_impl_iterator(D->decls_begin()),
104 E = prop_impl_iterator(D->decls_end()); I != E; ++I) {
David Blaikie581deb32012-06-06 20:45:41 +0000105 ObjCPropertyImplDecl *implD = *I;
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000106 if (implD->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
107 continue;
108 ObjCPropertyDecl *propD = implD->getPropertyDecl();
109 if (!propD || propD->isInvalidDecl())
110 continue;
111 ObjCIvarDecl *ivarD = implD->getPropertyIvarDecl();
112 if (!ivarD || ivarD->isInvalidDecl())
113 continue;
114 unsigned rawAtLoc = propD->getAtLoc().getRawEncoding();
115 AtPropDeclsTy::iterator findAtLoc = AtProps.find(rawAtLoc);
116 if (findAtLoc == AtProps.end())
117 continue;
118
119 PropsTy &props = findAtLoc->second;
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000120 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
121 if (I->PropD == propD) {
122 I->IvarD = ivarD;
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000123 I->ImplD = implD;
124 break;
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000125 }
126 }
127 }
128
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000129 for (AtPropDeclsTy::iterator
130 I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
131 SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
132 PropsTy &props = I->second;
Argyrios Kyrtzidis1d5fb8f2011-11-06 18:58:07 +0000133 if (!getPropertyType(props)->isObjCRetainableType())
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000134 continue;
Argyrios Kyrtzidisbf8455c2011-11-07 18:40:32 +0000135 if (hasIvarWithExplicitARCOwnership(props))
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000136 continue;
137
138 Transaction Trans(Pass.TA);
139 rewriteProperty(props, atLoc);
140 }
Argyrios Kyrtzidis44679012011-10-18 19:49:19 +0000141
142 AtPropDeclsTy AtExtProps;
143 // Look through extensions.
Douglas Gregord3297242013-01-16 23:00:23 +0000144 for (ObjCInterfaceDecl::visible_extensions_iterator
145 ext = iface->visible_extensions_begin(),
146 extEnd = iface->visible_extensions_end();
147 ext != extEnd; ++ext) {
148 collectProperties(*ext, AtExtProps, &AtProps);
149 }
Argyrios Kyrtzidis44679012011-10-18 19:49:19 +0000150
151 for (AtPropDeclsTy::iterator
152 I = AtExtProps.begin(), E = AtExtProps.end(); I != E; ++I) {
153 SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
154 PropsTy &props = I->second;
155 Transaction Trans(Pass.TA);
156 doActionForExtensionProp(props, atLoc);
157 }
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000158 }
159
160private:
Argyrios Kyrtzidis44679012011-10-18 19:49:19 +0000161 void doPropAction(PropActionKind kind,
162 PropsTy &props, SourceLocation atLoc,
163 bool markAction = true) {
164 if (markAction)
165 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
166 ActionOnProp[I->PropD->getIdentifier()] = kind;
167
168 switch (kind) {
169 case PropAction_None:
170 return;
Fariborz Jahanian86f96012012-01-20 19:15:02 +0000171 case PropAction_RetainReplacedWithStrong: {
172 StringRef toAttr = "strong";
173 MigrateCtx.rewritePropertyAttribute("retain", toAttr, atLoc);
Argyrios Kyrtzidis44679012011-10-18 19:49:19 +0000174 return;
Fariborz Jahanian86f96012012-01-20 19:15:02 +0000175 }
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +0000176 case PropAction_AssignRemoved:
177 return removeAssignForDefaultStrong(props, atLoc);
Argyrios Kyrtzidis44679012011-10-18 19:49:19 +0000178 case PropAction_AssignRewritten:
179 return rewriteAssign(props, atLoc);
Argyrios Kyrtzidis44679012011-10-18 19:49:19 +0000180 case PropAction_MaybeAddWeakOrUnsafe:
181 return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
182 }
183 }
184
185 void doActionForExtensionProp(PropsTy &props, SourceLocation atLoc) {
186 llvm::DenseMap<IdentifierInfo *, PropActionKind>::iterator I;
187 I = ActionOnProp.find(props[0].PropD->getIdentifier());
188 if (I == ActionOnProp.end())
189 return;
190
191 doPropAction(I->second, props, atLoc, false);
192 }
193
194 void rewriteProperty(PropsTy &props, SourceLocation atLoc) {
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000195 ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
196
197 if (propAttrs & (ObjCPropertyDecl::OBJC_PR_copy |
198 ObjCPropertyDecl::OBJC_PR_unsafe_unretained |
199 ObjCPropertyDecl::OBJC_PR_strong |
200 ObjCPropertyDecl::OBJC_PR_weak))
201 return;
202
203 if (propAttrs & ObjCPropertyDecl::OBJC_PR_retain) {
Argyrios Kyrtzidis8b08eb32011-11-08 23:09:34 +0000204 // strong is the default.
Fariborz Jahanian86f96012012-01-20 19:15:02 +0000205 return doPropAction(PropAction_RetainReplacedWithStrong, props, atLoc);
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000206 }
207
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +0000208 bool HasIvarAssignedAPlusOneObject = hasIvarAssignedAPlusOneObject(props);
209
Argyrios Kyrtzidis18fd0c62011-07-27 05:28:18 +0000210 if (propAttrs & ObjCPropertyDecl::OBJC_PR_assign) {
Fariborz Jahanian2f72ec92012-01-21 00:43:53 +0000211 if (HasIvarAssignedAPlusOneObject)
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +0000212 return doPropAction(PropAction_AssignRemoved, props, atLoc);
Argyrios Kyrtzidis44679012011-10-18 19:49:19 +0000213 return doPropAction(PropAction_AssignRewritten, props, atLoc);
Argyrios Kyrtzidis18fd0c62011-07-27 05:28:18 +0000214 }
215
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +0000216 if (HasIvarAssignedAPlusOneObject ||
217 (Pass.isGCMigration() && !hasGCWeak(props, atLoc)))
Argyrios Kyrtzidisaf9b5e92011-11-08 22:10:58 +0000218 return; // 'strong' by default.
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000219
Argyrios Kyrtzidis44679012011-10-18 19:49:19 +0000220 return doPropAction(PropAction_MaybeAddWeakOrUnsafe, props, atLoc);
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000221 }
222
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +0000223 void removeAssignForDefaultStrong(PropsTy &props,
224 SourceLocation atLoc) const {
225 removeAttribute("retain", atLoc);
226 if (!removeAttribute("assign", atLoc))
227 return;
228
229 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
230 if (I->ImplD)
Argyrios Kyrtzidis135aa602012-12-12 22:48:25 +0000231 Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
232 diag::err_arc_assign_property_ownership,
233 diag::err_arc_inconsistent_property_ownership,
234 I->IvarD->getLocation());
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +0000235 }
236 }
237
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000238 void rewriteAssign(PropsTy &props, SourceLocation atLoc) const {
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +0000239 bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
240 /*AllowOnUnknownClass=*/Pass.isGCMigration());
Fariborz Jahanian2f72ec92012-01-21 00:43:53 +0000241 const char *toWhich =
242 (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "strong" :
243 (canUseWeak ? "weak" : "unsafe_unretained");
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000244
Fariborz Jahanian2f72ec92012-01-21 00:43:53 +0000245 bool rewroteAttr = rewriteAttribute("assign", toWhich, atLoc);
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000246 if (!rewroteAttr)
247 canUseWeak = false;
248
249 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
Argyrios Kyrtzidis6d7d16d2011-11-28 00:23:12 +0000250 if (isUserDeclared(I->IvarD)) {
251 if (I->IvarD &&
Fariborz Jahanian2f72ec92012-01-21 00:43:53 +0000252 I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak) {
253 const char *toWhich =
254 (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "__strong " :
255 (canUseWeak ? "__weak " : "__unsafe_unretained ");
256 Pass.TA.insert(I->IvarD->getLocation(), toWhich);
257 }
Argyrios Kyrtzidis6d7d16d2011-11-28 00:23:12 +0000258 }
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000259 if (I->ImplD)
Argyrios Kyrtzidis135aa602012-12-12 22:48:25 +0000260 Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
261 diag::err_arc_assign_property_ownership,
262 diag::err_arc_inconsistent_property_ownership,
263 I->IvarD->getLocation());
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000264 }
265 }
266
267 void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
268 SourceLocation atLoc) const {
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +0000269 bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
270 /*AllowOnUnknownClass=*/Pass.isGCMigration());
Argyrios Kyrtzidis8b08eb32011-11-08 23:09:34 +0000271
272 bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained",
273 atLoc);
274 if (!addedAttr)
275 canUseWeak = false;
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000276
277 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
Argyrios Kyrtzidis6d7d16d2011-11-28 00:23:12 +0000278 if (isUserDeclared(I->IvarD)) {
279 if (I->IvarD &&
280 I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak)
281 Pass.TA.insert(I->IvarD->getLocation(),
282 canUseWeak ? "__weak " : "__unsafe_unretained ");
283 }
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000284 if (I->ImplD) {
Argyrios Kyrtzidis135aa602012-12-12 22:48:25 +0000285 Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
286 diag::err_arc_assign_property_ownership,
287 diag::err_arc_inconsistent_property_ownership,
288 I->IvarD->getLocation());
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000289 Pass.TA.clearDiagnostic(
290 diag::err_arc_objc_property_default_assign_on_object,
291 I->ImplD->getLocation());
292 }
293 }
294 }
295
Argyrios Kyrtzidis01b2b9b2011-10-17 23:14:16 +0000296 bool removeAttribute(StringRef fromAttr, SourceLocation atLoc) const {
Argyrios Kyrtzidis6da42742011-11-28 02:04:36 +0000297 return MigrateCtx.removePropertyAttribute(fromAttr, atLoc);
Argyrios Kyrtzidis01b2b9b2011-10-17 23:14:16 +0000298 }
299
Chris Lattner5f9e2722011-07-23 10:55:15 +0000300 bool rewriteAttribute(StringRef fromAttr, StringRef toAttr,
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000301 SourceLocation atLoc) const {
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +0000302 return MigrateCtx.rewritePropertyAttribute(fromAttr, toAttr, atLoc);
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000303 }
304
Chris Lattner5f9e2722011-07-23 10:55:15 +0000305 bool addAttribute(StringRef attr, SourceLocation atLoc) const {
Argyrios Kyrtzidis6da42742011-11-28 02:04:36 +0000306 return MigrateCtx.addPropertyAttribute(attr, atLoc);
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000307 }
308
Argyrios Kyrtzidis18fd0c62011-07-27 05:28:18 +0000309 class PlusOneAssign : public RecursiveASTVisitor<PlusOneAssign> {
310 ObjCIvarDecl *Ivar;
311 public:
312 PlusOneAssign(ObjCIvarDecl *D) : Ivar(D) {}
313
314 bool VisitBinAssign(BinaryOperator *E) {
315 Expr *lhs = E->getLHS()->IgnoreParenImpCasts();
316 if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(lhs)) {
317 if (RE->getDecl() != Ivar)
318 return true;
319
Argyrios Kyrtzidis1b8fbd32012-05-23 21:50:04 +0000320 if (isPlusOneAssign(E))
Argyrios Kyrtzidis94a90162011-08-10 21:46:48 +0000321 return false;
Argyrios Kyrtzidis18fd0c62011-07-27 05:28:18 +0000322 }
323
324 return true;
325 }
326 };
327
328 bool hasIvarAssignedAPlusOneObject(PropsTy &props) const {
329 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
330 PlusOneAssign oneAssign(I->IvarD);
331 bool notFound = oneAssign.TraverseDecl(CurImplD);
332 if (!notFound)
333 return true;
334 }
335
336 return false;
337 }
338
Argyrios Kyrtzidisbf8455c2011-11-07 18:40:32 +0000339 bool hasIvarWithExplicitARCOwnership(PropsTy &props) const {
340 if (Pass.isGCMigration())
341 return false;
342
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000343 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
344 if (isUserDeclared(I->IvarD)) {
345 if (isa<AttributedType>(I->IvarD->getType()))
346 return true;
347 if (I->IvarD->getType().getLocalQualifiers().getObjCLifetime()
348 != Qualifiers::OCL_Strong)
349 return true;
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000350 }
351 }
352
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000353 return false;
354 }
355
Argyrios Kyrtzidis18fd0c62011-07-27 05:28:18 +0000356 bool hasAllIvarsBacked(PropsTy &props) const {
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000357 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
Argyrios Kyrtzidis18fd0c62011-07-27 05:28:18 +0000358 if (!isUserDeclared(I->IvarD))
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000359 return false;
360
361 return true;
362 }
363
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +0000364 // \brief Returns true if all declarations in the @property have GC __weak.
365 bool hasGCWeak(PropsTy &props, SourceLocation atLoc) const {
366 if (!Pass.isGCMigration())
367 return false;
368 if (props.empty())
369 return false;
370 return MigrateCtx.AtPropsWeak.count(atLoc.getRawEncoding());
371 }
372
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000373 bool isUserDeclared(ObjCIvarDecl *ivarD) const {
374 return ivarD && !ivarD->getSynthesize();
375 }
376
377 QualType getPropertyType(PropsTy &props) const {
378 assert(!props.empty());
Argyrios Kyrtzidis1d5fb8f2011-11-06 18:58:07 +0000379 QualType ty = props[0].PropD->getType().getUnqualifiedType();
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000380
381#ifndef NDEBUG
382 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
Argyrios Kyrtzidis1d5fb8f2011-11-06 18:58:07 +0000383 assert(ty == I->PropD->getType().getUnqualifiedType());
Argyrios Kyrtzidis14c4b442011-07-13 19:22:00 +0000384#endif
385
386 return ty;
387 }
388
389 ObjCPropertyDecl::PropertyAttributeKind
390 getPropertyAttrs(PropsTy &props) const {
391 assert(!props.empty());
392 ObjCPropertyDecl::PropertyAttributeKind
393 attrs = props[0].PropD->getPropertyAttributesAsWritten();
394
395#ifndef NDEBUG
396 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
397 assert(attrs == I->PropD->getPropertyAttributesAsWritten());
398#endif
399
400 return attrs;
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000401 }
402};
403
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000404} // anonymous namespace
405
Argyrios Kyrtzidisb0d5db12011-11-06 18:57:57 +0000406void PropertyRewriteTraverser::traverseObjCImplementation(
407 ObjCImplementationContext &ImplCtx) {
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +0000408 PropertiesRewriter(ImplCtx.getMigrationContext())
Argyrios Kyrtzidisb0d5db12011-11-06 18:57:57 +0000409 .doTransform(ImplCtx.getImplementationDecl());
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000410}