TransProperties.cpp revision 18fd0c6915b45c4daafe18e3cd324c13306f913f
17196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//===--- TransProperties.cpp - Tranformations to ARC mode -----------------===// 27196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 37196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// The LLVM Compiler Infrastructure 47196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 57196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// This file is distributed under the University of Illinois Open Source 67196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// License. See LICENSE.TXT for details. 77196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 87196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 97196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 1014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis// rewriteProperties: 117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 1214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis// - Adds strong/weak/unsafe_unretained ownership specifier to properties that 1314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis// are missing one. 1414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis// - Migrates properties from (retain) to (strong) and (assign) to 1514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis// (unsafe_unretained/weak). 1614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis// - If a property is synthesized, adds the ownership specifier in the ivar 1714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis// backing the property. 187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// @interface Foo : NSObject { 207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// NSObject *x; 217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// } 227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// @property (assign) id x; 237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// @end 247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// ----> 257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// @interface Foo : NSObject { 267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// NSObject *__weak x; 277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// } 287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// @property (weak) id x; 297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// @end 307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "Transforms.h" 347196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "Internals.h" 357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "clang/Sema/SemaDiagnostic.h" 367196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "clang/Basic/SourceManager.h" 377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "clang/Lex/Lexer.h" 3814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#include <map> 397196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 407196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace clang; 417196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace arcmt; 427196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace trans; 437196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisnamespace { 457196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 4614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidisclass PropertiesRewriter { 477196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis MigrationPass &Pass; 4818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis ObjCImplementationDecl *CurImplD; 4914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 507196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis struct PropData { 517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis ObjCPropertyDecl *PropD; 527196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis ObjCIvarDecl *IvarD; 5314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis ObjCPropertyImplDecl *ImplD; 5414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 5514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis PropData(ObjCPropertyDecl *propD) : PropD(propD), IvarD(0), ImplD(0) { } 567196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis }; 577196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 585f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVector<PropData, 2> PropsTy; 5914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis typedef std::map<unsigned, PropsTy> AtPropDeclsTy; 6014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis AtPropDeclsTy AtProps; 617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 627196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidispublic: 6314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis PropertiesRewriter(MigrationPass &pass) : Pass(pass) { } 647196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 657196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis void doTransform(ObjCImplementationDecl *D) { 6618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis CurImplD = D; 6714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis ObjCInterfaceDecl *iface = D->getClassInterface(); 6814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (!iface) 6914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return; 707196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 717196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis for (ObjCInterfaceDecl::prop_iterator 7214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis propI = iface->prop_begin(), 7314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis propE = iface->prop_end(); propI != propE; ++propI) { 7414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (propI->getAtLoc().isInvalid()) 7514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis continue; 7614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis PropsTy &props = AtProps[propI->getAtLoc().getRawEncoding()]; 7714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis props.push_back(*propI); 787196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 797196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 807196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl> 817196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis prop_impl_iterator; 827196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis for (prop_impl_iterator 837196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis I = prop_impl_iterator(D->decls_begin()), 847196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis E = prop_impl_iterator(D->decls_end()); I != E; ++I) { 8514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis ObjCPropertyImplDecl *implD = *I; 8614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (implD->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize) 8714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis continue; 8814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis ObjCPropertyDecl *propD = implD->getPropertyDecl(); 8914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (!propD || propD->isInvalidDecl()) 9014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis continue; 9114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis ObjCIvarDecl *ivarD = implD->getPropertyIvarDecl(); 9214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (!ivarD || ivarD->isInvalidDecl()) 9314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis continue; 9414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis unsigned rawAtLoc = propD->getAtLoc().getRawEncoding(); 9514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis AtPropDeclsTy::iterator findAtLoc = AtProps.find(rawAtLoc); 9614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (findAtLoc == AtProps.end()) 9714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis continue; 9814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 9914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis PropsTy &props = findAtLoc->second; 10014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) { 10114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (I->PropD == propD) { 10214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis I->IvarD = ivarD; 10314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis I->ImplD = implD; 10414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis break; 10514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis } 10614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis } 1077196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1087196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 10914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis for (AtPropDeclsTy::iterator 11014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis I = AtProps.begin(), E = AtProps.end(); I != E; ++I) { 1117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first); 1127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis PropsTy &props = I->second; 11314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis QualType ty = getPropertyType(props); 11414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (!ty->isObjCRetainableType()) 11514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis continue; 11614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (hasIvarWithExplicitOwnership(props)) 11714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis continue; 11814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 11914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis Transaction Trans(Pass.TA); 12014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis rewriteProperty(props, atLoc); 1217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 12414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidisprivate: 12514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis void rewriteProperty(PropsTy &props, SourceLocation atLoc) const { 12614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props); 12714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 12814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (propAttrs & (ObjCPropertyDecl::OBJC_PR_copy | 12914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis ObjCPropertyDecl::OBJC_PR_unsafe_unretained | 13014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis ObjCPropertyDecl::OBJC_PR_strong | 13114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis ObjCPropertyDecl::OBJC_PR_weak)) 13214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return; 13314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 13414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (propAttrs & ObjCPropertyDecl::OBJC_PR_retain) { 13514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis rewriteAttribute("retain", "strong", atLoc); 13614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return; 1377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 13814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 13918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (propAttrs & ObjCPropertyDecl::OBJC_PR_assign) { 14018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (hasIvarAssignedAPlusOneObject(props)) { 14118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis rewriteAttribute("assign", "strong", atLoc); 14218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return; 14318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 14414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return rewriteAssign(props, atLoc); 14518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 14618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 14718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (hasIvarAssignedAPlusOneObject(props)) 14818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return maybeAddStrongAttr(props, atLoc); 14914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 15014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc); 1517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1527196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 15314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis void rewriteAssign(PropsTy &props, SourceLocation atLoc) const { 15414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props)); 15514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 15614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis bool rewroteAttr = rewriteAttribute("assign", 15714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis canUseWeak ? "weak" : "unsafe_unretained", 15814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis atLoc); 15914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (!rewroteAttr) 16014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis canUseWeak = false; 1617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 16214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) { 16314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (isUserDeclared(I->IvarD)) 16414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis Pass.TA.insert(I->IvarD->getLocation(), 16514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis canUseWeak ? "__weak " : "__unsafe_unretained "); 16614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (I->ImplD) 16714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership, 16814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis I->ImplD->getLocation()); 16914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis } 1707196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1717196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 17214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props, 17314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis SourceLocation atLoc) const { 17414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props); 17514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 17614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props)); 17718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (!(propAttrs & ObjCPropertyDecl::OBJC_PR_readonly) || 17818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis !hasAllIvarsBacked(props)) { 17918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained", 18018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis atLoc); 18118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (!addedAttr) 18218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis canUseWeak = false; 18318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 18414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 18514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) { 18614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (isUserDeclared(I->IvarD)) 18714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis Pass.TA.insert(I->IvarD->getLocation(), 18814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis canUseWeak ? "__weak " : "__unsafe_unretained "); 18914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (I->ImplD) { 190b8b0313e84700b5c6d597b3be4de41c97b7550f1Argyrios Kyrtzidis Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership, 19114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis I->ImplD->getLocation()); 19214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis Pass.TA.clearDiagnostic( 19314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis diag::err_arc_objc_property_default_assign_on_object, 19414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis I->ImplD->getLocation()); 1957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 19918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis void maybeAddStrongAttr(PropsTy &props, SourceLocation atLoc) const { 20018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props); 20118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 20218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (!(propAttrs & ObjCPropertyDecl::OBJC_PR_readonly) || 20318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis !hasAllIvarsBacked(props)) { 20418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis addAttribute("strong", atLoc); 20518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 20618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 20718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) { 20818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (I->ImplD) { 20918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership, 21018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis I->ImplD->getLocation()); 21118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis Pass.TA.clearDiagnostic( 21218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis diag::err_arc_objc_property_default_assign_on_object, 21318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis I->ImplD->getLocation()); 21418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 21518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 21618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 21718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 2185f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner bool rewriteAttribute(StringRef fromAttr, StringRef toAttr, 21914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis SourceLocation atLoc) const { 22014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (atLoc.isMacroID()) 22114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return false; 22214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 2237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis SourceManager &SM = Pass.Ctx.getSourceManager(); 2247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 22514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis // Break down the source location. 22614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc); 22714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 22814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis // Try to load the file buffer. 22914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis bool invalidTemp = false; 2305f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef file = SM.getBufferData(locInfo.first, &invalidTemp); 23114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (invalidTemp) 23214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return false; 2337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 23414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis const char *tokenBegin = file.data() + locInfo.second; 2357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 23614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis // Lex from the start of the given location. 23714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis Lexer lexer(SM.getLocForStartOfFile(locInfo.first), 23814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis Pass.Ctx.getLangOptions(), 23914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis file.begin(), tokenBegin, file.end()); 24014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis Token tok; 24114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 24214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (tok.isNot(tok::at)) return false; 24314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 24414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (tok.isNot(tok::raw_identifier)) return false; 2455f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner if (StringRef(tok.getRawIdentifierData(), tok.getLength()) 24614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis != "property") 24714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return false; 24814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 24914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (tok.isNot(tok::l_paren)) return false; 25014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 25114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 25214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (tok.is(tok::r_paren)) 25314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return false; 25414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 25514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis while (1) { 25614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (tok.isNot(tok::raw_identifier)) return false; 2575f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef ident(tok.getRawIdentifierData(), tok.getLength()); 25814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (ident == fromAttr) { 25914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr); 26014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return true; 2617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 26214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 26314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis do { 26414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 26514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis } while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren)); 26614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (tok.is(tok::r_paren)) 26714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis break; 26814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 2697196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 2707196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 27114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return false; 2727196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 2737196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2745f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner bool addAttribute(StringRef attr, SourceLocation atLoc) const { 27514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (atLoc.isMacroID()) 27614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return false; 27714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 2787196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis SourceManager &SM = Pass.Ctx.getSourceManager(); 2797196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2807196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // Break down the source location. 2817196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc); 2827196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2837196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // Try to load the file buffer. 2847196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool invalidTemp = false; 2855f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef file = SM.getBufferData(locInfo.first, &invalidTemp); 2867196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (invalidTemp) 28714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return false; 2887196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2897196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis const char *tokenBegin = file.data() + locInfo.second; 2907196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2917196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // Lex from the start of the given location. 2927196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Lexer lexer(SM.getLocForStartOfFile(locInfo.first), 2937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Pass.Ctx.getLangOptions(), 2947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis file.begin(), tokenBegin, file.end()); 2957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Token tok; 2967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 29714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (tok.isNot(tok::at)) return false; 2987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 29914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (tok.isNot(tok::raw_identifier)) return false; 3005f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner if (StringRef(tok.getRawIdentifierData(), tok.getLength()) 3017196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis != "property") 30214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return false; 3037196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 3047196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 30514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (tok.isNot(tok::l_paren)) { 30614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis Pass.TA.insert(tok.getLocation(), std::string("(") + attr.str() + ") "); 30714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return true; 30814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis } 30914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 3107196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 3117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (tok.is(tok::r_paren)) { 31214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis Pass.TA.insert(tok.getLocation(), attr); 31314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return true; 31414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis } 31514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 31614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (tok.isNot(tok::raw_identifier)) return false; 31714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 31814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis Pass.TA.insert(tok.getLocation(), std::string(attr) + ", "); 31914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return true; 32014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis } 32114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 32218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis class PlusOneAssign : public RecursiveASTVisitor<PlusOneAssign> { 32318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis ObjCIvarDecl *Ivar; 32418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis public: 32518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis PlusOneAssign(ObjCIvarDecl *D) : Ivar(D) {} 32618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 32718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis bool VisitBinAssign(BinaryOperator *E) { 32818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis Expr *lhs = E->getLHS()->IgnoreParenImpCasts(); 32918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(lhs)) { 33018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (RE->getDecl() != Ivar) 33118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return true; 33218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 33318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(E->getRHS()); 33418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis while (implCE && implCE->getCastKind() == CK_BitCast) 33518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis implCE = dyn_cast<ImplicitCastExpr>(implCE->getSubExpr()); 33618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 33718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (implCE && implCE->getCastKind() == CK_ObjCConsumeObject) 33818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return false; 33918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 34018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 34118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return true; 34218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 34318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis }; 34418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 34518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis bool hasIvarAssignedAPlusOneObject(PropsTy &props) const { 34618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) { 34718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis PlusOneAssign oneAssign(I->IvarD); 34818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis bool notFound = oneAssign.TraverseDecl(CurImplD); 34918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (!notFound) 35018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return true; 35118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 35218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 35318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return false; 35418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 35518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 35614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis bool hasIvarWithExplicitOwnership(PropsTy &props) const { 35714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) { 35814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (isUserDeclared(I->IvarD)) { 35914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (isa<AttributedType>(I->IvarD->getType())) 36014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return true; 36114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis if (I->IvarD->getType().getLocalQualifiers().getObjCLifetime() 36214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis != Qualifiers::OCL_Strong) 36314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return true; 3647196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 3657196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 3667196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 36714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return false; 36814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis } 36914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 37018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis bool hasAllIvarsBacked(PropsTy &props) const { 37114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) 37218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (!isUserDeclared(I->IvarD)) 37314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return false; 37414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 37514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return true; 37614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis } 37714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 37814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis bool isUserDeclared(ObjCIvarDecl *ivarD) const { 37914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return ivarD && !ivarD->getSynthesize(); 38014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis } 38114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 38214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis QualType getPropertyType(PropsTy &props) const { 38314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis assert(!props.empty()); 38414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis QualType ty = props[0].PropD->getType(); 38514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 38614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#ifndef NDEBUG 38714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) 38814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis assert(ty == I->PropD->getType()); 38914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#endif 39014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 39114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return ty; 39214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis } 39314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 39414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis ObjCPropertyDecl::PropertyAttributeKind 39514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis getPropertyAttrs(PropsTy &props) const { 39614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis assert(!props.empty()); 39714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis ObjCPropertyDecl::PropertyAttributeKind 39814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis attrs = props[0].PropD->getPropertyAttributesAsWritten(); 39914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 40014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#ifndef NDEBUG 40114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) 40214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis assert(attrs == I->PropD->getPropertyAttributesAsWritten()); 40314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#endif 40414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis 40514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis return attrs; 4067196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 4077196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis}; 4087196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 40914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidisclass ImplementationChecker : 41014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis public RecursiveASTVisitor<ImplementationChecker> { 4117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis MigrationPass &Pass; 4127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 4137196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidispublic: 41414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis ImplementationChecker(MigrationPass &pass) : Pass(pass) { } 4157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 4167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) { 41714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis PropertiesRewriter(Pass).doTransform(D); 4187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 4197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 4207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis}; 4217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 4227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} // anonymous namespace 4237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 42414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidisvoid trans::rewriteProperties(MigrationPass &pass) { 42514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis ImplementationChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl()); 4267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} 427