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