TransProperties.cpp revision af9b5e9f3eede62347835d8dedd44df86cbcc308
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 {
47b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  MigrationContext &MigrateCtx;
487196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  MigrationPass &Pass;
4918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  ObjCImplementationDecl *CurImplD;
5044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
5144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  enum PropActionKind {
5244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    PropAction_None,
5344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    PropAction_RetainToStrong,
5444679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    PropAction_RetainRemoved,
55b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    PropAction_AssignRemoved,
5644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    PropAction_AssignRewritten,
5744679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    PropAction_MaybeAddStrong,
5844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    PropAction_MaybeAddWeakOrUnsafe
5944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  };
6014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  struct PropData {
627196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    ObjCPropertyDecl *PropD;
637196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    ObjCIvarDecl *IvarD;
6414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    ObjCPropertyImplDecl *ImplD;
6514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
6614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    PropData(ObjCPropertyDecl *propD) : PropD(propD), IvarD(0), ImplD(0) { }
677196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  };
687196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
695f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  typedef SmallVector<PropData, 2> PropsTy;
7014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  typedef std::map<unsigned, PropsTy> AtPropDeclsTy;
7114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  AtPropDeclsTy AtProps;
7244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  llvm::DenseMap<IdentifierInfo *, PropActionKind> ActionOnProp;
737196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
747196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidispublic:
75b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  explicit PropertiesRewriter(MigrationContext &MigrateCtx)
76b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    : MigrateCtx(MigrateCtx), Pass(MigrateCtx.Pass) { }
777196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
7844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  static void collectProperties(ObjCContainerDecl *D, AtPropDeclsTy &AtProps) {
797196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    for (ObjCInterfaceDecl::prop_iterator
8044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis           propI = D->prop_begin(),
8144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis           propE = D->prop_end(); propI != propE; ++propI) {
8214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (propI->getAtLoc().isInvalid())
8314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
8414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      PropsTy &props = AtProps[propI->getAtLoc().getRawEncoding()];
8514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      props.push_back(*propI);
867196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
8744679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  }
8844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
8944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  void doTransform(ObjCImplementationDecl *D) {
9044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    CurImplD = D;
9144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    ObjCInterfaceDecl *iface = D->getClassInterface();
9244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    if (!iface)
9344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return;
9444679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
9544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    collectProperties(iface, AtProps);
967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl>
987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        prop_impl_iterator;
997196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    for (prop_impl_iterator
1007196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis           I = prop_impl_iterator(D->decls_begin()),
1017196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis           E = prop_impl_iterator(D->decls_end()); I != E; ++I) {
10214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      ObjCPropertyImplDecl *implD = *I;
10314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (implD->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
10414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
10514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      ObjCPropertyDecl *propD = implD->getPropertyDecl();
10614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (!propD || propD->isInvalidDecl())
10714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
10814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      ObjCIvarDecl *ivarD = implD->getPropertyIvarDecl();
10914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (!ivarD || ivarD->isInvalidDecl())
11014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
11114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      unsigned rawAtLoc = propD->getAtLoc().getRawEncoding();
11214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      AtPropDeclsTy::iterator findAtLoc = AtProps.find(rawAtLoc);
11314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (findAtLoc == AtProps.end())
11414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
11514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
11614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      PropsTy &props = findAtLoc->second;
11714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
11814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        if (I->PropD == propD) {
11914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          I->IvarD = ivarD;
12014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          I->ImplD = implD;
12114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          break;
12214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        }
12314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      }
1247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
1257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
12614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (AtPropDeclsTy::iterator
12714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis           I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
1287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
1297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      PropsTy &props = I->second;
1301d5fb8f6e85a5c9c7b9b611be655454159c92f12Argyrios Kyrtzidis      if (!getPropertyType(props)->isObjCRetainableType())
13114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
132bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis      if (hasIvarWithExplicitARCOwnership(props))
13314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
13414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
13514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      Transaction Trans(Pass.TA);
13614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      rewriteProperty(props, atLoc);
1377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
13844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
13944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    AtPropDeclsTy AtExtProps;
14044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    // Look through extensions.
14144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    for (ObjCCategoryDecl *Cat = iface->getCategoryList();
14244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis           Cat; Cat = Cat->getNextClassCategory())
14344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      if (Cat->IsClassExtension())
14444679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis        collectProperties(Cat, AtExtProps);
14544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
14644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    for (AtPropDeclsTy::iterator
14744679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis           I = AtExtProps.begin(), E = AtExtProps.end(); I != E; ++I) {
14844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
14944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      PropsTy &props = I->second;
15044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      Transaction Trans(Pass.TA);
15144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      doActionForExtensionProp(props, atLoc);
15244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    }
1537196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
1547196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
15514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidisprivate:
15644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  void doPropAction(PropActionKind kind,
15744679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis                    PropsTy &props, SourceLocation atLoc,
15844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis                    bool markAction = true) {
15944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    if (markAction)
16044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
16144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis        ActionOnProp[I->PropD->getIdentifier()] = kind;
16244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
16344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    switch (kind) {
16444679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    case PropAction_None:
16544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return;
16644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    case PropAction_RetainToStrong:
16744679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      rewriteAttribute("retain", "strong", atLoc);
16844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return;
16944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    case PropAction_RetainRemoved:
17044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      removeAttribute("retain", atLoc);
17144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return;
172b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    case PropAction_AssignRemoved:
173b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return removeAssignForDefaultStrong(props, atLoc);
17444679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    case PropAction_AssignRewritten:
17544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return rewriteAssign(props, atLoc);
17644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    case PropAction_MaybeAddStrong:
17744679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return maybeAddStrongAttr(props, atLoc);
17844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    case PropAction_MaybeAddWeakOrUnsafe:
17944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
18044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    }
18144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  }
18244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
18344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  void doActionForExtensionProp(PropsTy &props, SourceLocation atLoc) {
18444679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    llvm::DenseMap<IdentifierInfo *, PropActionKind>::iterator I;
18544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    I = ActionOnProp.find(props[0].PropD->getIdentifier());
18644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    if (I == ActionOnProp.end())
18744679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return;
18844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
18944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    doPropAction(I->second, props, atLoc, false);
19044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  }
19144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
19244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  void rewriteProperty(PropsTy &props, SourceLocation atLoc) {
19314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
19414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
19514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (propAttrs & (ObjCPropertyDecl::OBJC_PR_copy |
19614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                     ObjCPropertyDecl::OBJC_PR_unsafe_unretained |
19714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                     ObjCPropertyDecl::OBJC_PR_strong |
19814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                     ObjCPropertyDecl::OBJC_PR_weak))
19914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return;
20014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
20114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (propAttrs & ObjCPropertyDecl::OBJC_PR_retain) {
20201b2b9bb154d69cc695717876e903329f6f0973cArgyrios Kyrtzidis      if (propAttrs & ObjCPropertyDecl::OBJC_PR_readonly)
20344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis        return doPropAction(PropAction_RetainToStrong, props, atLoc);
20401b2b9bb154d69cc695717876e903329f6f0973cArgyrios Kyrtzidis      else
20544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis        // strong is the default.
20644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis        return doPropAction(PropAction_RetainRemoved, props, atLoc);
2077196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
20814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
209b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    bool HasIvarAssignedAPlusOneObject = hasIvarAssignedAPlusOneObject(props);
210b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
21118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    if (propAttrs & ObjCPropertyDecl::OBJC_PR_assign) {
212b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      if (HasIvarAssignedAPlusOneObject ||
213b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis          (Pass.isGCMigration() && !hasGCWeak(props, atLoc))) {
214b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        return doPropAction(PropAction_AssignRemoved, props, atLoc);
21518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      }
21644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return doPropAction(PropAction_AssignRewritten, props, atLoc);
21718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
21818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
219b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (HasIvarAssignedAPlusOneObject ||
220b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        (Pass.isGCMigration() && !hasGCWeak(props, atLoc)))
221af9b5e9f3eede62347835d8dedd44df86cbcc308Argyrios Kyrtzidis      return; // 'strong' by default.
22214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
22344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    return doPropAction(PropAction_MaybeAddWeakOrUnsafe, props, atLoc);
2247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
2257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
226b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  void removeAssignForDefaultStrong(PropsTy &props,
227b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                    SourceLocation atLoc) const {
228b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    removeAttribute("retain", atLoc);
229b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (!removeAttribute("assign", atLoc))
230b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return;
231b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
232b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
233b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      if (I->ImplD)
234b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
235b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                I->ImplD->getLocation());
236b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    }
237b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  }
238b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
23914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  void rewriteAssign(PropsTy &props, SourceLocation atLoc) const {
240b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
241b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                  /*AllowOnUnknownClass=*/Pass.isGCMigration());
24214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
24314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    bool rewroteAttr = rewriteAttribute("assign",
24414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                                     canUseWeak ? "weak" : "unsafe_unretained",
24514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                                         atLoc);
24614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (!rewroteAttr)
24714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      canUseWeak = false;
2487196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
24914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
25014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (isUserDeclared(I->IvarD))
25114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        Pass.TA.insert(I->IvarD->getLocation(),
25214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                       canUseWeak ? "__weak " : "__unsafe_unretained ");
25314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (I->ImplD)
25414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
25514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                                I->ImplD->getLocation());
25614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    }
2577196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
2587196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
25914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
26014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                                          SourceLocation atLoc) const {
26114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
26214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
263b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
264b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                  /*AllowOnUnknownClass=*/Pass.isGCMigration());
26518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    if (!(propAttrs & ObjCPropertyDecl::OBJC_PR_readonly) ||
26618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        !hasAllIvarsBacked(props)) {
26718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained",
26818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis                                    atLoc);
26918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (!addedAttr)
27018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        canUseWeak = false;
27118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
27214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
27314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
27414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (isUserDeclared(I->IvarD))
27514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        Pass.TA.insert(I->IvarD->getLocation(),
27614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                       canUseWeak ? "__weak " : "__unsafe_unretained ");
27714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (I->ImplD) {
278b8b0313e84700b5c6d597b3be4de41c97b7550f1Argyrios Kyrtzidis        Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
27914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                                I->ImplD->getLocation());
28014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        Pass.TA.clearDiagnostic(
28114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                           diag::err_arc_objc_property_default_assign_on_object,
28214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                           I->ImplD->getLocation());
2837196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
2847196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
2857196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
2867196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
28718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  void maybeAddStrongAttr(PropsTy &props, SourceLocation atLoc) const {
28818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
28918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
290ae7c25dab5ed7c8fc05462c8daf48e7d0945d364Argyrios Kyrtzidis    if (!(propAttrs & ObjCPropertyDecl::OBJC_PR_readonly))
291ae7c25dab5ed7c8fc05462c8daf48e7d0945d364Argyrios Kyrtzidis      return; // 'strong' by default.
292ae7c25dab5ed7c8fc05462c8daf48e7d0945d364Argyrios Kyrtzidis
293ae7c25dab5ed7c8fc05462c8daf48e7d0945d364Argyrios Kyrtzidis    if (!hasAllIvarsBacked(props)) {
29418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      addAttribute("strong", atLoc);
29518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
29618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
29718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
29818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (I->ImplD) {
29918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
30018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis                                I->ImplD->getLocation());
30118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        Pass.TA.clearDiagnostic(
30218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis                           diag::err_arc_objc_property_default_assign_on_object,
30318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis                           I->ImplD->getLocation());
30418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      }
30518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
30618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  }
30718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
30801b2b9bb154d69cc695717876e903329f6f0973cArgyrios Kyrtzidis  bool removeAttribute(StringRef fromAttr, SourceLocation atLoc) const {
30901b2b9bb154d69cc695717876e903329f6f0973cArgyrios Kyrtzidis    return rewriteAttribute(fromAttr, StringRef(), atLoc);
31001b2b9bb154d69cc695717876e903329f6f0973cArgyrios Kyrtzidis  }
31101b2b9bb154d69cc695717876e903329f6f0973cArgyrios Kyrtzidis
3125f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  bool rewriteAttribute(StringRef fromAttr, StringRef toAttr,
31314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                        SourceLocation atLoc) const {
314b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return MigrateCtx.rewritePropertyAttribute(fromAttr, toAttr, atLoc);
3157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
3167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3175f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  bool addAttribute(StringRef attr, SourceLocation atLoc) const {
31814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (atLoc.isMacroID())
31914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return false;
32014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
3217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    SourceManager &SM = Pass.Ctx.getSourceManager();
3227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    // Break down the source location.
3247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
3257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    // Try to load the file buffer.
3277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    bool invalidTemp = false;
3285f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
3297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (invalidTemp)
33014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return false;
3317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    const char *tokenBegin = file.data() + locInfo.second;
3337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3347196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    // Lex from the start of the given location.
3357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
3367196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                Pass.Ctx.getLangOptions(),
3377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                file.begin(), tokenBegin, file.end());
3387196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    Token tok;
3397196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    lexer.LexFromRawLexer(tok);
34014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (tok.isNot(tok::at)) return false;
3417196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    lexer.LexFromRawLexer(tok);
34214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (tok.isNot(tok::raw_identifier)) return false;
3435f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    if (StringRef(tok.getRawIdentifierData(), tok.getLength())
3447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          != "property")
34514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return false;
3467196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    lexer.LexFromRawLexer(tok);
3477196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
34814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (tok.isNot(tok::l_paren)) {
34914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      Pass.TA.insert(tok.getLocation(), std::string("(") + attr.str() + ") ");
35014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return true;
35114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    }
35214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
3537196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    lexer.LexFromRawLexer(tok);
3547196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (tok.is(tok::r_paren)) {
35514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      Pass.TA.insert(tok.getLocation(), attr);
35614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return true;
35714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    }
35814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
35914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (tok.isNot(tok::raw_identifier)) return false;
36014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
36114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    Pass.TA.insert(tok.getLocation(), std::string(attr) + ", ");
36214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return true;
36314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
36414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
36518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  class PlusOneAssign : public RecursiveASTVisitor<PlusOneAssign> {
36618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    ObjCIvarDecl *Ivar;
36718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  public:
36818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    PlusOneAssign(ObjCIvarDecl *D) : Ivar(D) {}
36918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
37018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    bool VisitBinAssign(BinaryOperator *E) {
37118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      Expr *lhs = E->getLHS()->IgnoreParenImpCasts();
37218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(lhs)) {
37318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        if (RE->getDecl() != Ivar)
37418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis          return true;
37518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
37694a9016a6b92cfebdb0b7d4dcad930248f1f301aArgyrios Kyrtzidis      if (ObjCMessageExpr *
37794a9016a6b92cfebdb0b7d4dcad930248f1f301aArgyrios Kyrtzidis            ME = dyn_cast<ObjCMessageExpr>(E->getRHS()->IgnoreParenCasts()))
37894a9016a6b92cfebdb0b7d4dcad930248f1f301aArgyrios Kyrtzidis        if (ME->getMethodFamily() == OMF_retain)
37994a9016a6b92cfebdb0b7d4dcad930248f1f301aArgyrios Kyrtzidis          return false;
38094a9016a6b92cfebdb0b7d4dcad930248f1f301aArgyrios Kyrtzidis
38118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(E->getRHS());
38218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      while (implCE && implCE->getCastKind() ==  CK_BitCast)
38318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        implCE = dyn_cast<ImplicitCastExpr>(implCE->getSubExpr());
38418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
38533e56f3273457bfa22c7c50bc46cf5a18216863dJohn McCall      if (implCE && implCE->getCastKind() == CK_ARCConsumeObject)
38618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        return false;
38718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      }
38818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
38918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      return true;
39018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
39118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  };
39218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
39318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  bool hasIvarAssignedAPlusOneObject(PropsTy &props) const {
39418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
39518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      PlusOneAssign oneAssign(I->IvarD);
39618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      bool notFound = oneAssign.TraverseDecl(CurImplD);
39718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (!notFound)
39818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        return true;
39918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
40018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
40118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    return false;
40218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  }
40318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
404bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis  bool hasIvarWithExplicitARCOwnership(PropsTy &props) const {
405bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis    if (Pass.isGCMigration())
406bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis      return false;
407bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis
40814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
40914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (isUserDeclared(I->IvarD)) {
41014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        if (isa<AttributedType>(I->IvarD->getType()))
41114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          return true;
41214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        if (I->IvarD->getType().getLocalQualifiers().getObjCLifetime()
41314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis              != Qualifiers::OCL_Strong)
41414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          return true;
4157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
4167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
4177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
41814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return false;
41914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
42014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
42118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  bool hasAllIvarsBacked(PropsTy &props) const {
42214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
42318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (!isUserDeclared(I->IvarD))
42414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        return false;
42514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
42614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return true;
42714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
42814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
429b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  // \brief Returns true if all declarations in the @property have GC __weak.
430b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  bool hasGCWeak(PropsTy &props, SourceLocation atLoc) const {
431b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (!Pass.isGCMigration())
432b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return false;
433b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (props.empty())
434b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return false;
435b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return MigrateCtx.AtPropsWeak.count(atLoc.getRawEncoding());
436b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  }
437b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
43814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  bool isUserDeclared(ObjCIvarDecl *ivarD) const {
43914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return ivarD && !ivarD->getSynthesize();
44014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
44114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
44214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  QualType getPropertyType(PropsTy &props) const {
44314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    assert(!props.empty());
4441d5fb8f6e85a5c9c7b9b611be655454159c92f12Argyrios Kyrtzidis    QualType ty = props[0].PropD->getType().getUnqualifiedType();
44514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
44614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#ifndef NDEBUG
44714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
4481d5fb8f6e85a5c9c7b9b611be655454159c92f12Argyrios Kyrtzidis      assert(ty == I->PropD->getType().getUnqualifiedType());
44914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#endif
45014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
45114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return ty;
45214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
45314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
45414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  ObjCPropertyDecl::PropertyAttributeKind
45514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  getPropertyAttrs(PropsTy &props) const {
45614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    assert(!props.empty());
45714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    ObjCPropertyDecl::PropertyAttributeKind
45814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      attrs = props[0].PropD->getPropertyAttributesAsWritten();
45914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
46014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#ifndef NDEBUG
46114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
46214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      assert(attrs == I->PropD->getPropertyAttributesAsWritten());
46314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#endif
46414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
46514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return attrs;
4667196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
4677196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis};
4687196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
4697196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} // anonymous namespace
4707196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
471b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidisvoid PropertyRewriteTraverser::traverseObjCImplementation(
472b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis                                           ObjCImplementationContext &ImplCtx) {
473b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  PropertiesRewriter(ImplCtx.getMigrationContext())
474b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis                                  .doTransform(ImplCtx.getImplementationDecl());
4757196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis}
476