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,
5386f960143c73f573919255c4465de71f85793c2eFariborz Jahanian    PropAction_RetainReplacedWithStrong,
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
760fd4a6869e9a12999af24b8df7a0275a0e6c18beArgyrios Kyrtzidis  static void collectProperties(ObjCContainerDecl *D, AtPropDeclsTy &AtProps,
770fd4a6869e9a12999af24b8df7a0275a0e6c18beArgyrios Kyrtzidis                                AtPropDeclsTy *PrevAtProps = 0) {
787196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    for (ObjCInterfaceDecl::prop_iterator
7944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis           propI = D->prop_begin(),
8044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis           propE = D->prop_end(); propI != propE; ++propI) {
8114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (propI->getAtLoc().isInvalid())
8214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
830fd4a6869e9a12999af24b8df7a0275a0e6c18beArgyrios Kyrtzidis      unsigned RawLoc = propI->getAtLoc().getRawEncoding();
840fd4a6869e9a12999af24b8df7a0275a0e6c18beArgyrios Kyrtzidis      if (PrevAtProps)
850fd4a6869e9a12999af24b8df7a0275a0e6c18beArgyrios Kyrtzidis        if (PrevAtProps->find(RawLoc) != PrevAtProps->end())
860fd4a6869e9a12999af24b8df7a0275a0e6c18beArgyrios Kyrtzidis          continue;
870fd4a6869e9a12999af24b8df7a0275a0e6c18beArgyrios Kyrtzidis      PropsTy &props = AtProps[RawLoc];
88581deb3da481053c4993c7600f97acf7768caac5David Blaikie      props.push_back(*propI);
897196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
9044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  }
9144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
9244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  void doTransform(ObjCImplementationDecl *D) {
9344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    CurImplD = D;
9444679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    ObjCInterfaceDecl *iface = D->getClassInterface();
9544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    if (!iface)
9644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return;
9744679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
9844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    collectProperties(iface, AtProps);
997196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
1007196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl>
1017196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        prop_impl_iterator;
1027196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    for (prop_impl_iterator
1037196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis           I = prop_impl_iterator(D->decls_begin()),
1047196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis           E = prop_impl_iterator(D->decls_end()); I != E; ++I) {
105581deb3da481053c4993c7600f97acf7768caac5David Blaikie      ObjCPropertyImplDecl *implD = *I;
10614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (implD->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
10714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
10814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      ObjCPropertyDecl *propD = implD->getPropertyDecl();
10914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (!propD || propD->isInvalidDecl())
11014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
11114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      ObjCIvarDecl *ivarD = implD->getPropertyIvarDecl();
11214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (!ivarD || ivarD->isInvalidDecl())
11314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
11414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      unsigned rawAtLoc = propD->getAtLoc().getRawEncoding();
11514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      AtPropDeclsTy::iterator findAtLoc = AtProps.find(rawAtLoc);
11614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (findAtLoc == AtProps.end())
11714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
11814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
11914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      PropsTy &props = findAtLoc->second;
12014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
12114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        if (I->PropD == propD) {
12214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          I->IvarD = ivarD;
12314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          I->ImplD = implD;
12414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          break;
12514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        }
12614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      }
1277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
1287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
12914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (AtPropDeclsTy::iterator
13014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis           I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
1317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
1327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      PropsTy &props = I->second;
1331d5fb8f6e85a5c9c7b9b611be655454159c92f12Argyrios Kyrtzidis      if (!getPropertyType(props)->isObjCRetainableType())
13414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
135bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis      if (hasIvarWithExplicitARCOwnership(props))
13614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
13714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
13814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      Transaction Trans(Pass.TA);
13914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      rewriteProperty(props, atLoc);
1407196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
14144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
14244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    AtPropDeclsTy AtExtProps;
14344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    // Look through extensions.
14444679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    for (ObjCCategoryDecl *Cat = iface->getCategoryList();
14544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis           Cat; Cat = Cat->getNextClassCategory())
14644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      if (Cat->IsClassExtension())
1470fd4a6869e9a12999af24b8df7a0275a0e6c18beArgyrios Kyrtzidis        collectProperties(Cat, AtExtProps, &AtProps);
14844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
14944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    for (AtPropDeclsTy::iterator
15044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis           I = AtExtProps.begin(), E = AtExtProps.end(); I != E; ++I) {
15144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
15244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      PropsTy &props = I->second;
15344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      Transaction Trans(Pass.TA);
15444679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      doActionForExtensionProp(props, atLoc);
15544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    }
1567196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
1577196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
15814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidisprivate:
15944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  void doPropAction(PropActionKind kind,
16044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis                    PropsTy &props, SourceLocation atLoc,
16144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis                    bool markAction = true) {
16244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    if (markAction)
16344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
16444679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis        ActionOnProp[I->PropD->getIdentifier()] = kind;
16544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
16644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    switch (kind) {
16744679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    case PropAction_None:
16844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return;
16986f960143c73f573919255c4465de71f85793c2eFariborz Jahanian    case PropAction_RetainReplacedWithStrong: {
17086f960143c73f573919255c4465de71f85793c2eFariborz Jahanian      StringRef toAttr = "strong";
17186f960143c73f573919255c4465de71f85793c2eFariborz Jahanian      MigrateCtx.rewritePropertyAttribute("retain", toAttr, atLoc);
17244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return;
17386f960143c73f573919255c4465de71f85793c2eFariborz Jahanian    }
174b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    case PropAction_AssignRemoved:
175b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return removeAssignForDefaultStrong(props, atLoc);
17644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    case PropAction_AssignRewritten:
17744679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return rewriteAssign(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) {
2028b08eb34565a644d3345b1bfee3542a8f4a6c300Argyrios Kyrtzidis      // strong is the default.
20386f960143c73f573919255c4465de71f85793c2eFariborz Jahanian      return doPropAction(PropAction_RetainReplacedWithStrong, props, atLoc);
2047196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
20514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
206b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    bool HasIvarAssignedAPlusOneObject = hasIvarAssignedAPlusOneObject(props);
207b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
20818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    if (propAttrs & ObjCPropertyDecl::OBJC_PR_assign) {
2092f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian      if (HasIvarAssignedAPlusOneObject)
210b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        return doPropAction(PropAction_AssignRemoved, props, atLoc);
21144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return doPropAction(PropAction_AssignRewritten, props, atLoc);
21218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
21318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
214b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (HasIvarAssignedAPlusOneObject ||
215b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        (Pass.isGCMigration() && !hasGCWeak(props, atLoc)))
216af9b5e9f3eede62347835d8dedd44df86cbcc308Argyrios Kyrtzidis      return; // 'strong' by default.
21714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
21844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    return doPropAction(PropAction_MaybeAddWeakOrUnsafe, props, atLoc);
2197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
2207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
221b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  void removeAssignForDefaultStrong(PropsTy &props,
222b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                    SourceLocation atLoc) const {
223b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    removeAttribute("retain", atLoc);
224b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (!removeAttribute("assign", atLoc))
225b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return;
226b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
227b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
228b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      if (I->ImplD)
229b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
230b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                I->ImplD->getLocation());
231b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    }
232b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  }
233b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
23414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  void rewriteAssign(PropsTy &props, SourceLocation atLoc) const {
235b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
236b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                  /*AllowOnUnknownClass=*/Pass.isGCMigration());
2372f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian    const char *toWhich =
2382f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian      (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "strong" :
2392f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian      (canUseWeak ? "weak" : "unsafe_unretained");
24014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
2412f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian    bool rewroteAttr = rewriteAttribute("assign", toWhich, atLoc);
24214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (!rewroteAttr)
24314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      canUseWeak = false;
2447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
24514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
2466d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis      if (isUserDeclared(I->IvarD)) {
2476d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis        if (I->IvarD &&
2482f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian            I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak) {
2492f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian          const char *toWhich =
2502f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian            (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "__strong " :
2512f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian              (canUseWeak ? "__weak " : "__unsafe_unretained ");
2522f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian          Pass.TA.insert(I->IvarD->getLocation(), toWhich);
2532f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian        }
2546d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis      }
25514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (I->ImplD)
25614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
25714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                                I->ImplD->getLocation());
25814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    }
2597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
2607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
26114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
26214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                                          SourceLocation atLoc) const {
263b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
264b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                  /*AllowOnUnknownClass=*/Pass.isGCMigration());
2658b08eb34565a644d3345b1bfee3542a8f4a6c300Argyrios Kyrtzidis
2668b08eb34565a644d3345b1bfee3542a8f4a6c300Argyrios Kyrtzidis    bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained",
2678b08eb34565a644d3345b1bfee3542a8f4a6c300Argyrios Kyrtzidis                                  atLoc);
2688b08eb34565a644d3345b1bfee3542a8f4a6c300Argyrios Kyrtzidis    if (!addedAttr)
2698b08eb34565a644d3345b1bfee3542a8f4a6c300Argyrios Kyrtzidis      canUseWeak = false;
27014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
27114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
2726d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis      if (isUserDeclared(I->IvarD)) {
2736d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis        if (I->IvarD &&
2746d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis            I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak)
2756d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis          Pass.TA.insert(I->IvarD->getLocation(),
2766d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis                         canUseWeak ? "__weak " : "__unsafe_unretained ");
2776d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis      }
27814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (I->ImplD) {
279b8b0313e84700b5c6d597b3be4de41c97b7550f1Argyrios Kyrtzidis        Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
28014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                                I->ImplD->getLocation());
28114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        Pass.TA.clearDiagnostic(
28214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                           diag::err_arc_objc_property_default_assign_on_object,
28314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                           I->ImplD->getLocation());
2847196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
2857196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
2867196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
2877196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
28801b2b9bb154d69cc695717876e903329f6f0973cArgyrios Kyrtzidis  bool removeAttribute(StringRef fromAttr, SourceLocation atLoc) const {
2896da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis    return MigrateCtx.removePropertyAttribute(fromAttr, atLoc);
29001b2b9bb154d69cc695717876e903329f6f0973cArgyrios Kyrtzidis  }
29101b2b9bb154d69cc695717876e903329f6f0973cArgyrios Kyrtzidis
2925f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  bool rewriteAttribute(StringRef fromAttr, StringRef toAttr,
29314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                        SourceLocation atLoc) const {
294b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return MigrateCtx.rewritePropertyAttribute(fromAttr, toAttr, atLoc);
2957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
2967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2975f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  bool addAttribute(StringRef attr, SourceLocation atLoc) const {
2986da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis    return MigrateCtx.addPropertyAttribute(attr, atLoc);
29914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
30014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
30118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  class PlusOneAssign : public RecursiveASTVisitor<PlusOneAssign> {
30218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    ObjCIvarDecl *Ivar;
30318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  public:
30418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    PlusOneAssign(ObjCIvarDecl *D) : Ivar(D) {}
30518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
30618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    bool VisitBinAssign(BinaryOperator *E) {
30718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      Expr *lhs = E->getLHS()->IgnoreParenImpCasts();
30818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(lhs)) {
30918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        if (RE->getDecl() != Ivar)
31018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis          return true;
31118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
3121b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis        if (isPlusOneAssign(E))
31394a9016a6b92cfebdb0b7d4dcad930248f1f301aArgyrios Kyrtzidis          return false;
31418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      }
31518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
31618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      return true;
31718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
31818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  };
31918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
32018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  bool hasIvarAssignedAPlusOneObject(PropsTy &props) const {
32118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
32218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      PlusOneAssign oneAssign(I->IvarD);
32318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      bool notFound = oneAssign.TraverseDecl(CurImplD);
32418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (!notFound)
32518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        return true;
32618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
32718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
32818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    return false;
32918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  }
33018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
331bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis  bool hasIvarWithExplicitARCOwnership(PropsTy &props) const {
332bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis    if (Pass.isGCMigration())
333bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis      return false;
334bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis
33514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
33614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (isUserDeclared(I->IvarD)) {
33714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        if (isa<AttributedType>(I->IvarD->getType()))
33814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          return true;
33914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        if (I->IvarD->getType().getLocalQualifiers().getObjCLifetime()
34014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis              != Qualifiers::OCL_Strong)
34114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          return true;
3427196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
3437196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
3447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
34514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return false;
34614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
34714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
34818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  bool hasAllIvarsBacked(PropsTy &props) const {
34914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
35018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (!isUserDeclared(I->IvarD))
35114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        return false;
35214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
35314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return true;
35414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
35514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
356b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  // \brief Returns true if all declarations in the @property have GC __weak.
357b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  bool hasGCWeak(PropsTy &props, SourceLocation atLoc) const {
358b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (!Pass.isGCMigration())
359b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return false;
360b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (props.empty())
361b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return false;
362b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return MigrateCtx.AtPropsWeak.count(atLoc.getRawEncoding());
363b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  }
364b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
36514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  bool isUserDeclared(ObjCIvarDecl *ivarD) const {
36614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return ivarD && !ivarD->getSynthesize();
36714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
36814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
36914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  QualType getPropertyType(PropsTy &props) const {
37014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    assert(!props.empty());
3711d5fb8f6e85a5c9c7b9b611be655454159c92f12Argyrios Kyrtzidis    QualType ty = props[0].PropD->getType().getUnqualifiedType();
37214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
37314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#ifndef NDEBUG
37414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
3751d5fb8f6e85a5c9c7b9b611be655454159c92f12Argyrios Kyrtzidis      assert(ty == I->PropD->getType().getUnqualifiedType());
37614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#endif
37714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
37814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return ty;
37914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
38014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
38114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  ObjCPropertyDecl::PropertyAttributeKind
38214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  getPropertyAttrs(PropsTy &props) const {
38314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    assert(!props.empty());
38414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    ObjCPropertyDecl::PropertyAttributeKind
38514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      attrs = props[0].PropD->getPropertyAttributesAsWritten();
38614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
38714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#ifndef NDEBUG
38814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
38914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      assert(attrs == I->PropD->getPropertyAttributesAsWritten());
39014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#endif
39114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
39214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return attrs;
3937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
3947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis};
3957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} // anonymous namespace
3977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
398b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidisvoid PropertyRewriteTraverser::traverseObjCImplementation(
399b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis                                           ObjCImplementationContext &ImplCtx) {
400b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  PropertiesRewriter(ImplCtx.getMigrationContext())
401b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis                                  .doTransform(ImplCtx.getImplementationDecl());
4027196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis}
403