TransProperties.cpp revision 18fd0c6915b45c4daafe18e3cd324c13306f913f
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 {
477196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  MigrationPass &Pass;
4818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  ObjCImplementationDecl *CurImplD;
4914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
507196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  struct PropData {
517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    ObjCPropertyDecl *PropD;
527196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    ObjCIvarDecl *IvarD;
5314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    ObjCPropertyImplDecl *ImplD;
5414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
5514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    PropData(ObjCPropertyDecl *propD) : PropD(propD), IvarD(0), ImplD(0) { }
567196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  };
577196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
585f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  typedef SmallVector<PropData, 2> PropsTy;
5914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  typedef std::map<unsigned, PropsTy> AtPropDeclsTy;
6014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  AtPropDeclsTy AtProps;
617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
627196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidispublic:
6314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  PropertiesRewriter(MigrationPass &pass) : Pass(pass) { }
647196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
657196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  void doTransform(ObjCImplementationDecl *D) {
6618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    CurImplD = D;
6714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    ObjCInterfaceDecl *iface = D->getClassInterface();
6814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (!iface)
6914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return;
707196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
717196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    for (ObjCInterfaceDecl::prop_iterator
7214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis           propI = iface->prop_begin(),
7314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis           propE = iface->prop_end(); propI != propE; ++propI) {
7414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (propI->getAtLoc().isInvalid())
7514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
7614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      PropsTy &props = AtProps[propI->getAtLoc().getRawEncoding()];
7714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      props.push_back(*propI);
787196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
797196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
807196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl>
817196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        prop_impl_iterator;
827196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    for (prop_impl_iterator
837196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis           I = prop_impl_iterator(D->decls_begin()),
847196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis           E = prop_impl_iterator(D->decls_end()); I != E; ++I) {
8514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      ObjCPropertyImplDecl *implD = *I;
8614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (implD->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
8714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
8814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      ObjCPropertyDecl *propD = implD->getPropertyDecl();
8914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (!propD || propD->isInvalidDecl())
9014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
9114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      ObjCIvarDecl *ivarD = implD->getPropertyIvarDecl();
9214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (!ivarD || ivarD->isInvalidDecl())
9314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
9414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      unsigned rawAtLoc = propD->getAtLoc().getRawEncoding();
9514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      AtPropDeclsTy::iterator findAtLoc = AtProps.find(rawAtLoc);
9614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (findAtLoc == AtProps.end())
9714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
9814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
9914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      PropsTy &props = findAtLoc->second;
10014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
10114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        if (I->PropD == propD) {
10214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          I->IvarD = ivarD;
10314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          I->ImplD = implD;
10414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          break;
10514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        }
10614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      }
1077196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
1087196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
10914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (AtPropDeclsTy::iterator
11014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis           I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
1117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
1127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      PropsTy &props = I->second;
11314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      QualType ty = getPropertyType(props);
11414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (!ty->isObjCRetainableType())
11514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
11614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (hasIvarWithExplicitOwnership(props))
11714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        continue;
11814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
11914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      Transaction Trans(Pass.TA);
12014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      rewriteProperty(props, atLoc);
1217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
1227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
1237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
12414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidisprivate:
12514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  void rewriteProperty(PropsTy &props, SourceLocation atLoc) const {
12614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
12714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
12814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (propAttrs & (ObjCPropertyDecl::OBJC_PR_copy |
12914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                     ObjCPropertyDecl::OBJC_PR_unsafe_unretained |
13014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                     ObjCPropertyDecl::OBJC_PR_strong |
13114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                     ObjCPropertyDecl::OBJC_PR_weak))
13214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return;
13314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
13414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (propAttrs & ObjCPropertyDecl::OBJC_PR_retain) {
13514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      rewriteAttribute("retain", "strong", atLoc);
13614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return;
1377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
13814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
13918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    if (propAttrs & ObjCPropertyDecl::OBJC_PR_assign) {
14018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (hasIvarAssignedAPlusOneObject(props)) {
14118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        rewriteAttribute("assign", "strong", atLoc);
14218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        return;
14318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      }
14414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return rewriteAssign(props, atLoc);
14518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
14618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
14718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    if (hasIvarAssignedAPlusOneObject(props))
14818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      return maybeAddStrongAttr(props, atLoc);
14914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
15014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
1517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
1527196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
15314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  void rewriteAssign(PropsTy &props, SourceLocation atLoc) const {
15414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props));
15514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
15614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    bool rewroteAttr = rewriteAttribute("assign",
15714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                                     canUseWeak ? "weak" : "unsafe_unretained",
15814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                                         atLoc);
15914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (!rewroteAttr)
16014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      canUseWeak = false;
1617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
16214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
16314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (isUserDeclared(I->IvarD))
16414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        Pass.TA.insert(I->IvarD->getLocation(),
16514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                       canUseWeak ? "__weak " : "__unsafe_unretained ");
16614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (I->ImplD)
16714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
16814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                                I->ImplD->getLocation());
16914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    }
1707196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
1717196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
17214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
17314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                                          SourceLocation atLoc) const {
17414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
17514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
17614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props));
17718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    if (!(propAttrs & ObjCPropertyDecl::OBJC_PR_readonly) ||
17818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        !hasAllIvarsBacked(props)) {
17918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained",
18018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis                                    atLoc);
18118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (!addedAttr)
18218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        canUseWeak = false;
18318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
18414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
18514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
18614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (isUserDeclared(I->IvarD))
18714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        Pass.TA.insert(I->IvarD->getLocation(),
18814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                       canUseWeak ? "__weak " : "__unsafe_unretained ");
18914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (I->ImplD) {
190b8b0313e84700b5c6d597b3be4de41c97b7550f1Argyrios Kyrtzidis        Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
19114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                                I->ImplD->getLocation());
19214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        Pass.TA.clearDiagnostic(
19314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                           diag::err_arc_objc_property_default_assign_on_object,
19414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                           I->ImplD->getLocation());
1957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
1967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
1977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
1987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
19918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  void maybeAddStrongAttr(PropsTy &props, SourceLocation atLoc) const {
20018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
20118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
20218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    if (!(propAttrs & ObjCPropertyDecl::OBJC_PR_readonly) ||
20318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        !hasAllIvarsBacked(props)) {
20418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      addAttribute("strong", atLoc);
20518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
20618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
20718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
20818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (I->ImplD) {
20918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
21018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis                                I->ImplD->getLocation());
21118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        Pass.TA.clearDiagnostic(
21218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis                           diag::err_arc_objc_property_default_assign_on_object,
21318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis                           I->ImplD->getLocation());
21418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      }
21518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
21618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  }
21718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
2185f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  bool rewriteAttribute(StringRef fromAttr, StringRef toAttr,
21914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                        SourceLocation atLoc) const {
22014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (atLoc.isMacroID())
22114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return false;
22214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
2237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    SourceManager &SM = Pass.Ctx.getSourceManager();
2247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
22514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    // Break down the source location.
22614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
22714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
22814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    // Try to load the file buffer.
22914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    bool invalidTemp = false;
2305f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
23114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (invalidTemp)
23214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return false;
2337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
23414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    const char *tokenBegin = file.data() + locInfo.second;
2357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
23614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    // Lex from the start of the given location.
23714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
23814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                Pass.Ctx.getLangOptions(),
23914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                file.begin(), tokenBegin, file.end());
24014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    Token tok;
24114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    lexer.LexFromRawLexer(tok);
24214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (tok.isNot(tok::at)) return false;
24314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    lexer.LexFromRawLexer(tok);
24414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (tok.isNot(tok::raw_identifier)) return false;
2455f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    if (StringRef(tok.getRawIdentifierData(), tok.getLength())
24614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          != "property")
24714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return false;
24814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    lexer.LexFromRawLexer(tok);
24914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (tok.isNot(tok::l_paren)) return false;
25014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
25114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    lexer.LexFromRawLexer(tok);
25214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (tok.is(tok::r_paren))
25314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return false;
25414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
25514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    while (1) {
25614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (tok.isNot(tok::raw_identifier)) return false;
2575f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner      StringRef ident(tok.getRawIdentifierData(), tok.getLength());
25814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (ident == fromAttr) {
25914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr);
26014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        return true;
2617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
26214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
26314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      do {
26414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        lexer.LexFromRawLexer(tok);
26514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      } while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren));
26614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (tok.is(tok::r_paren))
26714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        break;
26814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      lexer.LexFromRawLexer(tok);
2697196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
2707196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
27114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return false;
2727196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
2737196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2745f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  bool addAttribute(StringRef attr, SourceLocation atLoc) const {
27514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (atLoc.isMacroID())
27614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return false;
27714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
2787196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    SourceManager &SM = Pass.Ctx.getSourceManager();
2797196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2807196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    // Break down the source location.
2817196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
2827196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2837196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    // Try to load the file buffer.
2847196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    bool invalidTemp = false;
2855f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
2867196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (invalidTemp)
28714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return false;
2887196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2897196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    const char *tokenBegin = file.data() + locInfo.second;
2907196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2917196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    // Lex from the start of the given location.
2927196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
2937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                Pass.Ctx.getLangOptions(),
2947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                file.begin(), tokenBegin, file.end());
2957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    Token tok;
2967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    lexer.LexFromRawLexer(tok);
29714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (tok.isNot(tok::at)) return false;
2987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    lexer.LexFromRawLexer(tok);
29914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (tok.isNot(tok::raw_identifier)) return false;
3005f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    if (StringRef(tok.getRawIdentifierData(), tok.getLength())
3017196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          != "property")
30214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return false;
3037196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    lexer.LexFromRawLexer(tok);
3047196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
30514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (tok.isNot(tok::l_paren)) {
30614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      Pass.TA.insert(tok.getLocation(), std::string("(") + attr.str() + ") ");
30714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return true;
30814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    }
30914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
3107196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    lexer.LexFromRawLexer(tok);
3117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (tok.is(tok::r_paren)) {
31214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      Pass.TA.insert(tok.getLocation(), attr);
31314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      return true;
31414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    }
31514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
31614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    if (tok.isNot(tok::raw_identifier)) return false;
31714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
31814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    Pass.TA.insert(tok.getLocation(), std::string(attr) + ", ");
31914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return true;
32014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
32114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
32218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  class PlusOneAssign : public RecursiveASTVisitor<PlusOneAssign> {
32318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    ObjCIvarDecl *Ivar;
32418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  public:
32518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    PlusOneAssign(ObjCIvarDecl *D) : Ivar(D) {}
32618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
32718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    bool VisitBinAssign(BinaryOperator *E) {
32818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      Expr *lhs = E->getLHS()->IgnoreParenImpCasts();
32918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(lhs)) {
33018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        if (RE->getDecl() != Ivar)
33118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis          return true;
33218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
33318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(E->getRHS());
33418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      while (implCE && implCE->getCastKind() ==  CK_BitCast)
33518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        implCE = dyn_cast<ImplicitCastExpr>(implCE->getSubExpr());
33618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
33718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (implCE && implCE->getCastKind() == CK_ObjCConsumeObject)
33818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        return false;
33918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      }
34018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
34118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      return true;
34218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
34318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  };
34418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
34518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  bool hasIvarAssignedAPlusOneObject(PropsTy &props) const {
34618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
34718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      PlusOneAssign oneAssign(I->IvarD);
34818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      bool notFound = oneAssign.TraverseDecl(CurImplD);
34918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (!notFound)
35018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        return true;
35118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    }
35218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
35318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    return false;
35418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  }
35518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
35614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  bool hasIvarWithExplicitOwnership(PropsTy &props) const {
35714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
35814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      if (isUserDeclared(I->IvarD)) {
35914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        if (isa<AttributedType>(I->IvarD->getType()))
36014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          return true;
36114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        if (I->IvarD->getType().getLocalQualifiers().getObjCLifetime()
36214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis              != Qualifiers::OCL_Strong)
36314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis          return true;
3647196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
3657196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
3667196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
36714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return false;
36814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
36914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
37018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  bool hasAllIvarsBacked(PropsTy &props) const {
37114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
37218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (!isUserDeclared(I->IvarD))
37314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis        return false;
37414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
37514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return true;
37614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
37714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
37814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  bool isUserDeclared(ObjCIvarDecl *ivarD) const {
37914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return ivarD && !ivarD->getSynthesize();
38014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
38114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
38214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  QualType getPropertyType(PropsTy &props) const {
38314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    assert(!props.empty());
38414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    QualType ty = props[0].PropD->getType();
38514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
38614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#ifndef NDEBUG
38714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
38814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      assert(ty == I->PropD->getType());
38914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#endif
39014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
39114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return ty;
39214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  }
39314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
39414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  ObjCPropertyDecl::PropertyAttributeKind
39514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  getPropertyAttrs(PropsTy &props) const {
39614c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    assert(!props.empty());
39714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    ObjCPropertyDecl::PropertyAttributeKind
39814c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      attrs = props[0].PropD->getPropertyAttributesAsWritten();
39914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
40014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#ifndef NDEBUG
40114c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
40214c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis      assert(attrs == I->PropD->getPropertyAttributesAsWritten());
40314c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis#endif
40414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis
40514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    return attrs;
4067196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
4077196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis};
4087196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
40914c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidisclass ImplementationChecker :
41014c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis                             public RecursiveASTVisitor<ImplementationChecker> {
4117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  MigrationPass &Pass;
4127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
4137196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidispublic:
41414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  ImplementationChecker(MigrationPass &pass) : Pass(pass) { }
4157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
4167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) {
41714c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis    PropertiesRewriter(Pass).doTransform(D);
4187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    return true;
4197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
4207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis};
4217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
4227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} // anonymous namespace
4237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
42414c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidisvoid trans::rewriteProperties(MigrationPass &pass) {
42514c4b4405fdbb54445c2d2d6320ed4f9e2326696Argyrios Kyrtzidis  ImplementationChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
4267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis}
427