10b57cec5SDimitry Andric //===--- TransProperties.cpp - Transformations to ARC mode ----------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // rewriteProperties:
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric // - Adds strong/weak/unsafe_unretained ownership specifier to properties that
120b57cec5SDimitry Andric // are missing one.
130b57cec5SDimitry Andric // - Migrates properties from (retain) to (strong) and (assign) to
140b57cec5SDimitry Andric // (unsafe_unretained/weak).
150b57cec5SDimitry Andric // - If a property is synthesized, adds the ownership specifier in the ivar
160b57cec5SDimitry Andric // backing the property.
170b57cec5SDimitry Andric //
180b57cec5SDimitry Andric // @interface Foo : NSObject {
190b57cec5SDimitry Andric // NSObject *x;
200b57cec5SDimitry Andric // }
210b57cec5SDimitry Andric // @property (assign) id x;
220b57cec5SDimitry Andric // @end
230b57cec5SDimitry Andric // ---->
240b57cec5SDimitry Andric // @interface Foo : NSObject {
250b57cec5SDimitry Andric // NSObject *__weak x;
260b57cec5SDimitry Andric // }
270b57cec5SDimitry Andric // @property (weak) id x;
280b57cec5SDimitry Andric // @end
290b57cec5SDimitry Andric //
300b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric #include "Transforms.h"
330b57cec5SDimitry Andric #include "Internals.h"
340b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
350b57cec5SDimitry Andric #include "clang/Lex/Lexer.h"
360b57cec5SDimitry Andric #include "clang/Sema/SemaDiagnostic.h"
370b57cec5SDimitry Andric #include <map>
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric using namespace clang;
400b57cec5SDimitry Andric using namespace arcmt;
410b57cec5SDimitry Andric using namespace trans;
420b57cec5SDimitry Andric
430b57cec5SDimitry Andric namespace {
440b57cec5SDimitry Andric
450b57cec5SDimitry Andric class PropertiesRewriter {
460b57cec5SDimitry Andric MigrationContext &MigrateCtx;
470b57cec5SDimitry Andric MigrationPass &Pass;
48*06c3fb27SDimitry Andric ObjCImplementationDecl *CurImplD = nullptr;
490b57cec5SDimitry Andric
500b57cec5SDimitry Andric enum PropActionKind {
510b57cec5SDimitry Andric PropAction_None,
520b57cec5SDimitry Andric PropAction_RetainReplacedWithStrong,
530b57cec5SDimitry Andric PropAction_AssignRemoved,
540b57cec5SDimitry Andric PropAction_AssignRewritten,
550b57cec5SDimitry Andric PropAction_MaybeAddWeakOrUnsafe
560b57cec5SDimitry Andric };
570b57cec5SDimitry Andric
580b57cec5SDimitry Andric struct PropData {
590b57cec5SDimitry Andric ObjCPropertyDecl *PropD;
600b57cec5SDimitry Andric ObjCIvarDecl *IvarD;
610b57cec5SDimitry Andric ObjCPropertyImplDecl *ImplD;
620b57cec5SDimitry Andric
PropData__anon8393a07d0111::PropertiesRewriter::PropData630b57cec5SDimitry Andric PropData(ObjCPropertyDecl *propD)
640b57cec5SDimitry Andric : PropD(propD), IvarD(nullptr), ImplD(nullptr) {}
650b57cec5SDimitry Andric };
660b57cec5SDimitry Andric
670b57cec5SDimitry Andric typedef SmallVector<PropData, 2> PropsTy;
68e8d8bef9SDimitry Andric typedef std::map<SourceLocation, PropsTy> AtPropDeclsTy;
690b57cec5SDimitry Andric AtPropDeclsTy AtProps;
700b57cec5SDimitry Andric llvm::DenseMap<IdentifierInfo *, PropActionKind> ActionOnProp;
710b57cec5SDimitry Andric
720b57cec5SDimitry Andric public:
PropertiesRewriter(MigrationContext & MigrateCtx)730b57cec5SDimitry Andric explicit PropertiesRewriter(MigrationContext &MigrateCtx)
740b57cec5SDimitry Andric : MigrateCtx(MigrateCtx), Pass(MigrateCtx.Pass) { }
750b57cec5SDimitry Andric
collectProperties(ObjCContainerDecl * D,AtPropDeclsTy & AtProps,AtPropDeclsTy * PrevAtProps=nullptr)760b57cec5SDimitry Andric static void collectProperties(ObjCContainerDecl *D, AtPropDeclsTy &AtProps,
770b57cec5SDimitry Andric AtPropDeclsTy *PrevAtProps = nullptr) {
780b57cec5SDimitry Andric for (auto *Prop : D->instance_properties()) {
79e8d8bef9SDimitry Andric SourceLocation Loc = Prop->getAtLoc();
80e8d8bef9SDimitry Andric if (Loc.isInvalid())
810b57cec5SDimitry Andric continue;
820b57cec5SDimitry Andric if (PrevAtProps)
83e8d8bef9SDimitry Andric if (PrevAtProps->find(Loc) != PrevAtProps->end())
840b57cec5SDimitry Andric continue;
85e8d8bef9SDimitry Andric PropsTy &props = AtProps[Loc];
860b57cec5SDimitry Andric props.push_back(Prop);
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric
doTransform(ObjCImplementationDecl * D)900b57cec5SDimitry Andric void doTransform(ObjCImplementationDecl *D) {
910b57cec5SDimitry Andric CurImplD = D;
920b57cec5SDimitry Andric ObjCInterfaceDecl *iface = D->getClassInterface();
930b57cec5SDimitry Andric if (!iface)
940b57cec5SDimitry Andric return;
950b57cec5SDimitry Andric
960b57cec5SDimitry Andric collectProperties(iface, AtProps);
970b57cec5SDimitry Andric
980b57cec5SDimitry Andric // Look through extensions.
990b57cec5SDimitry Andric for (auto *Ext : iface->visible_extensions())
1000b57cec5SDimitry Andric collectProperties(Ext, AtProps);
1010b57cec5SDimitry Andric
1020b57cec5SDimitry Andric typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl>
1030b57cec5SDimitry Andric prop_impl_iterator;
1040b57cec5SDimitry Andric for (prop_impl_iterator
1050b57cec5SDimitry Andric I = prop_impl_iterator(D->decls_begin()),
1060b57cec5SDimitry Andric E = prop_impl_iterator(D->decls_end()); I != E; ++I) {
1070b57cec5SDimitry Andric ObjCPropertyImplDecl *implD = *I;
1080b57cec5SDimitry Andric if (implD->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
1090b57cec5SDimitry Andric continue;
1100b57cec5SDimitry Andric ObjCPropertyDecl *propD = implD->getPropertyDecl();
1110b57cec5SDimitry Andric if (!propD || propD->isInvalidDecl())
1120b57cec5SDimitry Andric continue;
1130b57cec5SDimitry Andric ObjCIvarDecl *ivarD = implD->getPropertyIvarDecl();
1140b57cec5SDimitry Andric if (!ivarD || ivarD->isInvalidDecl())
1150b57cec5SDimitry Andric continue;
116e8d8bef9SDimitry Andric AtPropDeclsTy::iterator findAtLoc = AtProps.find(propD->getAtLoc());
1170b57cec5SDimitry Andric if (findAtLoc == AtProps.end())
1180b57cec5SDimitry Andric continue;
1190b57cec5SDimitry Andric
1200b57cec5SDimitry Andric PropsTy &props = findAtLoc->second;
1210b57cec5SDimitry Andric for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
1220b57cec5SDimitry Andric if (I->PropD == propD) {
1230b57cec5SDimitry Andric I->IvarD = ivarD;
1240b57cec5SDimitry Andric I->ImplD = implD;
1250b57cec5SDimitry Andric break;
1260b57cec5SDimitry Andric }
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric
1300b57cec5SDimitry Andric for (AtPropDeclsTy::iterator
1310b57cec5SDimitry Andric I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
132e8d8bef9SDimitry Andric SourceLocation atLoc = I->first;
1330b57cec5SDimitry Andric PropsTy &props = I->second;
1340b57cec5SDimitry Andric if (!getPropertyType(props)->isObjCRetainableType())
1350b57cec5SDimitry Andric continue;
1360b57cec5SDimitry Andric if (hasIvarWithExplicitARCOwnership(props))
1370b57cec5SDimitry Andric continue;
1380b57cec5SDimitry Andric
1390b57cec5SDimitry Andric Transaction Trans(Pass.TA);
1400b57cec5SDimitry Andric rewriteProperty(props, atLoc);
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric
1440b57cec5SDimitry Andric private:
doPropAction(PropActionKind kind,PropsTy & props,SourceLocation atLoc,bool markAction=true)1450b57cec5SDimitry Andric void doPropAction(PropActionKind kind,
1460b57cec5SDimitry Andric PropsTy &props, SourceLocation atLoc,
1470b57cec5SDimitry Andric bool markAction = true) {
1480b57cec5SDimitry Andric if (markAction)
1490b57cec5SDimitry Andric for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
1500b57cec5SDimitry Andric ActionOnProp[I->PropD->getIdentifier()] = kind;
1510b57cec5SDimitry Andric
1520b57cec5SDimitry Andric switch (kind) {
1530b57cec5SDimitry Andric case PropAction_None:
1540b57cec5SDimitry Andric return;
1550b57cec5SDimitry Andric case PropAction_RetainReplacedWithStrong: {
1560b57cec5SDimitry Andric StringRef toAttr = "strong";
1570b57cec5SDimitry Andric MigrateCtx.rewritePropertyAttribute("retain", toAttr, atLoc);
1580b57cec5SDimitry Andric return;
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric case PropAction_AssignRemoved:
1610b57cec5SDimitry Andric return removeAssignForDefaultStrong(props, atLoc);
1620b57cec5SDimitry Andric case PropAction_AssignRewritten:
1630b57cec5SDimitry Andric return rewriteAssign(props, atLoc);
1640b57cec5SDimitry Andric case PropAction_MaybeAddWeakOrUnsafe:
1650b57cec5SDimitry Andric return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric
rewriteProperty(PropsTy & props,SourceLocation atLoc)1690b57cec5SDimitry Andric void rewriteProperty(PropsTy &props, SourceLocation atLoc) {
1705ffd83dbSDimitry Andric ObjCPropertyAttribute::Kind propAttrs = getPropertyAttrs(props);
1710b57cec5SDimitry Andric
1725ffd83dbSDimitry Andric if (propAttrs &
1735ffd83dbSDimitry Andric (ObjCPropertyAttribute::kind_copy |
1745ffd83dbSDimitry Andric ObjCPropertyAttribute::kind_unsafe_unretained |
1755ffd83dbSDimitry Andric ObjCPropertyAttribute::kind_strong | ObjCPropertyAttribute::kind_weak))
1760b57cec5SDimitry Andric return;
1770b57cec5SDimitry Andric
1785ffd83dbSDimitry Andric if (propAttrs & ObjCPropertyAttribute::kind_retain) {
1790b57cec5SDimitry Andric // strong is the default.
1800b57cec5SDimitry Andric return doPropAction(PropAction_RetainReplacedWithStrong, props, atLoc);
1810b57cec5SDimitry Andric }
1820b57cec5SDimitry Andric
1830b57cec5SDimitry Andric bool HasIvarAssignedAPlusOneObject = hasIvarAssignedAPlusOneObject(props);
1840b57cec5SDimitry Andric
1855ffd83dbSDimitry Andric if (propAttrs & ObjCPropertyAttribute::kind_assign) {
1860b57cec5SDimitry Andric if (HasIvarAssignedAPlusOneObject)
1870b57cec5SDimitry Andric return doPropAction(PropAction_AssignRemoved, props, atLoc);
1880b57cec5SDimitry Andric return doPropAction(PropAction_AssignRewritten, props, atLoc);
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric
1910b57cec5SDimitry Andric if (HasIvarAssignedAPlusOneObject ||
1920b57cec5SDimitry Andric (Pass.isGCMigration() && !hasGCWeak(props, atLoc)))
1930b57cec5SDimitry Andric return; // 'strong' by default.
1940b57cec5SDimitry Andric
1950b57cec5SDimitry Andric return doPropAction(PropAction_MaybeAddWeakOrUnsafe, props, atLoc);
1960b57cec5SDimitry Andric }
1970b57cec5SDimitry Andric
removeAssignForDefaultStrong(PropsTy & props,SourceLocation atLoc) const1980b57cec5SDimitry Andric void removeAssignForDefaultStrong(PropsTy &props,
1990b57cec5SDimitry Andric SourceLocation atLoc) const {
2000b57cec5SDimitry Andric removeAttribute("retain", atLoc);
2010b57cec5SDimitry Andric if (!removeAttribute("assign", atLoc))
2020b57cec5SDimitry Andric return;
2030b57cec5SDimitry Andric
2040b57cec5SDimitry Andric for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
2050b57cec5SDimitry Andric if (I->ImplD)
2060b57cec5SDimitry Andric Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
2070b57cec5SDimitry Andric diag::err_arc_assign_property_ownership,
2080b57cec5SDimitry Andric diag::err_arc_inconsistent_property_ownership,
2090b57cec5SDimitry Andric I->IvarD->getLocation());
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric
rewriteAssign(PropsTy & props,SourceLocation atLoc) const2130b57cec5SDimitry Andric void rewriteAssign(PropsTy &props, SourceLocation atLoc) const {
2140b57cec5SDimitry Andric bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
2150b57cec5SDimitry Andric /*AllowOnUnknownClass=*/Pass.isGCMigration());
2160b57cec5SDimitry Andric const char *toWhich =
2170b57cec5SDimitry Andric (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "strong" :
2180b57cec5SDimitry Andric (canUseWeak ? "weak" : "unsafe_unretained");
2190b57cec5SDimitry Andric
2200b57cec5SDimitry Andric bool rewroteAttr = rewriteAttribute("assign", toWhich, atLoc);
2210b57cec5SDimitry Andric if (!rewroteAttr)
2220b57cec5SDimitry Andric canUseWeak = false;
2230b57cec5SDimitry Andric
2240b57cec5SDimitry Andric for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
2250b57cec5SDimitry Andric if (isUserDeclared(I->IvarD)) {
2260b57cec5SDimitry Andric if (I->IvarD &&
2270b57cec5SDimitry Andric I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak) {
2280b57cec5SDimitry Andric const char *toWhich =
2290b57cec5SDimitry Andric (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "__strong " :
2300b57cec5SDimitry Andric (canUseWeak ? "__weak " : "__unsafe_unretained ");
2310b57cec5SDimitry Andric Pass.TA.insert(I->IvarD->getLocation(), toWhich);
2320b57cec5SDimitry Andric }
2330b57cec5SDimitry Andric }
2340b57cec5SDimitry Andric if (I->ImplD)
2350b57cec5SDimitry Andric Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
2360b57cec5SDimitry Andric diag::err_arc_assign_property_ownership,
2370b57cec5SDimitry Andric diag::err_arc_inconsistent_property_ownership,
2380b57cec5SDimitry Andric I->IvarD->getLocation());
2390b57cec5SDimitry Andric }
2400b57cec5SDimitry Andric }
2410b57cec5SDimitry Andric
maybeAddWeakOrUnsafeUnretainedAttr(PropsTy & props,SourceLocation atLoc) const2420b57cec5SDimitry Andric void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
2430b57cec5SDimitry Andric SourceLocation atLoc) const {
2440b57cec5SDimitry Andric bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
2450b57cec5SDimitry Andric /*AllowOnUnknownClass=*/Pass.isGCMigration());
2460b57cec5SDimitry Andric
2470b57cec5SDimitry Andric bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained",
2480b57cec5SDimitry Andric atLoc);
2490b57cec5SDimitry Andric if (!addedAttr)
2500b57cec5SDimitry Andric canUseWeak = false;
2510b57cec5SDimitry Andric
2520b57cec5SDimitry Andric for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
2530b57cec5SDimitry Andric if (isUserDeclared(I->IvarD)) {
2540b57cec5SDimitry Andric if (I->IvarD &&
2550b57cec5SDimitry Andric I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak)
2560b57cec5SDimitry Andric Pass.TA.insert(I->IvarD->getLocation(),
2570b57cec5SDimitry Andric canUseWeak ? "__weak " : "__unsafe_unretained ");
2580b57cec5SDimitry Andric }
2590b57cec5SDimitry Andric if (I->ImplD) {
2600b57cec5SDimitry Andric Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
2610b57cec5SDimitry Andric diag::err_arc_assign_property_ownership,
2620b57cec5SDimitry Andric diag::err_arc_inconsistent_property_ownership,
2630b57cec5SDimitry Andric I->IvarD->getLocation());
2640b57cec5SDimitry Andric Pass.TA.clearDiagnostic(
2650b57cec5SDimitry Andric diag::err_arc_objc_property_default_assign_on_object,
2660b57cec5SDimitry Andric I->ImplD->getLocation());
2670b57cec5SDimitry Andric }
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric }
2700b57cec5SDimitry Andric
removeAttribute(StringRef fromAttr,SourceLocation atLoc) const2710b57cec5SDimitry Andric bool removeAttribute(StringRef fromAttr, SourceLocation atLoc) const {
2720b57cec5SDimitry Andric return MigrateCtx.removePropertyAttribute(fromAttr, atLoc);
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric
rewriteAttribute(StringRef fromAttr,StringRef toAttr,SourceLocation atLoc) const2750b57cec5SDimitry Andric bool rewriteAttribute(StringRef fromAttr, StringRef toAttr,
2760b57cec5SDimitry Andric SourceLocation atLoc) const {
2770b57cec5SDimitry Andric return MigrateCtx.rewritePropertyAttribute(fromAttr, toAttr, atLoc);
2780b57cec5SDimitry Andric }
2790b57cec5SDimitry Andric
addAttribute(StringRef attr,SourceLocation atLoc) const2800b57cec5SDimitry Andric bool addAttribute(StringRef attr, SourceLocation atLoc) const {
2810b57cec5SDimitry Andric return MigrateCtx.addPropertyAttribute(attr, atLoc);
2820b57cec5SDimitry Andric }
2830b57cec5SDimitry Andric
2840b57cec5SDimitry Andric class PlusOneAssign : public RecursiveASTVisitor<PlusOneAssign> {
2850b57cec5SDimitry Andric ObjCIvarDecl *Ivar;
2860b57cec5SDimitry Andric public:
PlusOneAssign(ObjCIvarDecl * D)2870b57cec5SDimitry Andric PlusOneAssign(ObjCIvarDecl *D) : Ivar(D) {}
2880b57cec5SDimitry Andric
VisitBinaryOperator(BinaryOperator * E)2895ffd83dbSDimitry Andric bool VisitBinaryOperator(BinaryOperator *E) {
2905ffd83dbSDimitry Andric if (E->getOpcode() != BO_Assign)
2915ffd83dbSDimitry Andric return true;
2925ffd83dbSDimitry Andric
2930b57cec5SDimitry Andric Expr *lhs = E->getLHS()->IgnoreParenImpCasts();
2940b57cec5SDimitry Andric if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(lhs)) {
2950b57cec5SDimitry Andric if (RE->getDecl() != Ivar)
2960b57cec5SDimitry Andric return true;
2970b57cec5SDimitry Andric
2980b57cec5SDimitry Andric if (isPlusOneAssign(E))
2990b57cec5SDimitry Andric return false;
3000b57cec5SDimitry Andric }
3010b57cec5SDimitry Andric
3020b57cec5SDimitry Andric return true;
3030b57cec5SDimitry Andric }
3040b57cec5SDimitry Andric };
3050b57cec5SDimitry Andric
hasIvarAssignedAPlusOneObject(PropsTy & props) const3060b57cec5SDimitry Andric bool hasIvarAssignedAPlusOneObject(PropsTy &props) const {
3070b57cec5SDimitry Andric for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
3080b57cec5SDimitry Andric PlusOneAssign oneAssign(I->IvarD);
3090b57cec5SDimitry Andric bool notFound = oneAssign.TraverseDecl(CurImplD);
3100b57cec5SDimitry Andric if (!notFound)
3110b57cec5SDimitry Andric return true;
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric
3140b57cec5SDimitry Andric return false;
3150b57cec5SDimitry Andric }
3160b57cec5SDimitry Andric
hasIvarWithExplicitARCOwnership(PropsTy & props) const3170b57cec5SDimitry Andric bool hasIvarWithExplicitARCOwnership(PropsTy &props) const {
3180b57cec5SDimitry Andric if (Pass.isGCMigration())
3190b57cec5SDimitry Andric return false;
3200b57cec5SDimitry Andric
3210b57cec5SDimitry Andric for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
3220b57cec5SDimitry Andric if (isUserDeclared(I->IvarD)) {
3230b57cec5SDimitry Andric if (isa<AttributedType>(I->IvarD->getType()))
3240b57cec5SDimitry Andric return true;
3250b57cec5SDimitry Andric if (I->IvarD->getType().getLocalQualifiers().getObjCLifetime()
3260b57cec5SDimitry Andric != Qualifiers::OCL_Strong)
3270b57cec5SDimitry Andric return true;
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric }
3300b57cec5SDimitry Andric
3310b57cec5SDimitry Andric return false;
3320b57cec5SDimitry Andric }
3330b57cec5SDimitry Andric
3340b57cec5SDimitry Andric // Returns true if all declarations in the @property have GC __weak.
hasGCWeak(PropsTy & props,SourceLocation atLoc) const3350b57cec5SDimitry Andric bool hasGCWeak(PropsTy &props, SourceLocation atLoc) const {
3360b57cec5SDimitry Andric if (!Pass.isGCMigration())
3370b57cec5SDimitry Andric return false;
3380b57cec5SDimitry Andric if (props.empty())
3390b57cec5SDimitry Andric return false;
340e8d8bef9SDimitry Andric return MigrateCtx.AtPropsWeak.count(atLoc);
3410b57cec5SDimitry Andric }
3420b57cec5SDimitry Andric
isUserDeclared(ObjCIvarDecl * ivarD) const3430b57cec5SDimitry Andric bool isUserDeclared(ObjCIvarDecl *ivarD) const {
3440b57cec5SDimitry Andric return ivarD && !ivarD->getSynthesize();
3450b57cec5SDimitry Andric }
3460b57cec5SDimitry Andric
getPropertyType(PropsTy & props) const3470b57cec5SDimitry Andric QualType getPropertyType(PropsTy &props) const {
3480b57cec5SDimitry Andric assert(!props.empty());
3490b57cec5SDimitry Andric QualType ty = props[0].PropD->getType().getUnqualifiedType();
3500b57cec5SDimitry Andric
3510b57cec5SDimitry Andric #ifndef NDEBUG
3520b57cec5SDimitry Andric for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
3530b57cec5SDimitry Andric assert(ty == I->PropD->getType().getUnqualifiedType());
3540b57cec5SDimitry Andric #endif
3550b57cec5SDimitry Andric
3560b57cec5SDimitry Andric return ty;
3570b57cec5SDimitry Andric }
3580b57cec5SDimitry Andric
getPropertyAttrs(PropsTy & props) const3595ffd83dbSDimitry Andric ObjCPropertyAttribute::Kind getPropertyAttrs(PropsTy &props) const {
3600b57cec5SDimitry Andric assert(!props.empty());
3615ffd83dbSDimitry Andric ObjCPropertyAttribute::Kind attrs =
3625ffd83dbSDimitry Andric props[0].PropD->getPropertyAttributesAsWritten();
3630b57cec5SDimitry Andric
3640b57cec5SDimitry Andric #ifndef NDEBUG
3650b57cec5SDimitry Andric for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
3660b57cec5SDimitry Andric assert(attrs == I->PropD->getPropertyAttributesAsWritten());
3670b57cec5SDimitry Andric #endif
3680b57cec5SDimitry Andric
3690b57cec5SDimitry Andric return attrs;
3700b57cec5SDimitry Andric }
3710b57cec5SDimitry Andric };
3720b57cec5SDimitry Andric
3730b57cec5SDimitry Andric } // anonymous namespace
3740b57cec5SDimitry Andric
traverseObjCImplementation(ObjCImplementationContext & ImplCtx)3750b57cec5SDimitry Andric void PropertyRewriteTraverser::traverseObjCImplementation(
3760b57cec5SDimitry Andric ObjCImplementationContext &ImplCtx) {
3770b57cec5SDimitry Andric PropertiesRewriter(ImplCtx.getMigrationContext())
3780b57cec5SDimitry Andric .doTransform(ImplCtx.getImplementationDecl());
3790b57cec5SDimitry Andric }
380