TransProperties.cpp revision 6d7d16d45c1d601483e46a77bd2fa1d199219721
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_RetainRemoved,
54b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    PropAction_AssignRemoved,
5544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    PropAction_AssignRewritten,
5644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    PropAction_MaybeAddWeakOrUnsafe
5744679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  };
5814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  struct PropData {
607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    ObjCPropertyDecl *PropD;
617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    ObjCIvarDecl *IvarD;
6214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    ObjCPropertyImplDecl *ImplD;
6314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
6414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    PropData(ObjCPropertyDecl *propD) : PropD(propD), IvarD(0), ImplD(0) { }
657196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  };
667196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
675f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  typedef SmallVector<PropData, 2> PropsTy;
6814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  typedef std::map<unsigned, PropsTy> AtPropDeclsTy;
6914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  AtPropDeclsTy AtProps;
7044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  llvm::DenseMap<IdentifierInfo *, PropActionKind> ActionOnProp;
717196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
727196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidispublic:
73b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  explicit PropertiesRewriter(MigrationContext &MigrateCtx)
74b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    : MigrateCtx(MigrateCtx), Pass(MigrateCtx.Pass) { }
757196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
7644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  static void collectProperties(ObjCContainerDecl *D, AtPropDeclsTy &AtProps) {
777196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    for (ObjCInterfaceDecl::prop_iterator
7844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis           propI = D->prop_begin(),
7944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis           propE = D->prop_end(); propI != propE; ++propI) {
8014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (propI->getAtLoc().isInvalid())
8114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
8214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      PropsTy &props = AtProps[propI->getAtLoc().getRawEncoding()];
8314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      props.push_back(*propI);
847196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
8544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  }
8644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
8744679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  void doTransform(ObjCImplementationDecl *D) {
8844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    CurImplD = D;
8944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    ObjCInterfaceDecl *iface = D->getClassInterface();
9044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    if (!iface)
9144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return;
9244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
9344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    collectProperties(iface, AtProps);
947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl>
967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        prop_impl_iterator;
977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    for (prop_impl_iterator
987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis           I = prop_impl_iterator(D->decls_begin()),
997196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis           E = prop_impl_iterator(D->decls_end()); I != E; ++I) {
10014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      ObjCPropertyImplDecl *implD = *I;
10114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (implD->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
10214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
10314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      ObjCPropertyDecl *propD = implD->getPropertyDecl();
10414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (!propD || propD->isInvalidDecl())
10514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
10614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      ObjCIvarDecl *ivarD = implD->getPropertyIvarDecl();
10714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (!ivarD || ivarD->isInvalidDecl())
10814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
10914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      unsigned rawAtLoc = propD->getAtLoc().getRawEncoding();
11014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      AtPropDeclsTy::iterator findAtLoc = AtProps.find(rawAtLoc);
11114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (findAtLoc == AtProps.end())
11214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
11314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
11414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      PropsTy &props = findAtLoc->second;
11514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
11614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        if (I->PropD == propD) {
11714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          I->IvarD = ivarD;
11814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          I->ImplD = implD;
11914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          break;
12014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        }
12114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      }
1227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
1237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
12414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (AtPropDeclsTy::iterator
12514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis           I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
1267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
1277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      PropsTy &props = I->second;
1281d5fb8f6e85a5c9c7b9b611be655454159c92f12Argyrios Kyrtzidis      if (!getPropertyType(props)->isObjCRetainableType())
12914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
130bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis      if (hasIvarWithExplicitARCOwnership(props))
13114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
13214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
13314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      Transaction Trans(Pass.TA);
13414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      rewriteProperty(props, atLoc);
1357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
13644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
13744679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    AtPropDeclsTy AtExtProps;
13844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    // Look through extensions.
13944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    for (ObjCCategoryDecl *Cat = iface->getCategoryList();
14044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis           Cat; Cat = Cat->getNextClassCategory())
14144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      if (Cat->IsClassExtension())
14244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis        collectProperties(Cat, AtExtProps);
14344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
14444679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    for (AtPropDeclsTy::iterator
14544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis           I = AtExtProps.begin(), E = AtExtProps.end(); I != E; ++I) {
14644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
14744679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      PropsTy &props = I->second;
14844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      Transaction Trans(Pass.TA);
14944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      doActionForExtensionProp(props, atLoc);
15044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    }
1517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
1527196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
15314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidisprivate:
15444679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  void doPropAction(PropActionKind kind,
15544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis                    PropsTy &props, SourceLocation atLoc,
15644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis                    bool markAction = true) {
15744679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    if (markAction)
15844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
15944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis        ActionOnProp[I->PropD->getIdentifier()] = kind;
16044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
16144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    switch (kind) {
16244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    case PropAction_None:
16344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return;
16444679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    case PropAction_RetainRemoved:
16544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      removeAttribute("retain", atLoc);
16644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return;
167b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    case PropAction_AssignRemoved:
168b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return removeAssignForDefaultStrong(props, atLoc);
16944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    case PropAction_AssignRewritten:
17044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return rewriteAssign(props, atLoc);
17144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    case PropAction_MaybeAddWeakOrUnsafe:
17244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
17344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    }
17444679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  }
17544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
17644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  void doActionForExtensionProp(PropsTy &props, SourceLocation atLoc) {
17744679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    llvm::DenseMap<IdentifierInfo *, PropActionKind>::iterator I;
17844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    I = ActionOnProp.find(props[0].PropD->getIdentifier());
17944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    if (I == ActionOnProp.end())
18044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return;
18144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
18244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    doPropAction(I->second, props, atLoc, false);
18344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  }
18444679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
18544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  void rewriteProperty(PropsTy &props, SourceLocation atLoc) {
18614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
18714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
18814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (propAttrs & (ObjCPropertyDecl::OBJC_PR_copy |
18914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                     ObjCPropertyDecl::OBJC_PR_unsafe_unretained |
19014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                     ObjCPropertyDecl::OBJC_PR_strong |
19114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                     ObjCPropertyDecl::OBJC_PR_weak))
19214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return;
19314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
19414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (propAttrs & ObjCPropertyDecl::OBJC_PR_retain) {
1958b08eb34565a644d3345b1bfee3542a8f4a6c300Argyrios Kyrtzidis      // strong is the default.
1968b08eb34565a644d3345b1bfee3542a8f4a6c300Argyrios Kyrtzidis      return doPropAction(PropAction_RetainRemoved, props, atLoc);
1977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
19814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
199b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    bool HasIvarAssignedAPlusOneObject = hasIvarAssignedAPlusOneObject(props);
200b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
20118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    if (propAttrs & ObjCPropertyDecl::OBJC_PR_assign) {
202b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      if (HasIvarAssignedAPlusOneObject ||
203b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis          (Pass.isGCMigration() && !hasGCWeak(props, atLoc))) {
204b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        return doPropAction(PropAction_AssignRemoved, props, atLoc);
20518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      }
20644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return doPropAction(PropAction_AssignRewritten, props, atLoc);
20718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
20818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
209b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (HasIvarAssignedAPlusOneObject ||
210b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        (Pass.isGCMigration() && !hasGCWeak(props, atLoc)))
211af9b5e9f3eede62347835d8dedd44df86cbcc308Argyrios Kyrtzidis      return; // 'strong' by default.
21214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
21344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    return doPropAction(PropAction_MaybeAddWeakOrUnsafe, props, atLoc);
2147196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
2157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
216b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  void removeAssignForDefaultStrong(PropsTy &props,
217b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                    SourceLocation atLoc) const {
218b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    removeAttribute("retain", atLoc);
219b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (!removeAttribute("assign", atLoc))
220b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return;
221b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
222b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
223b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      if (I->ImplD)
224b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
225b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                I->ImplD->getLocation());
226b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    }
227b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  }
228b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
22914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  void rewriteAssign(PropsTy &props, SourceLocation atLoc) const {
230b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
231b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                  /*AllowOnUnknownClass=*/Pass.isGCMigration());
23214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
23314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    bool rewroteAttr = rewriteAttribute("assign",
23414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                                     canUseWeak ? "weak" : "unsafe_unretained",
23514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                                         atLoc);
23614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (!rewroteAttr)
23714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      canUseWeak = false;
2387196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
23914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
2406d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis      if (isUserDeclared(I->IvarD)) {
2416d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis        if (I->IvarD &&
2426d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis            I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak)
2436d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis          Pass.TA.insert(I->IvarD->getLocation(),
2446d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis                         canUseWeak ? "__weak " : "__unsafe_unretained ");
2456d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis      }
24614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (I->ImplD)
24714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
24814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                                I->ImplD->getLocation());
24914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    }
2507196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
2517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
25214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
25314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                                          SourceLocation atLoc) const {
254b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
255b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                  /*AllowOnUnknownClass=*/Pass.isGCMigration());
2568b08eb34565a644d3345b1bfee3542a8f4a6c300Argyrios Kyrtzidis
2578b08eb34565a644d3345b1bfee3542a8f4a6c300Argyrios Kyrtzidis    bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained",
2588b08eb34565a644d3345b1bfee3542a8f4a6c300Argyrios Kyrtzidis                                  atLoc);
2598b08eb34565a644d3345b1bfee3542a8f4a6c300Argyrios Kyrtzidis    if (!addedAttr)
2608b08eb34565a644d3345b1bfee3542a8f4a6c300Argyrios Kyrtzidis      canUseWeak = false;
26114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
26214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
2636d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis      if (isUserDeclared(I->IvarD)) {
2646d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis        if (I->IvarD &&
2656d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis            I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak)
2666d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis          Pass.TA.insert(I->IvarD->getLocation(),
2676d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis                         canUseWeak ? "__weak " : "__unsafe_unretained ");
2686d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis      }
26914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (I->ImplD) {
270b8b0313e84700b5c6d597b3be4de41c97b7550f1Argyrios Kyrtzidis        Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
27114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                                I->ImplD->getLocation());
27214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        Pass.TA.clearDiagnostic(
27314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                           diag::err_arc_objc_property_default_assign_on_object,
27414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                           I->ImplD->getLocation());
2757196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
2767196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
2777196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
2787196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
27901b2b9bb154d69cc695717876e903329f6f0973cArgyrios Kyrtzidis  bool removeAttribute(StringRef fromAttr, SourceLocation atLoc) const {
28001b2b9bb154d69cc695717876e903329f6f0973cArgyrios Kyrtzidis    return rewriteAttribute(fromAttr, StringRef(), atLoc);
28101b2b9bb154d69cc695717876e903329f6f0973cArgyrios Kyrtzidis  }
28201b2b9bb154d69cc695717876e903329f6f0973cArgyrios Kyrtzidis
2835f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  bool rewriteAttribute(StringRef fromAttr, StringRef toAttr,
28414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                        SourceLocation atLoc) const {
285b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return MigrateCtx.rewritePropertyAttribute(fromAttr, toAttr, atLoc);
2867196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
2877196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2885f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  bool addAttribute(StringRef attr, SourceLocation atLoc) const {
28914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (atLoc.isMacroID())
29014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return false;
29114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
2927196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    SourceManager &SM = Pass.Ctx.getSourceManager();
2937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    // Break down the source location.
2957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
2967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    // Try to load the file buffer.
2987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    bool invalidTemp = false;
2995f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
3007196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (invalidTemp)
30114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return false;
3027196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3037196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    const char *tokenBegin = file.data() + locInfo.second;
3047196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3057196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    // Lex from the start of the given location.
3067196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
3077196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                Pass.Ctx.getLangOptions(),
3087196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                file.begin(), tokenBegin, file.end());
3097196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    Token tok;
3107196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    lexer.LexFromRawLexer(tok);
31114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (tok.isNot(tok::at)) return false;
3127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    lexer.LexFromRawLexer(tok);
31314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (tok.isNot(tok::raw_identifier)) return false;
3145f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    if (StringRef(tok.getRawIdentifierData(), tok.getLength())
3157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          != "property")
31614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return false;
3177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    lexer.LexFromRawLexer(tok);
3187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
31914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (tok.isNot(tok::l_paren)) {
32014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      Pass.TA.insert(tok.getLocation(), std::string("(") + attr.str() + ") ");
32114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return true;
32214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    }
32314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
3247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    lexer.LexFromRawLexer(tok);
3257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (tok.is(tok::r_paren)) {
32614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      Pass.TA.insert(tok.getLocation(), attr);
32714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return true;
32814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    }
32914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
33014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (tok.isNot(tok::raw_identifier)) return false;
33114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
33214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    Pass.TA.insert(tok.getLocation(), std::string(attr) + ", ");
33314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return true;
33414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
33514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
33618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  class PlusOneAssign : public RecursiveASTVisitor<PlusOneAssign> {
33718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    ObjCIvarDecl *Ivar;
33818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  public:
33918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    PlusOneAssign(ObjCIvarDecl *D) : Ivar(D) {}
34018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
34118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    bool VisitBinAssign(BinaryOperator *E) {
34218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      Expr *lhs = E->getLHS()->IgnoreParenImpCasts();
34318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(lhs)) {
34418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        if (RE->getDecl() != Ivar)
34518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis          return true;
34618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
34794a9016a6b92cfebdb0b7d4dcad930248f1f301aArgyrios Kyrtzidis      if (ObjCMessageExpr *
34894a9016a6b92cfebdb0b7d4dcad930248f1f301aArgyrios Kyrtzidis            ME = dyn_cast<ObjCMessageExpr>(E->getRHS()->IgnoreParenCasts()))
34994a9016a6b92cfebdb0b7d4dcad930248f1f301aArgyrios Kyrtzidis        if (ME->getMethodFamily() == OMF_retain)
35094a9016a6b92cfebdb0b7d4dcad930248f1f301aArgyrios Kyrtzidis          return false;
35194a9016a6b92cfebdb0b7d4dcad930248f1f301aArgyrios Kyrtzidis
35218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(E->getRHS());
35318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      while (implCE && implCE->getCastKind() ==  CK_BitCast)
35418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        implCE = dyn_cast<ImplicitCastExpr>(implCE->getSubExpr());
35518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
35633e56f3273457bfa22c7c50bc46cf5a18216863dJohn McCall      if (implCE && implCE->getCastKind() == CK_ARCConsumeObject)
35718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        return false;
35818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      }
35918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
36018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      return true;
36118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
36218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  };
36318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
36418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  bool hasIvarAssignedAPlusOneObject(PropsTy &props) const {
36518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
36618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      PlusOneAssign oneAssign(I->IvarD);
36718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      bool notFound = oneAssign.TraverseDecl(CurImplD);
36818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (!notFound)
36918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        return true;
37018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
37118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
37218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    return false;
37318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  }
37418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
375bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis  bool hasIvarWithExplicitARCOwnership(PropsTy &props) const {
376bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis    if (Pass.isGCMigration())
377bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis      return false;
378bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis
37914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
38014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (isUserDeclared(I->IvarD)) {
38114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        if (isa<AttributedType>(I->IvarD->getType()))
38214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          return true;
38314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        if (I->IvarD->getType().getLocalQualifiers().getObjCLifetime()
38414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis              != Qualifiers::OCL_Strong)
38514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          return true;
3867196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
3877196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
3887196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
38914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return false;
39014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
39114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
39218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  bool hasAllIvarsBacked(PropsTy &props) const {
39314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
39418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (!isUserDeclared(I->IvarD))
39514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        return false;
39614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
39714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return true;
39814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
39914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
400b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  // \brief Returns true if all declarations in the @property have GC __weak.
401b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  bool hasGCWeak(PropsTy &props, SourceLocation atLoc) const {
402b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (!Pass.isGCMigration())
403b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return false;
404b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (props.empty())
405b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return false;
406b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return MigrateCtx.AtPropsWeak.count(atLoc.getRawEncoding());
407b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  }
408b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
40914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  bool isUserDeclared(ObjCIvarDecl *ivarD) const {
41014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return ivarD && !ivarD->getSynthesize();
41114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
41214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
41314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  QualType getPropertyType(PropsTy &props) const {
41414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    assert(!props.empty());
4151d5fb8f6e85a5c9c7b9b611be655454159c92f12Argyrios Kyrtzidis    QualType ty = props[0].PropD->getType().getUnqualifiedType();
41614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
41714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#ifndef NDEBUG
41814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
4191d5fb8f6e85a5c9c7b9b611be655454159c92f12Argyrios Kyrtzidis      assert(ty == I->PropD->getType().getUnqualifiedType());
42014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#endif
42114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
42214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return ty;
42314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
42414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
42514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  ObjCPropertyDecl::PropertyAttributeKind
42614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  getPropertyAttrs(PropsTy &props) const {
42714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    assert(!props.empty());
42814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    ObjCPropertyDecl::PropertyAttributeKind
42914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      attrs = props[0].PropD->getPropertyAttributesAsWritten();
43014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
43114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#ifndef NDEBUG
43214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
43314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      assert(attrs == I->PropD->getPropertyAttributesAsWritten());
43414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#endif
43514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
43614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return attrs;
4377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
4387196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis};
4397196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
4407196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} // anonymous namespace
4417196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
442b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidisvoid PropertyRewriteTraverser::traverseObjCImplementation(
443b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis                                           ObjCImplementationContext &ImplCtx) {
444b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  PropertiesRewriter(ImplCtx.getMigrationContext())
445b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis                                  .doTransform(ImplCtx.getImplementationDecl());
4467196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis}
447