blob: f9c02061343ffb04cb3535e9389042af900505fc [file] [log] [blame]
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +00001//===--- TransProperties.cpp - Tranformations 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//
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +000010// rewriteProperties:
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +000011//
Argyrios Kyrtzidisc8b36192011-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 Kyrtzidise5b475c2011-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"
35#include "clang/Sema/SemaDiagnostic.h"
36#include "clang/Basic/SourceManager.h"
37#include "clang/Lex/Lexer.h"
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +000038#include <map>
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +000039
40using namespace clang;
41using namespace arcmt;
42using namespace trans;
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +000043
44namespace {
45
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +000046class PropertiesRewriter {
Argyrios Kyrtzidis722d21c2011-11-07 18:46:46 +000047 MigrationContext &MigrateCtx;
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +000048 MigrationPass &Pass;
Argyrios Kyrtzidis93907472011-07-27 05:28:18 +000049 ObjCImplementationDecl *CurImplD;
Argyrios Kyrtzidis05c65fb2011-10-18 19:49:19 +000050
51 enum PropActionKind {
52 PropAction_None,
53 PropAction_RetainToStrong,
54 PropAction_RetainRemoved,
Argyrios Kyrtzidis722d21c2011-11-07 18:46:46 +000055 PropAction_AssignRemoved,
Argyrios Kyrtzidis05c65fb2011-10-18 19:49:19 +000056 PropAction_AssignRewritten,
57 PropAction_MaybeAddStrong,
58 PropAction_MaybeAddWeakOrUnsafe
59 };
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +000060
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +000061 struct PropData {
62 ObjCPropertyDecl *PropD;
63 ObjCIvarDecl *IvarD;
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +000064 ObjCPropertyImplDecl *ImplD;
65
66 PropData(ObjCPropertyDecl *propD) : PropD(propD), IvarD(0), ImplD(0) { }
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +000067 };
68
Chris Lattner0e62c1c2011-07-23 10:55:15 +000069 typedef SmallVector<PropData, 2> PropsTy;
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +000070 typedef std::map<unsigned, PropsTy> AtPropDeclsTy;
71 AtPropDeclsTy AtProps;
Argyrios Kyrtzidis05c65fb2011-10-18 19:49:19 +000072 llvm::DenseMap<IdentifierInfo *, PropActionKind> ActionOnProp;
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +000073
74public:
Argyrios Kyrtzidis722d21c2011-11-07 18:46:46 +000075 explicit PropertiesRewriter(MigrationContext &MigrateCtx)
76 : MigrateCtx(MigrateCtx), Pass(MigrateCtx.Pass) { }
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +000077
Argyrios Kyrtzidis05c65fb2011-10-18 19:49:19 +000078 static void collectProperties(ObjCContainerDecl *D, AtPropDeclsTy &AtProps) {
79 for (ObjCInterfaceDecl::prop_iterator
80 propI = D->prop_begin(),
81 propE = D->prop_end(); propI != propE; ++propI) {
82 if (propI->getAtLoc().isInvalid())
83 continue;
84 PropsTy &props = AtProps[propI->getAtLoc().getRawEncoding()];
85 props.push_back(*propI);
86 }
87 }
88
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +000089 void doTransform(ObjCImplementationDecl *D) {
Argyrios Kyrtzidis93907472011-07-27 05:28:18 +000090 CurImplD = D;
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +000091 ObjCInterfaceDecl *iface = D->getClassInterface();
92 if (!iface)
93 return;
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +000094
Argyrios Kyrtzidis05c65fb2011-10-18 19:49:19 +000095 collectProperties(iface, AtProps);
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +000096
97 typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl>
98 prop_impl_iterator;
99 for (prop_impl_iterator
100 I = prop_impl_iterator(D->decls_begin()),
101 E = prop_impl_iterator(D->decls_end()); I != E; ++I) {
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000102 ObjCPropertyImplDecl *implD = *I;
103 if (implD->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
104 continue;
105 ObjCPropertyDecl *propD = implD->getPropertyDecl();
106 if (!propD || propD->isInvalidDecl())
107 continue;
108 ObjCIvarDecl *ivarD = implD->getPropertyIvarDecl();
109 if (!ivarD || ivarD->isInvalidDecl())
110 continue;
111 unsigned rawAtLoc = propD->getAtLoc().getRawEncoding();
112 AtPropDeclsTy::iterator findAtLoc = AtProps.find(rawAtLoc);
113 if (findAtLoc == AtProps.end())
114 continue;
115
116 PropsTy &props = findAtLoc->second;
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000117 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
118 if (I->PropD == propD) {
119 I->IvarD = ivarD;
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000120 I->ImplD = implD;
121 break;
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000122 }
123 }
124 }
125
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000126 for (AtPropDeclsTy::iterator
127 I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
128 SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
129 PropsTy &props = I->second;
Argyrios Kyrtzidisaa421ea2011-11-06 18:58:07 +0000130 if (!getPropertyType(props)->isObjCRetainableType())
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000131 continue;
Argyrios Kyrtzidis0dd98a42011-11-07 18:40:32 +0000132 if (hasIvarWithExplicitARCOwnership(props))
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000133 continue;
134
135 Transaction Trans(Pass.TA);
136 rewriteProperty(props, atLoc);
137 }
Argyrios Kyrtzidis05c65fb2011-10-18 19:49:19 +0000138
139 AtPropDeclsTy AtExtProps;
140 // Look through extensions.
141 for (ObjCCategoryDecl *Cat = iface->getCategoryList();
142 Cat; Cat = Cat->getNextClassCategory())
143 if (Cat->IsClassExtension())
144 collectProperties(Cat, AtExtProps);
145
146 for (AtPropDeclsTy::iterator
147 I = AtExtProps.begin(), E = AtExtProps.end(); I != E; ++I) {
148 SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
149 PropsTy &props = I->second;
150 Transaction Trans(Pass.TA);
151 doActionForExtensionProp(props, atLoc);
152 }
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000153 }
154
155private:
Argyrios Kyrtzidis05c65fb2011-10-18 19:49:19 +0000156 void doPropAction(PropActionKind kind,
157 PropsTy &props, SourceLocation atLoc,
158 bool markAction = true) {
159 if (markAction)
160 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
161 ActionOnProp[I->PropD->getIdentifier()] = kind;
162
163 switch (kind) {
164 case PropAction_None:
165 return;
166 case PropAction_RetainToStrong:
167 rewriteAttribute("retain", "strong", atLoc);
168 return;
169 case PropAction_RetainRemoved:
170 removeAttribute("retain", atLoc);
171 return;
Argyrios Kyrtzidis722d21c2011-11-07 18:46:46 +0000172 case PropAction_AssignRemoved:
173 return removeAssignForDefaultStrong(props, atLoc);
Argyrios Kyrtzidis05c65fb2011-10-18 19:49:19 +0000174 case PropAction_AssignRewritten:
175 return rewriteAssign(props, atLoc);
176 case PropAction_MaybeAddStrong:
177 return maybeAddStrongAttr(props, atLoc);
178 case PropAction_MaybeAddWeakOrUnsafe:
179 return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
180 }
181 }
182
183 void doActionForExtensionProp(PropsTy &props, SourceLocation atLoc) {
184 llvm::DenseMap<IdentifierInfo *, PropActionKind>::iterator I;
185 I = ActionOnProp.find(props[0].PropD->getIdentifier());
186 if (I == ActionOnProp.end())
187 return;
188
189 doPropAction(I->second, props, atLoc, false);
190 }
191
192 void rewriteProperty(PropsTy &props, SourceLocation atLoc) {
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000193 ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
194
195 if (propAttrs & (ObjCPropertyDecl::OBJC_PR_copy |
196 ObjCPropertyDecl::OBJC_PR_unsafe_unretained |
197 ObjCPropertyDecl::OBJC_PR_strong |
198 ObjCPropertyDecl::OBJC_PR_weak))
199 return;
200
201 if (propAttrs & ObjCPropertyDecl::OBJC_PR_retain) {
Argyrios Kyrtzidisffe8b1c2011-10-17 23:14:16 +0000202 if (propAttrs & ObjCPropertyDecl::OBJC_PR_readonly)
Argyrios Kyrtzidis05c65fb2011-10-18 19:49:19 +0000203 return doPropAction(PropAction_RetainToStrong, props, atLoc);
Argyrios Kyrtzidisffe8b1c2011-10-17 23:14:16 +0000204 else
Argyrios Kyrtzidis05c65fb2011-10-18 19:49:19 +0000205 // strong is the default.
206 return doPropAction(PropAction_RetainRemoved, props, atLoc);
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000207 }
208
Argyrios Kyrtzidis722d21c2011-11-07 18:46:46 +0000209 bool HasIvarAssignedAPlusOneObject = hasIvarAssignedAPlusOneObject(props);
210
Argyrios Kyrtzidis93907472011-07-27 05:28:18 +0000211 if (propAttrs & ObjCPropertyDecl::OBJC_PR_assign) {
Argyrios Kyrtzidis722d21c2011-11-07 18:46:46 +0000212 if (HasIvarAssignedAPlusOneObject ||
213 (Pass.isGCMigration() && !hasGCWeak(props, atLoc))) {
214 return doPropAction(PropAction_AssignRemoved, props, atLoc);
Argyrios Kyrtzidis93907472011-07-27 05:28:18 +0000215 }
Argyrios Kyrtzidis05c65fb2011-10-18 19:49:19 +0000216 return doPropAction(PropAction_AssignRewritten, props, atLoc);
Argyrios Kyrtzidis93907472011-07-27 05:28:18 +0000217 }
218
Argyrios Kyrtzidis722d21c2011-11-07 18:46:46 +0000219 if (HasIvarAssignedAPlusOneObject ||
220 (Pass.isGCMigration() && !hasGCWeak(props, atLoc)))
Argyrios Kyrtzidise4a38a72011-11-08 22:10:58 +0000221 return; // 'strong' by default.
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000222
Argyrios Kyrtzidis05c65fb2011-10-18 19:49:19 +0000223 return doPropAction(PropAction_MaybeAddWeakOrUnsafe, props, atLoc);
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000224 }
225
Argyrios Kyrtzidis722d21c2011-11-07 18:46:46 +0000226 void removeAssignForDefaultStrong(PropsTy &props,
227 SourceLocation atLoc) const {
228 removeAttribute("retain", atLoc);
229 if (!removeAttribute("assign", atLoc))
230 return;
231
232 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
233 if (I->ImplD)
234 Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
235 I->ImplD->getLocation());
236 }
237 }
238
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000239 void rewriteAssign(PropsTy &props, SourceLocation atLoc) const {
Argyrios Kyrtzidis722d21c2011-11-07 18:46:46 +0000240 bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
241 /*AllowOnUnknownClass=*/Pass.isGCMigration());
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000242
243 bool rewroteAttr = rewriteAttribute("assign",
244 canUseWeak ? "weak" : "unsafe_unretained",
245 atLoc);
246 if (!rewroteAttr)
247 canUseWeak = false;
248
249 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
250 if (isUserDeclared(I->IvarD))
251 Pass.TA.insert(I->IvarD->getLocation(),
252 canUseWeak ? "__weak " : "__unsafe_unretained ");
253 if (I->ImplD)
254 Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
255 I->ImplD->getLocation());
256 }
257 }
258
259 void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
260 SourceLocation atLoc) const {
261 ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000262
Argyrios Kyrtzidis722d21c2011-11-07 18:46:46 +0000263 bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
264 /*AllowOnUnknownClass=*/Pass.isGCMigration());
Argyrios Kyrtzidis93907472011-07-27 05:28:18 +0000265 if (!(propAttrs & ObjCPropertyDecl::OBJC_PR_readonly) ||
266 !hasAllIvarsBacked(props)) {
267 bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained",
268 atLoc);
269 if (!addedAttr)
270 canUseWeak = false;
271 }
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000272
273 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
274 if (isUserDeclared(I->IvarD))
275 Pass.TA.insert(I->IvarD->getLocation(),
276 canUseWeak ? "__weak " : "__unsafe_unretained ");
277 if (I->ImplD) {
278 Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
279 I->ImplD->getLocation());
280 Pass.TA.clearDiagnostic(
281 diag::err_arc_objc_property_default_assign_on_object,
282 I->ImplD->getLocation());
283 }
284 }
285 }
286
Argyrios Kyrtzidis93907472011-07-27 05:28:18 +0000287 void maybeAddStrongAttr(PropsTy &props, SourceLocation atLoc) const {
288 ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
289
Argyrios Kyrtzidisdbe077a2011-11-08 05:56:11 +0000290 if (!(propAttrs & ObjCPropertyDecl::OBJC_PR_readonly))
291 return; // 'strong' by default.
292
293 if (!hasAllIvarsBacked(props)) {
Argyrios Kyrtzidis93907472011-07-27 05:28:18 +0000294 addAttribute("strong", atLoc);
295 }
296
297 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
298 if (I->ImplD) {
299 Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
300 I->ImplD->getLocation());
301 Pass.TA.clearDiagnostic(
302 diag::err_arc_objc_property_default_assign_on_object,
303 I->ImplD->getLocation());
304 }
305 }
306 }
307
Argyrios Kyrtzidisffe8b1c2011-10-17 23:14:16 +0000308 bool removeAttribute(StringRef fromAttr, SourceLocation atLoc) const {
309 return rewriteAttribute(fromAttr, StringRef(), atLoc);
310 }
311
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000312 bool rewriteAttribute(StringRef fromAttr, StringRef toAttr,
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000313 SourceLocation atLoc) const {
Argyrios Kyrtzidis722d21c2011-11-07 18:46:46 +0000314 return MigrateCtx.rewritePropertyAttribute(fromAttr, toAttr, atLoc);
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000315 }
316
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000317 bool addAttribute(StringRef attr, SourceLocation atLoc) const {
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000318 if (atLoc.isMacroID())
319 return false;
320
321 SourceManager &SM = Pass.Ctx.getSourceManager();
322
323 // Break down the source location.
324 std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
325
326 // Try to load the file buffer.
327 bool invalidTemp = false;
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000328 StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000329 if (invalidTemp)
330 return false;
331
332 const char *tokenBegin = file.data() + locInfo.second;
333
334 // Lex from the start of the given location.
335 Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
336 Pass.Ctx.getLangOptions(),
337 file.begin(), tokenBegin, file.end());
338 Token tok;
339 lexer.LexFromRawLexer(tok);
340 if (tok.isNot(tok::at)) return false;
341 lexer.LexFromRawLexer(tok);
342 if (tok.isNot(tok::raw_identifier)) return false;
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000343 if (StringRef(tok.getRawIdentifierData(), tok.getLength())
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000344 != "property")
345 return false;
346 lexer.LexFromRawLexer(tok);
347
348 if (tok.isNot(tok::l_paren)) {
349 Pass.TA.insert(tok.getLocation(), std::string("(") + attr.str() + ") ");
350 return true;
351 }
352
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000353 lexer.LexFromRawLexer(tok);
354 if (tok.is(tok::r_paren)) {
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000355 Pass.TA.insert(tok.getLocation(), attr);
356 return true;
357 }
358
359 if (tok.isNot(tok::raw_identifier)) return false;
360
361 Pass.TA.insert(tok.getLocation(), std::string(attr) + ", ");
362 return true;
363 }
364
Argyrios Kyrtzidis93907472011-07-27 05:28:18 +0000365 class PlusOneAssign : public RecursiveASTVisitor<PlusOneAssign> {
366 ObjCIvarDecl *Ivar;
367 public:
368 PlusOneAssign(ObjCIvarDecl *D) : Ivar(D) {}
369
370 bool VisitBinAssign(BinaryOperator *E) {
371 Expr *lhs = E->getLHS()->IgnoreParenImpCasts();
372 if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(lhs)) {
373 if (RE->getDecl() != Ivar)
374 return true;
375
Argyrios Kyrtzidis93db2272011-08-10 21:46:48 +0000376 if (ObjCMessageExpr *
377 ME = dyn_cast<ObjCMessageExpr>(E->getRHS()->IgnoreParenCasts()))
378 if (ME->getMethodFamily() == OMF_retain)
379 return false;
380
Argyrios Kyrtzidis93907472011-07-27 05:28:18 +0000381 ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(E->getRHS());
382 while (implCE && implCE->getCastKind() == CK_BitCast)
383 implCE = dyn_cast<ImplicitCastExpr>(implCE->getSubExpr());
384
John McCall2d637d22011-09-10 06:18:15 +0000385 if (implCE && implCE->getCastKind() == CK_ARCConsumeObject)
Argyrios Kyrtzidis93907472011-07-27 05:28:18 +0000386 return false;
387 }
388
389 return true;
390 }
391 };
392
393 bool hasIvarAssignedAPlusOneObject(PropsTy &props) const {
394 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
395 PlusOneAssign oneAssign(I->IvarD);
396 bool notFound = oneAssign.TraverseDecl(CurImplD);
397 if (!notFound)
398 return true;
399 }
400
401 return false;
402 }
403
Argyrios Kyrtzidis0dd98a42011-11-07 18:40:32 +0000404 bool hasIvarWithExplicitARCOwnership(PropsTy &props) const {
405 if (Pass.isGCMigration())
406 return false;
407
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000408 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
409 if (isUserDeclared(I->IvarD)) {
410 if (isa<AttributedType>(I->IvarD->getType()))
411 return true;
412 if (I->IvarD->getType().getLocalQualifiers().getObjCLifetime()
413 != Qualifiers::OCL_Strong)
414 return true;
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000415 }
416 }
417
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000418 return false;
419 }
420
Argyrios Kyrtzidis93907472011-07-27 05:28:18 +0000421 bool hasAllIvarsBacked(PropsTy &props) const {
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000422 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
Argyrios Kyrtzidis93907472011-07-27 05:28:18 +0000423 if (!isUserDeclared(I->IvarD))
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000424 return false;
425
426 return true;
427 }
428
Argyrios Kyrtzidis722d21c2011-11-07 18:46:46 +0000429 // \brief Returns true if all declarations in the @property have GC __weak.
430 bool hasGCWeak(PropsTy &props, SourceLocation atLoc) const {
431 if (!Pass.isGCMigration())
432 return false;
433 if (props.empty())
434 return false;
435 return MigrateCtx.AtPropsWeak.count(atLoc.getRawEncoding());
436 }
437
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000438 bool isUserDeclared(ObjCIvarDecl *ivarD) const {
439 return ivarD && !ivarD->getSynthesize();
440 }
441
442 QualType getPropertyType(PropsTy &props) const {
443 assert(!props.empty());
Argyrios Kyrtzidisaa421ea2011-11-06 18:58:07 +0000444 QualType ty = props[0].PropD->getType().getUnqualifiedType();
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000445
446#ifndef NDEBUG
447 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
Argyrios Kyrtzidisaa421ea2011-11-06 18:58:07 +0000448 assert(ty == I->PropD->getType().getUnqualifiedType());
Argyrios Kyrtzidisc8b36192011-07-13 19:22:00 +0000449#endif
450
451 return ty;
452 }
453
454 ObjCPropertyDecl::PropertyAttributeKind
455 getPropertyAttrs(PropsTy &props) const {
456 assert(!props.empty());
457 ObjCPropertyDecl::PropertyAttributeKind
458 attrs = props[0].PropD->getPropertyAttributesAsWritten();
459
460#ifndef NDEBUG
461 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
462 assert(attrs == I->PropD->getPropertyAttributesAsWritten());
463#endif
464
465 return attrs;
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000466 }
467};
468
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000469} // anonymous namespace
470
Argyrios Kyrtzidisaaa99962011-11-06 18:57:57 +0000471void PropertyRewriteTraverser::traverseObjCImplementation(
472 ObjCImplementationContext &ImplCtx) {
Argyrios Kyrtzidis722d21c2011-11-07 18:46:46 +0000473 PropertiesRewriter(ImplCtx.getMigrationContext())
Argyrios Kyrtzidisaaa99962011-11-06 18:57:57 +0000474 .doTransform(ImplCtx.getImplementationDecl());
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000475}