1accaf19bc1129c0273ec50dba52318e60bc29103Benjamin Kramer//===--- TransProperties.cpp - Transformations 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/Basic/SourceManager.h"
367196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "clang/Lex/Lexer.h"
3755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Sema/SemaDiagnostic.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
646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    PropData(ObjCPropertyDecl *propD)
656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      : PropD(propD), IvarD(nullptr), ImplD(nullptr) {}
667196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  };
677196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
685f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  typedef SmallVector<PropData, 2> PropsTy;
6914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  typedef std::map<unsigned, PropsTy> AtPropDeclsTy;
7014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  AtPropDeclsTy AtProps;
7144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  llvm::DenseMap<IdentifierInfo *, PropActionKind> ActionOnProp;
727196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
737196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidispublic:
74b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  explicit PropertiesRewriter(MigrationContext &MigrateCtx)
75b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    : MigrateCtx(MigrateCtx), Pass(MigrateCtx.Pass) { }
767196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
770fd4a6869e9a12999af24b8df7a0275a0e6c18beArgyrios Kyrtzidis  static void collectProperties(ObjCContainerDecl *D, AtPropDeclsTy &AtProps,
786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                AtPropDeclsTy *PrevAtProps = nullptr) {
79651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (auto *Prop : D->properties()) {
80651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (Prop->getAtLoc().isInvalid())
8114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
82651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      unsigned RawLoc = Prop->getAtLoc().getRawEncoding();
830fd4a6869e9a12999af24b8df7a0275a0e6c18beArgyrios Kyrtzidis      if (PrevAtProps)
840fd4a6869e9a12999af24b8df7a0275a0e6c18beArgyrios Kyrtzidis        if (PrevAtProps->find(RawLoc) != PrevAtProps->end())
850fd4a6869e9a12999af24b8df7a0275a0e6c18beArgyrios Kyrtzidis          continue;
860fd4a6869e9a12999af24b8df7a0275a0e6c18beArgyrios Kyrtzidis      PropsTy &props = AtProps[RawLoc];
87651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      props.push_back(Prop);
887196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
8944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  }
9044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
9144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  void doTransform(ObjCImplementationDecl *D) {
9244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    CurImplD = D;
9344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    ObjCInterfaceDecl *iface = D->getClassInterface();
9444679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    if (!iface)
9544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return;
9644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
9744679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    collectProperties(iface, AtProps);
987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
997196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl>
1007196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        prop_impl_iterator;
1017196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    for (prop_impl_iterator
1027196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis           I = prop_impl_iterator(D->decls_begin()),
1037196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis           E = prop_impl_iterator(D->decls_end()); I != E; ++I) {
104581deb3da481053c4993c7600f97acf7768caac5David Blaikie      ObjCPropertyImplDecl *implD = *I;
10514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (implD->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
10614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
10714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      ObjCPropertyDecl *propD = implD->getPropertyDecl();
10814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (!propD || propD->isInvalidDecl())
10914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
11014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      ObjCIvarDecl *ivarD = implD->getPropertyIvarDecl();
11114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (!ivarD || ivarD->isInvalidDecl())
11214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
11314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      unsigned rawAtLoc = propD->getAtLoc().getRawEncoding();
11414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      AtPropDeclsTy::iterator findAtLoc = AtProps.find(rawAtLoc);
11514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (findAtLoc == AtProps.end())
11614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
11714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
11814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      PropsTy &props = findAtLoc->second;
11914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
12014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        if (I->PropD == propD) {
12114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          I->IvarD = ivarD;
12214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          I->ImplD = implD;
12314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          break;
12414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        }
12514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      }
1267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
1277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
12814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (AtPropDeclsTy::iterator
12914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis           I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
1307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
1317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      PropsTy &props = I->second;
1321d5fb8f6e85a5c9c7b9b611be655454159c92f12Argyrios Kyrtzidis      if (!getPropertyType(props)->isObjCRetainableType())
13314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
134bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis      if (hasIvarWithExplicitARCOwnership(props))
13514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
13614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
13714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      Transaction Trans(Pass.TA);
13814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      rewriteProperty(props, atLoc);
1397196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
14044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
14144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    AtPropDeclsTy AtExtProps;
14244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    // Look through extensions.
143651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (auto *Ext : iface->visible_extensions())
144651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      collectProperties(Ext, AtExtProps, &AtProps);
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;
16686f960143c73f573919255c4465de71f85793c2eFariborz Jahanian    case PropAction_RetainReplacedWithStrong: {
16786f960143c73f573919255c4465de71f85793c2eFariborz Jahanian      StringRef toAttr = "strong";
16886f960143c73f573919255c4465de71f85793c2eFariborz Jahanian      MigrateCtx.rewritePropertyAttribute("retain", toAttr, atLoc);
16944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return;
17086f960143c73f573919255c4465de71f85793c2eFariborz Jahanian    }
171b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    case PropAction_AssignRemoved:
172b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return removeAssignForDefaultStrong(props, atLoc);
17344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    case PropAction_AssignRewritten:
17444679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return rewriteAssign(props, atLoc);
17544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    case PropAction_MaybeAddWeakOrUnsafe:
17644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
17744679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    }
17844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  }
17944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
18044679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  void doActionForExtensionProp(PropsTy &props, SourceLocation atLoc) {
18144679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    llvm::DenseMap<IdentifierInfo *, PropActionKind>::iterator I;
18244679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    I = ActionOnProp.find(props[0].PropD->getIdentifier());
18344679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    if (I == ActionOnProp.end())
18444679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return;
18544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
18644679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    doPropAction(I->second, props, atLoc, false);
18744679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  }
18844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis
18944679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis  void rewriteProperty(PropsTy &props, SourceLocation atLoc) {
19014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
19114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
19214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (propAttrs & (ObjCPropertyDecl::OBJC_PR_copy |
19314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                     ObjCPropertyDecl::OBJC_PR_unsafe_unretained |
19414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                     ObjCPropertyDecl::OBJC_PR_strong |
19514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                     ObjCPropertyDecl::OBJC_PR_weak))
19614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return;
19714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
19814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (propAttrs & ObjCPropertyDecl::OBJC_PR_retain) {
1998b08eb34565a644d3345b1bfee3542a8f4a6c300Argyrios Kyrtzidis      // strong is the default.
20086f960143c73f573919255c4465de71f85793c2eFariborz Jahanian      return doPropAction(PropAction_RetainReplacedWithStrong, props, atLoc);
2017196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
20214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
203b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    bool HasIvarAssignedAPlusOneObject = hasIvarAssignedAPlusOneObject(props);
204b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
20518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    if (propAttrs & ObjCPropertyDecl::OBJC_PR_assign) {
2062f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian      if (HasIvarAssignedAPlusOneObject)
207b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        return doPropAction(PropAction_AssignRemoved, props, atLoc);
20844679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis      return doPropAction(PropAction_AssignRewritten, props, atLoc);
20918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
21018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
211b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (HasIvarAssignedAPlusOneObject ||
212b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        (Pass.isGCMigration() && !hasGCWeak(props, atLoc)))
213af9b5e9f3eede62347835d8dedd44df86cbcc308Argyrios Kyrtzidis      return; // 'strong' by default.
21414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
21544679012052b0d57f26a3aa141004687cb71a551Argyrios Kyrtzidis    return doPropAction(PropAction_MaybeAddWeakOrUnsafe, props, atLoc);
2167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
2177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
218b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  void removeAssignForDefaultStrong(PropsTy &props,
219b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                    SourceLocation atLoc) const {
220b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    removeAttribute("retain", atLoc);
221b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (!removeAttribute("assign", atLoc))
222b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return;
223b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
224b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
225b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      if (I->ImplD)
226135aa60c613bdcc0e8e237b12bf93cab04284419Argyrios Kyrtzidis        Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
227135aa60c613bdcc0e8e237b12bf93cab04284419Argyrios Kyrtzidis                                diag::err_arc_assign_property_ownership,
228135aa60c613bdcc0e8e237b12bf93cab04284419Argyrios Kyrtzidis                                diag::err_arc_inconsistent_property_ownership,
229135aa60c613bdcc0e8e237b12bf93cab04284419Argyrios Kyrtzidis                                I->IvarD->getLocation());
230b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    }
231b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  }
232b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
23314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  void rewriteAssign(PropsTy &props, SourceLocation atLoc) const {
234b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
235b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                  /*AllowOnUnknownClass=*/Pass.isGCMigration());
2362f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian    const char *toWhich =
2372f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian      (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "strong" :
2382f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian      (canUseWeak ? "weak" : "unsafe_unretained");
23914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
2402f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian    bool rewroteAttr = rewriteAttribute("assign", toWhich, atLoc);
24114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (!rewroteAttr)
24214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      canUseWeak = false;
2437196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
24414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
2456d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis      if (isUserDeclared(I->IvarD)) {
2466d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis        if (I->IvarD &&
2472f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian            I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak) {
2482f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian          const char *toWhich =
2492f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian            (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "__strong " :
2502f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian              (canUseWeak ? "__weak " : "__unsafe_unretained ");
2512f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian          Pass.TA.insert(I->IvarD->getLocation(), toWhich);
2522f72ec9fc4d3c127b5c77e13346eb640deae396aFariborz Jahanian        }
2536d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis      }
25414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (I->ImplD)
255135aa60c613bdcc0e8e237b12bf93cab04284419Argyrios Kyrtzidis        Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
256135aa60c613bdcc0e8e237b12bf93cab04284419Argyrios Kyrtzidis                                diag::err_arc_assign_property_ownership,
257135aa60c613bdcc0e8e237b12bf93cab04284419Argyrios Kyrtzidis                                diag::err_arc_inconsistent_property_ownership,
258135aa60c613bdcc0e8e237b12bf93cab04284419Argyrios Kyrtzidis                                I->IvarD->getLocation());
25914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    }
2607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
2617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
26214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
26314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                                          SourceLocation atLoc) const {
264b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
265b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                  /*AllowOnUnknownClass=*/Pass.isGCMigration());
2668b08eb34565a644d3345b1bfee3542a8f4a6c300Argyrios Kyrtzidis
2678b08eb34565a644d3345b1bfee3542a8f4a6c300Argyrios Kyrtzidis    bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained",
2688b08eb34565a644d3345b1bfee3542a8f4a6c300Argyrios Kyrtzidis                                  atLoc);
2698b08eb34565a644d3345b1bfee3542a8f4a6c300Argyrios Kyrtzidis    if (!addedAttr)
2708b08eb34565a644d3345b1bfee3542a8f4a6c300Argyrios Kyrtzidis      canUseWeak = false;
27114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
27214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
2736d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis      if (isUserDeclared(I->IvarD)) {
2746d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis        if (I->IvarD &&
2756d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis            I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak)
2766d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis          Pass.TA.insert(I->IvarD->getLocation(),
2776d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis                         canUseWeak ? "__weak " : "__unsafe_unretained ");
2786d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis      }
27914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (I->ImplD) {
280135aa60c613bdcc0e8e237b12bf93cab04284419Argyrios Kyrtzidis        Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
281135aa60c613bdcc0e8e237b12bf93cab04284419Argyrios Kyrtzidis                                diag::err_arc_assign_property_ownership,
282135aa60c613bdcc0e8e237b12bf93cab04284419Argyrios Kyrtzidis                                diag::err_arc_inconsistent_property_ownership,
283135aa60c613bdcc0e8e237b12bf93cab04284419Argyrios Kyrtzidis                                I->IvarD->getLocation());
28414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        Pass.TA.clearDiagnostic(
28514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                           diag::err_arc_objc_property_default_assign_on_object,
28614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                           I->ImplD->getLocation());
2877196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
2887196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
2897196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
2907196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
29101b2b9bb154d69cc695717876e903329f6f0973cArgyrios Kyrtzidis  bool removeAttribute(StringRef fromAttr, SourceLocation atLoc) const {
2926da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis    return MigrateCtx.removePropertyAttribute(fromAttr, atLoc);
29301b2b9bb154d69cc695717876e903329f6f0973cArgyrios Kyrtzidis  }
29401b2b9bb154d69cc695717876e903329f6f0973cArgyrios Kyrtzidis
2955f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  bool rewriteAttribute(StringRef fromAttr, StringRef toAttr,
29614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                        SourceLocation atLoc) const {
297b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return MigrateCtx.rewritePropertyAttribute(fromAttr, toAttr, atLoc);
2987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
2997196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3005f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  bool addAttribute(StringRef attr, SourceLocation atLoc) const {
3016da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis    return MigrateCtx.addPropertyAttribute(attr, atLoc);
30214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
30314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
30418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  class PlusOneAssign : public RecursiveASTVisitor<PlusOneAssign> {
30518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    ObjCIvarDecl *Ivar;
30618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  public:
30718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    PlusOneAssign(ObjCIvarDecl *D) : Ivar(D) {}
30818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
30918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    bool VisitBinAssign(BinaryOperator *E) {
31018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      Expr *lhs = E->getLHS()->IgnoreParenImpCasts();
31118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(lhs)) {
31218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        if (RE->getDecl() != Ivar)
31318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis          return true;
31418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
3151b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis        if (isPlusOneAssign(E))
31694a9016a6b92cfebdb0b7d4dcad930248f1f301aArgyrios Kyrtzidis          return false;
31718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      }
31818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
31918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      return true;
32018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
32118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  };
32218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
32318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  bool hasIvarAssignedAPlusOneObject(PropsTy &props) const {
32418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
32518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      PlusOneAssign oneAssign(I->IvarD);
32618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      bool notFound = oneAssign.TraverseDecl(CurImplD);
32718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (!notFound)
32818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        return true;
32918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
33018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
33118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    return false;
33218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  }
33318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
334bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis  bool hasIvarWithExplicitARCOwnership(PropsTy &props) const {
335bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis    if (Pass.isGCMigration())
336bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis      return false;
337bf8455c56cc5e328c31a2b56f5587cd0873ba0aeArgyrios Kyrtzidis
33814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
33914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (isUserDeclared(I->IvarD)) {
34014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        if (isa<AttributedType>(I->IvarD->getType()))
34114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          return true;
34214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        if (I->IvarD->getType().getLocalQualifiers().getObjCLifetime()
34314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis              != Qualifiers::OCL_Strong)
34414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          return true;
3457196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
3467196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
3477196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
34814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return false;
34914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
35014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
351b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  // \brief Returns true if all declarations in the @property have GC __weak.
352b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  bool hasGCWeak(PropsTy &props, SourceLocation atLoc) const {
353b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (!Pass.isGCMigration())
354b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return false;
355b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (props.empty())
356b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return false;
357b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return MigrateCtx.AtPropsWeak.count(atLoc.getRawEncoding());
358b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  }
359b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
36014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  bool isUserDeclared(ObjCIvarDecl *ivarD) const {
36114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return ivarD && !ivarD->getSynthesize();
36214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
36314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
36414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  QualType getPropertyType(PropsTy &props) const {
36514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    assert(!props.empty());
3661d5fb8f6e85a5c9c7b9b611be655454159c92f12Argyrios Kyrtzidis    QualType ty = props[0].PropD->getType().getUnqualifiedType();
36714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
36814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#ifndef NDEBUG
36914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
3701d5fb8f6e85a5c9c7b9b611be655454159c92f12Argyrios Kyrtzidis      assert(ty == I->PropD->getType().getUnqualifiedType());
37114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#endif
37214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
37314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return ty;
37414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
37514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
37614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  ObjCPropertyDecl::PropertyAttributeKind
37714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  getPropertyAttrs(PropsTy &props) const {
37814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    assert(!props.empty());
37914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    ObjCPropertyDecl::PropertyAttributeKind
38014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      attrs = props[0].PropD->getPropertyAttributesAsWritten();
38114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
38214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#ifndef NDEBUG
38314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
38414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      assert(attrs == I->PropD->getPropertyAttributesAsWritten());
38514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#endif
38614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
38714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return attrs;
3887196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
3897196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis};
3907196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3917196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} // anonymous namespace
3927196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
393b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidisvoid PropertyRewriteTraverser::traverseObjCImplementation(
394b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis                                           ObjCImplementationContext &ImplCtx) {
395b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  PropertiesRewriter(ImplCtx.getMigrationContext())
396b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis                                  .doTransform(ImplCtx.getImplementationDecl());
3977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis}
398