TransProperties.cpp revision b8b0313e84700b5c6d597b3be4de41c97b7550f1
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// 107196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// changeIvarsOfAssignProperties: 117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// If a property is synthesized with 'assign' attribute and the user didn't 137196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// set a lifetime attribute, change the property to 'weak' or add 147196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// __unsafe_unretained if the ARC runtime is not available. 157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// @interface Foo : NSObject { 177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// NSObject *x; 187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// } 197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// @property (assign) id x; 207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// @end 217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// ----> 227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// @interface Foo : NSObject { 237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// NSObject *__weak x; 247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// } 257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// @property (weak) id x; 267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// @end 277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "Transforms.h" 317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "Internals.h" 327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "clang/Sema/SemaDiagnostic.h" 337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "clang/Basic/SourceManager.h" 347196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "clang/Lex/Lexer.h" 357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 367196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace clang; 377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace arcmt; 387196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace trans; 397196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing llvm::StringRef; 407196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 417196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisnamespace { 427196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 437196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisclass AssignPropertiesTrans { 447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis MigrationPass &Pass; 457196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis struct PropData { 467196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis ObjCPropertyDecl *PropD; 477196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis ObjCIvarDecl *IvarD; 487196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool ShouldChangeToWeak; 497196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis SourceLocation ArcPropAssignErrorLoc; 507196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis }; 517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 527196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis typedef llvm::SmallVector<PropData, 2> PropsTy; 537196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis typedef llvm::DenseMap<unsigned, PropsTy> PropsMapTy; 547196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis PropsMapTy PropsMap; 557196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 567196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidispublic: 577196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis AssignPropertiesTrans(MigrationPass &pass) : Pass(pass) { } 587196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis void doTransform(ObjCImplementationDecl *D) { 607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis SourceManager &SM = Pass.Ctx.getSourceManager(); 617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 627196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis ObjCInterfaceDecl *IFace = D->getClassInterface(); 637196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis for (ObjCInterfaceDecl::prop_iterator 647196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis I = IFace->prop_begin(), E = IFace->prop_end(); I != E; ++I) { 657196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis ObjCPropertyDecl *propD = *I; 667196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis unsigned loc = SM.getInstantiationLoc(propD->getAtLoc()).getRawEncoding(); 677196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis PropsTy &props = PropsMap[loc]; 687196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis props.push_back(PropData()); 697196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis props.back().PropD = propD; 707196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis props.back().IvarD = 0; 717196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis props.back().ShouldChangeToWeak = false; 727196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 737196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 747196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl> 757196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis prop_impl_iterator; 767196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis for (prop_impl_iterator 777196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis I = prop_impl_iterator(D->decls_begin()), 787196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis E = prop_impl_iterator(D->decls_end()); I != E; ++I) { 797196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis VisitObjCPropertyImplDecl(*I); 807196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 817196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 827196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis for (PropsMapTy::iterator 837196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis I = PropsMap.begin(), E = PropsMap.end(); I != E; ++I) { 847196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first); 857196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis PropsTy &props = I->second; 867196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (shouldApplyWeakToAllProp(props)) { 877196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (changeAssignToWeak(atLoc)) { 887196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // Couldn't add the 'weak' property attribute, 897196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // try adding __unsafe_unretained. 907196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis applyUnsafeUnretained(props); 917196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } else { 927196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis for (PropsTy::iterator 937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis PI = props.begin(), PE = props.end(); PI != PE; ++PI) { 947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis applyWeak(*PI); 957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } else { 987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // We should not add 'weak' attribute since not all properties need it. 997196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // So just add __unsafe_unretained to the ivars. 1007196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis applyUnsafeUnretained(props); 1017196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1027196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1037196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1047196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1057196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool shouldApplyWeakToAllProp(PropsTy &props) { 1067196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis for (PropsTy::iterator 1077196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis PI = props.begin(), PE = props.end(); PI != PE; ++PI) { 1087196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (!PI->ShouldChangeToWeak) 1097196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return false; 1107196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1137196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1147196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis void applyWeak(PropData &prop) { 1157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis assert(!Pass.Ctx.getLangOptions().ObjCNoAutoRefCountRuntime); 1167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Transaction Trans(Pass.TA); 1187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Pass.TA.insert(prop.IvarD->getLocation(), "__weak "); 119b8b0313e84700b5c6d597b3be4de41c97b7550f1Argyrios Kyrtzidis Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership, 1207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis prop.ArcPropAssignErrorLoc); 1217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis void applyUnsafeUnretained(PropsTy &props) { 1247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis for (PropsTy::iterator 1257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis PI = props.begin(), PE = props.end(); PI != PE; ++PI) { 1267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (PI->ShouldChangeToWeak) { 1277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Transaction Trans(Pass.TA); 1287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Pass.TA.insert(PI->IvarD->getLocation(), "__unsafe_unretained "); 129b8b0313e84700b5c6d597b3be4de41c97b7550f1Argyrios Kyrtzidis Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership, 1307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis PI->ArcPropAssignErrorLoc); 1317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1347196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { 1367196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis SourceManager &SM = Pass.Ctx.getSourceManager(); 1377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1387196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (D->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize) 1397196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1407196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis ObjCPropertyDecl *propD = D->getPropertyDecl(); 1417196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (!propD || propD->isInvalidDecl()) 1427196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1437196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis ObjCIvarDecl *ivarD = D->getPropertyIvarDecl(); 1447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (!ivarD || ivarD->isInvalidDecl()) 1457196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1467196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (!(propD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign)) 1477196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1487196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (isa<AttributedType>(ivarD->getType().getTypePtr())) 1497196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1507196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (ivarD->getType().getLocalQualifiers().getObjCLifetime() 1517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis != Qualifiers::OCL_Strong) 1527196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1537196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (!Pass.TA.hasDiagnostic( 154b8b0313e84700b5c6d597b3be4de41c97b7550f1Argyrios Kyrtzidis diag::err_arc_assign_property_ownership, D->getLocation())) 1557196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1567196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1577196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // There is a "error: existing ivar for assign property must be 1587196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // __unsafe_unretained"; fix it. 1597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (Pass.Ctx.getLangOptions().ObjCNoAutoRefCountRuntime) { 1617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // We will just add __unsafe_unretained to the ivar. 1627196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Transaction Trans(Pass.TA); 1637196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Pass.TA.insert(ivarD->getLocation(), "__unsafe_unretained "); 1647196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Pass.TA.clearDiagnostic( 165b8b0313e84700b5c6d597b3be4de41c97b7550f1Argyrios Kyrtzidis diag::err_arc_assign_property_ownership, D->getLocation()); 1667196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } else { 1677196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // Mark that we want the ivar to become weak. 1687196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis unsigned loc = SM.getInstantiationLoc(propD->getAtLoc()).getRawEncoding(); 1697196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis PropsTy &props = PropsMap[loc]; 1707196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) { 1717196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (I->PropD == propD) { 1727196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis I->IvarD = ivarD; 1737196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis I->ShouldChangeToWeak = true; 1747196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis I->ArcPropAssignErrorLoc = D->getLocation(); 1757196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1767196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1777196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1787196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1797196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1807196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1817196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1827196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisprivate: 1837196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool changeAssignToWeak(SourceLocation atLoc) { 1847196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis SourceManager &SM = Pass.Ctx.getSourceManager(); 1857196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1867196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // Break down the source location. 1877196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc); 1887196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1897196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // Try to load the file buffer. 1907196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool invalidTemp = false; 1917196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis llvm::StringRef file = SM.getBufferData(locInfo.first, &invalidTemp); 1927196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (invalidTemp) 1937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis const char *tokenBegin = file.data() + locInfo.second; 1967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // Lex from the start of the given location. 1987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Lexer lexer(SM.getLocForStartOfFile(locInfo.first), 1997196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Pass.Ctx.getLangOptions(), 2007196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis file.begin(), tokenBegin, file.end()); 2017196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Token tok; 2027196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 2037196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (tok.isNot(tok::at)) return true; 2047196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 2057196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (tok.isNot(tok::raw_identifier)) return true; 2067196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (llvm::StringRef(tok.getRawIdentifierData(), tok.getLength()) 2077196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis != "property") 2087196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 2097196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 2107196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (tok.isNot(tok::l_paren)) return true; 2117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis SourceLocation LParen = tok.getLocation(); 2137196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis SourceLocation assignLoc; 2147196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool isEmpty = false; 2157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 2177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (tok.is(tok::r_paren)) { 2187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis isEmpty = true; 2197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } else { 2207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis while (1) { 2217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (tok.isNot(tok::raw_identifier)) return true; 2227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis llvm::StringRef ident(tok.getRawIdentifierData(), tok.getLength()); 2237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (ident == "assign") 2247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis assignLoc = tok.getLocation(); 2257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis do { 2277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 2287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren)); 2297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (tok.is(tok::r_paren)) 2307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis break; 2317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 2327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 2337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 2347196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Transaction Trans(Pass.TA); 2367196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (assignLoc.isValid()) 2377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Pass.TA.replaceText(assignLoc, "assign", "weak"); 2387196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis else 2397196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Pass.TA.insertAfterToken(LParen, isEmpty ? "weak" : "weak, "); 2407196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return false; 2417196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 2427196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis}; 2437196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisclass PropertiesChecker : public RecursiveASTVisitor<PropertiesChecker> { 2457196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis MigrationPass &Pass; 2467196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2477196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidispublic: 2487196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis PropertiesChecker(MigrationPass &pass) : Pass(pass) { } 2497196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2507196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) { 2517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis AssignPropertiesTrans(Pass).doTransform(D); 2527196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 2537196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 2547196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis}; 2557196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2567196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} // anonymous namespace 2577196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2587196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisvoid trans::changeIvarsOfAssignProperties(MigrationPass &pass) { 2597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis PropertiesChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl()); 2607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} 261