2012-11-14 23:08:31 +08:00
|
|
|
//===--- TransProperties.cpp - Transformations to ARC mode ----------------===//
|
2011-06-22 04:20:39 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2011-07-14 03:22:00 +08:00
|
|
|
// rewriteProperties:
|
2011-06-22 04:20:39 +08:00
|
|
|
//
|
2011-07-14 03:22:00 +08:00
|
|
|
// - Adds strong/weak/unsafe_unretained ownership specifier to properties that
|
|
|
|
// are missing one.
|
|
|
|
// - Migrates properties from (retain) to (strong) and (assign) to
|
|
|
|
// (unsafe_unretained/weak).
|
|
|
|
// - If a property is synthesized, adds the ownership specifier in the ivar
|
|
|
|
// backing the property.
|
2011-06-22 04:20:39 +08:00
|
|
|
//
|
|
|
|
// @interface Foo : NSObject {
|
|
|
|
// NSObject *x;
|
|
|
|
// }
|
|
|
|
// @property (assign) id x;
|
|
|
|
// @end
|
|
|
|
// ---->
|
|
|
|
// @interface Foo : NSObject {
|
|
|
|
// NSObject *__weak x;
|
|
|
|
// }
|
|
|
|
// @property (weak) id x;
|
|
|
|
// @end
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "Transforms.h"
|
|
|
|
#include "Internals.h"
|
|
|
|
#include "clang/Basic/SourceManager.h"
|
|
|
|
#include "clang/Lex/Lexer.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Sema/SemaDiagnostic.h"
|
2011-07-14 03:22:00 +08:00
|
|
|
#include <map>
|
2011-06-22 04:20:39 +08:00
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
using namespace arcmt;
|
|
|
|
using namespace trans;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2011-07-14 03:22:00 +08:00
|
|
|
class PropertiesRewriter {
|
2011-11-08 02:46:46 +08:00
|
|
|
MigrationContext &MigrateCtx;
|
2011-06-22 04:20:39 +08:00
|
|
|
MigrationPass &Pass;
|
2011-07-27 13:28:18 +08:00
|
|
|
ObjCImplementationDecl *CurImplD;
|
2011-10-19 03:49:19 +08:00
|
|
|
|
|
|
|
enum PropActionKind {
|
|
|
|
PropAction_None,
|
2012-01-21 03:15:02 +08:00
|
|
|
PropAction_RetainReplacedWithStrong,
|
2011-11-08 02:46:46 +08:00
|
|
|
PropAction_AssignRemoved,
|
2011-10-19 03:49:19 +08:00
|
|
|
PropAction_AssignRewritten,
|
|
|
|
PropAction_MaybeAddWeakOrUnsafe
|
|
|
|
};
|
2011-07-14 03:22:00 +08:00
|
|
|
|
2011-06-22 04:20:39 +08:00
|
|
|
struct PropData {
|
|
|
|
ObjCPropertyDecl *PropD;
|
|
|
|
ObjCIvarDecl *IvarD;
|
2011-07-14 03:22:00 +08:00
|
|
|
ObjCPropertyImplDecl *ImplD;
|
|
|
|
|
2014-05-07 14:21:57 +08:00
|
|
|
PropData(ObjCPropertyDecl *propD)
|
|
|
|
: PropD(propD), IvarD(nullptr), ImplD(nullptr) {}
|
2011-06-22 04:20:39 +08:00
|
|
|
};
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
typedef SmallVector<PropData, 2> PropsTy;
|
2011-07-14 03:22:00 +08:00
|
|
|
typedef std::map<unsigned, PropsTy> AtPropDeclsTy;
|
|
|
|
AtPropDeclsTy AtProps;
|
2011-10-19 03:49:19 +08:00
|
|
|
llvm::DenseMap<IdentifierInfo *, PropActionKind> ActionOnProp;
|
2011-06-22 04:20:39 +08:00
|
|
|
|
|
|
|
public:
|
2011-11-08 02:46:46 +08:00
|
|
|
explicit PropertiesRewriter(MigrationContext &MigrateCtx)
|
|
|
|
: MigrateCtx(MigrateCtx), Pass(MigrateCtx.Pass) { }
|
2011-06-22 04:20:39 +08:00
|
|
|
|
2012-03-29 09:10:31 +08:00
|
|
|
static void collectProperties(ObjCContainerDecl *D, AtPropDeclsTy &AtProps,
|
2014-05-07 14:21:57 +08:00
|
|
|
AtPropDeclsTy *PrevAtProps = nullptr) {
|
2016-01-27 02:05:23 +08:00
|
|
|
for (auto *Prop : D->instance_properties()) {
|
2014-03-14 02:47:37 +08:00
|
|
|
if (Prop->getAtLoc().isInvalid())
|
2011-07-14 03:22:00 +08:00
|
|
|
continue;
|
2014-03-14 02:47:37 +08:00
|
|
|
unsigned RawLoc = Prop->getAtLoc().getRawEncoding();
|
2012-03-29 09:10:31 +08:00
|
|
|
if (PrevAtProps)
|
|
|
|
if (PrevAtProps->find(RawLoc) != PrevAtProps->end())
|
|
|
|
continue;
|
|
|
|
PropsTy &props = AtProps[RawLoc];
|
2014-03-14 02:47:37 +08:00
|
|
|
props.push_back(Prop);
|
2011-06-22 04:20:39 +08:00
|
|
|
}
|
2011-10-19 03:49:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void doTransform(ObjCImplementationDecl *D) {
|
|
|
|
CurImplD = D;
|
|
|
|
ObjCInterfaceDecl *iface = D->getClassInterface();
|
|
|
|
if (!iface)
|
|
|
|
return;
|
|
|
|
|
|
|
|
collectProperties(iface, AtProps);
|
2011-06-22 04:20:39 +08:00
|
|
|
|
Stop back-patching 'readonly' Objective-C properties with 'readwrite' ones.
A 'readonly' Objective-C property declared in the primary class can
effectively be shadowed by a 'readwrite' property declared within an
extension of that class, so long as the types and attributes of the
two property declarations are compatible.
Previously, this functionality was implemented by back-patching the
original 'readonly' property to make it 'readwrite', destroying source
information and causing some hideously redundant, incorrect
code. Simplify the implementation to express how this should actually
be modeled: as a separate property declaration in the extension that
shadows (via the name lookup rules) the declaration in the primary
class. While here, correct some broken Fix-Its, eliminate a pile of
redundant code, clean up the ARC migrator's handling of properties
declared in extensions, and fix debug info's naming of methods that
come from categories.
A wonderous side effect of doing this write is that it eliminates the
"AddedObjCPropertyInClassExtension" method from the AST mutation
listener, which in turn eliminates the last place where we rewrite
entire declarations in a chained PCH file or a module file. This
change (which fixes rdar://problem/18475765) will allow us to
eliminate the rewritten-decls logic from the serialization library,
and fixes a crash (rdar://problem/23247794) illustrated by the
test/PCH/chain-categories.m example.
llvm-svn: 251874
2015-11-03 09:15:46 +08:00
|
|
|
// Look through extensions.
|
|
|
|
for (auto *Ext : iface->visible_extensions())
|
|
|
|
collectProperties(Ext, AtProps);
|
|
|
|
|
2011-06-22 04:20:39 +08:00
|
|
|
typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl>
|
|
|
|
prop_impl_iterator;
|
|
|
|
for (prop_impl_iterator
|
|
|
|
I = prop_impl_iterator(D->decls_begin()),
|
|
|
|
E = prop_impl_iterator(D->decls_end()); I != E; ++I) {
|
2012-06-07 04:45:41 +08:00
|
|
|
ObjCPropertyImplDecl *implD = *I;
|
2011-07-14 03:22:00 +08:00
|
|
|
if (implD->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
|
|
|
|
continue;
|
|
|
|
ObjCPropertyDecl *propD = implD->getPropertyDecl();
|
|
|
|
if (!propD || propD->isInvalidDecl())
|
|
|
|
continue;
|
|
|
|
ObjCIvarDecl *ivarD = implD->getPropertyIvarDecl();
|
|
|
|
if (!ivarD || ivarD->isInvalidDecl())
|
|
|
|
continue;
|
|
|
|
unsigned rawAtLoc = propD->getAtLoc().getRawEncoding();
|
|
|
|
AtPropDeclsTy::iterator findAtLoc = AtProps.find(rawAtLoc);
|
|
|
|
if (findAtLoc == AtProps.end())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
PropsTy &props = findAtLoc->second;
|
|
|
|
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
|
|
|
|
if (I->PropD == propD) {
|
|
|
|
I->IvarD = ivarD;
|
|
|
|
I->ImplD = implD;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-06-22 04:20:39 +08:00
|
|
|
}
|
|
|
|
|
2011-07-14 03:22:00 +08:00
|
|
|
for (AtPropDeclsTy::iterator
|
|
|
|
I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
|
2011-06-22 04:20:39 +08:00
|
|
|
SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
|
|
|
|
PropsTy &props = I->second;
|
2011-11-07 02:58:07 +08:00
|
|
|
if (!getPropertyType(props)->isObjCRetainableType())
|
2011-07-14 03:22:00 +08:00
|
|
|
continue;
|
2011-11-08 02:40:32 +08:00
|
|
|
if (hasIvarWithExplicitARCOwnership(props))
|
2011-07-14 03:22:00 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
Transaction Trans(Pass.TA);
|
|
|
|
rewriteProperty(props, atLoc);
|
2011-06-22 04:20:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-14 03:22:00 +08:00
|
|
|
private:
|
2011-10-19 03:49:19 +08:00
|
|
|
void doPropAction(PropActionKind kind,
|
|
|
|
PropsTy &props, SourceLocation atLoc,
|
|
|
|
bool markAction = true) {
|
|
|
|
if (markAction)
|
|
|
|
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
|
|
|
|
ActionOnProp[I->PropD->getIdentifier()] = kind;
|
|
|
|
|
|
|
|
switch (kind) {
|
|
|
|
case PropAction_None:
|
|
|
|
return;
|
2012-01-21 03:15:02 +08:00
|
|
|
case PropAction_RetainReplacedWithStrong: {
|
|
|
|
StringRef toAttr = "strong";
|
|
|
|
MigrateCtx.rewritePropertyAttribute("retain", toAttr, atLoc);
|
2011-10-19 03:49:19 +08:00
|
|
|
return;
|
2012-01-21 03:15:02 +08:00
|
|
|
}
|
2011-11-08 02:46:46 +08:00
|
|
|
case PropAction_AssignRemoved:
|
|
|
|
return removeAssignForDefaultStrong(props, atLoc);
|
2011-10-19 03:49:19 +08:00
|
|
|
case PropAction_AssignRewritten:
|
|
|
|
return rewriteAssign(props, atLoc);
|
|
|
|
case PropAction_MaybeAddWeakOrUnsafe:
|
|
|
|
return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void rewriteProperty(PropsTy &props, SourceLocation atLoc) {
|
2011-07-14 03:22:00 +08:00
|
|
|
ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
|
|
|
|
|
|
|
|
if (propAttrs & (ObjCPropertyDecl::OBJC_PR_copy |
|
|
|
|
ObjCPropertyDecl::OBJC_PR_unsafe_unretained |
|
|
|
|
ObjCPropertyDecl::OBJC_PR_strong |
|
|
|
|
ObjCPropertyDecl::OBJC_PR_weak))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (propAttrs & ObjCPropertyDecl::OBJC_PR_retain) {
|
2011-11-09 07:09:34 +08:00
|
|
|
// strong is the default.
|
2012-01-21 03:15:02 +08:00
|
|
|
return doPropAction(PropAction_RetainReplacedWithStrong, props, atLoc);
|
2011-06-22 04:20:39 +08:00
|
|
|
}
|
2011-07-14 03:22:00 +08:00
|
|
|
|
2011-11-08 02:46:46 +08:00
|
|
|
bool HasIvarAssignedAPlusOneObject = hasIvarAssignedAPlusOneObject(props);
|
|
|
|
|
2011-07-27 13:28:18 +08:00
|
|
|
if (propAttrs & ObjCPropertyDecl::OBJC_PR_assign) {
|
2012-01-21 08:43:53 +08:00
|
|
|
if (HasIvarAssignedAPlusOneObject)
|
2011-11-08 02:46:46 +08:00
|
|
|
return doPropAction(PropAction_AssignRemoved, props, atLoc);
|
2011-10-19 03:49:19 +08:00
|
|
|
return doPropAction(PropAction_AssignRewritten, props, atLoc);
|
2011-07-27 13:28:18 +08:00
|
|
|
}
|
|
|
|
|
2011-11-08 02:46:46 +08:00
|
|
|
if (HasIvarAssignedAPlusOneObject ||
|
|
|
|
(Pass.isGCMigration() && !hasGCWeak(props, atLoc)))
|
2011-11-09 06:10:58 +08:00
|
|
|
return; // 'strong' by default.
|
2011-07-14 03:22:00 +08:00
|
|
|
|
2011-10-19 03:49:19 +08:00
|
|
|
return doPropAction(PropAction_MaybeAddWeakOrUnsafe, props, atLoc);
|
2011-06-22 04:20:39 +08:00
|
|
|
}
|
|
|
|
|
2011-11-08 02:46:46 +08:00
|
|
|
void removeAssignForDefaultStrong(PropsTy &props,
|
|
|
|
SourceLocation atLoc) const {
|
|
|
|
removeAttribute("retain", atLoc);
|
|
|
|
if (!removeAttribute("assign", atLoc))
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
|
|
|
|
if (I->ImplD)
|
2012-12-13 06:48:25 +08:00
|
|
|
Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
|
|
|
|
diag::err_arc_assign_property_ownership,
|
|
|
|
diag::err_arc_inconsistent_property_ownership,
|
|
|
|
I->IvarD->getLocation());
|
2011-11-08 02:46:46 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-14 03:22:00 +08:00
|
|
|
void rewriteAssign(PropsTy &props, SourceLocation atLoc) const {
|
2011-11-08 02:46:46 +08:00
|
|
|
bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
|
|
|
|
/*AllowOnUnknownClass=*/Pass.isGCMigration());
|
2012-01-21 08:43:53 +08:00
|
|
|
const char *toWhich =
|
|
|
|
(Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "strong" :
|
|
|
|
(canUseWeak ? "weak" : "unsafe_unretained");
|
2011-07-14 03:22:00 +08:00
|
|
|
|
2012-01-21 08:43:53 +08:00
|
|
|
bool rewroteAttr = rewriteAttribute("assign", toWhich, atLoc);
|
2011-07-14 03:22:00 +08:00
|
|
|
if (!rewroteAttr)
|
|
|
|
canUseWeak = false;
|
2011-06-22 04:20:39 +08:00
|
|
|
|
2011-07-14 03:22:00 +08:00
|
|
|
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
|
2011-11-28 08:23:12 +08:00
|
|
|
if (isUserDeclared(I->IvarD)) {
|
|
|
|
if (I->IvarD &&
|
2012-01-21 08:43:53 +08:00
|
|
|
I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak) {
|
|
|
|
const char *toWhich =
|
|
|
|
(Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "__strong " :
|
|
|
|
(canUseWeak ? "__weak " : "__unsafe_unretained ");
|
|
|
|
Pass.TA.insert(I->IvarD->getLocation(), toWhich);
|
|
|
|
}
|
2011-11-28 08:23:12 +08:00
|
|
|
}
|
2011-07-14 03:22:00 +08:00
|
|
|
if (I->ImplD)
|
2012-12-13 06:48:25 +08:00
|
|
|
Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
|
|
|
|
diag::err_arc_assign_property_ownership,
|
|
|
|
diag::err_arc_inconsistent_property_ownership,
|
|
|
|
I->IvarD->getLocation());
|
2011-07-14 03:22:00 +08:00
|
|
|
}
|
2011-06-22 04:20:39 +08:00
|
|
|
}
|
|
|
|
|
2011-07-14 03:22:00 +08:00
|
|
|
void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
|
|
|
|
SourceLocation atLoc) const {
|
2011-11-08 02:46:46 +08:00
|
|
|
bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
|
|
|
|
/*AllowOnUnknownClass=*/Pass.isGCMigration());
|
2011-11-09 07:09:34 +08:00
|
|
|
|
|
|
|
bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained",
|
|
|
|
atLoc);
|
|
|
|
if (!addedAttr)
|
|
|
|
canUseWeak = false;
|
2011-07-14 03:22:00 +08:00
|
|
|
|
|
|
|
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
|
2011-11-28 08:23:12 +08:00
|
|
|
if (isUserDeclared(I->IvarD)) {
|
|
|
|
if (I->IvarD &&
|
|
|
|
I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak)
|
|
|
|
Pass.TA.insert(I->IvarD->getLocation(),
|
|
|
|
canUseWeak ? "__weak " : "__unsafe_unretained ");
|
|
|
|
}
|
2011-07-14 03:22:00 +08:00
|
|
|
if (I->ImplD) {
|
2012-12-13 06:48:25 +08:00
|
|
|
Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
|
|
|
|
diag::err_arc_assign_property_ownership,
|
|
|
|
diag::err_arc_inconsistent_property_ownership,
|
|
|
|
I->IvarD->getLocation());
|
2011-07-14 03:22:00 +08:00
|
|
|
Pass.TA.clearDiagnostic(
|
|
|
|
diag::err_arc_objc_property_default_assign_on_object,
|
|
|
|
I->ImplD->getLocation());
|
2011-06-22 04:20:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-18 07:14:16 +08:00
|
|
|
bool removeAttribute(StringRef fromAttr, SourceLocation atLoc) const {
|
2011-11-28 10:04:36 +08:00
|
|
|
return MigrateCtx.removePropertyAttribute(fromAttr, atLoc);
|
2011-10-18 07:14:16 +08:00
|
|
|
}
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
bool rewriteAttribute(StringRef fromAttr, StringRef toAttr,
|
2011-07-14 03:22:00 +08:00
|
|
|
SourceLocation atLoc) const {
|
2011-11-08 02:46:46 +08:00
|
|
|
return MigrateCtx.rewritePropertyAttribute(fromAttr, toAttr, atLoc);
|
2011-06-22 04:20:39 +08:00
|
|
|
}
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
bool addAttribute(StringRef attr, SourceLocation atLoc) const {
|
2011-11-28 10:04:36 +08:00
|
|
|
return MigrateCtx.addPropertyAttribute(attr, atLoc);
|
2011-07-14 03:22:00 +08:00
|
|
|
}
|
|
|
|
|
2011-07-27 13:28:18 +08:00
|
|
|
class PlusOneAssign : public RecursiveASTVisitor<PlusOneAssign> {
|
|
|
|
ObjCIvarDecl *Ivar;
|
|
|
|
public:
|
|
|
|
PlusOneAssign(ObjCIvarDecl *D) : Ivar(D) {}
|
|
|
|
|
|
|
|
bool VisitBinAssign(BinaryOperator *E) {
|
|
|
|
Expr *lhs = E->getLHS()->IgnoreParenImpCasts();
|
|
|
|
if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(lhs)) {
|
|
|
|
if (RE->getDecl() != Ivar)
|
|
|
|
return true;
|
|
|
|
|
2012-05-24 05:50:04 +08:00
|
|
|
if (isPlusOneAssign(E))
|
2011-08-11 05:46:48 +08:00
|
|
|
return false;
|
2011-07-27 13:28:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
bool hasIvarAssignedAPlusOneObject(PropsTy &props) const {
|
|
|
|
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
|
|
|
|
PlusOneAssign oneAssign(I->IvarD);
|
|
|
|
bool notFound = oneAssign.TraverseDecl(CurImplD);
|
|
|
|
if (!notFound)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-11-08 02:40:32 +08:00
|
|
|
bool hasIvarWithExplicitARCOwnership(PropsTy &props) const {
|
|
|
|
if (Pass.isGCMigration())
|
|
|
|
return false;
|
|
|
|
|
2011-07-14 03:22:00 +08:00
|
|
|
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
|
|
|
|
if (isUserDeclared(I->IvarD)) {
|
|
|
|
if (isa<AttributedType>(I->IvarD->getType()))
|
|
|
|
return true;
|
|
|
|
if (I->IvarD->getType().getLocalQualifiers().getObjCLifetime()
|
|
|
|
!= Qualifiers::OCL_Strong)
|
|
|
|
return true;
|
2011-06-22 04:20:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-14 03:22:00 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
// Returns true if all declarations in the @property have GC __weak.
|
2011-11-08 02:46:46 +08:00
|
|
|
bool hasGCWeak(PropsTy &props, SourceLocation atLoc) const {
|
|
|
|
if (!Pass.isGCMigration())
|
|
|
|
return false;
|
|
|
|
if (props.empty())
|
|
|
|
return false;
|
|
|
|
return MigrateCtx.AtPropsWeak.count(atLoc.getRawEncoding());
|
|
|
|
}
|
|
|
|
|
2011-07-14 03:22:00 +08:00
|
|
|
bool isUserDeclared(ObjCIvarDecl *ivarD) const {
|
|
|
|
return ivarD && !ivarD->getSynthesize();
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType getPropertyType(PropsTy &props) const {
|
|
|
|
assert(!props.empty());
|
2011-11-07 02:58:07 +08:00
|
|
|
QualType ty = props[0].PropD->getType().getUnqualifiedType();
|
2011-07-14 03:22:00 +08:00
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
|
2011-11-07 02:58:07 +08:00
|
|
|
assert(ty == I->PropD->getType().getUnqualifiedType());
|
2011-07-14 03:22:00 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return ty;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjCPropertyDecl::PropertyAttributeKind
|
|
|
|
getPropertyAttrs(PropsTy &props) const {
|
|
|
|
assert(!props.empty());
|
|
|
|
ObjCPropertyDecl::PropertyAttributeKind
|
|
|
|
attrs = props[0].PropD->getPropertyAttributesAsWritten();
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
|
|
|
|
assert(attrs == I->PropD->getPropertyAttributesAsWritten());
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return attrs;
|
2011-06-22 04:20:39 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
2011-11-07 02:57:57 +08:00
|
|
|
void PropertyRewriteTraverser::traverseObjCImplementation(
|
|
|
|
ObjCImplementationContext &ImplCtx) {
|
2011-11-08 02:46:46 +08:00
|
|
|
PropertiesRewriter(ImplCtx.getMigrationContext())
|
2011-11-07 02:57:57 +08:00
|
|
|
.doTransform(ImplCtx.getImplementationDecl());
|
2011-06-22 04:20:39 +08:00
|
|
|
}
|