forked from OSchip/llvm-project
[arcmt] For properties rewrite 'assign' -> 'weak or unsafe_unretained', 'retain' -> 'strong', and add
'weak or unsafe_unretained' when 'assign' is missing. rdar://9496219&9602589. llvm-svn: 135065
This commit is contained in:
parent
4a40a747ba
commit
c8b3619773
|
@ -7,11 +7,14 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// changeIvarsOfAssignProperties:
|
||||
// rewriteProperties:
|
||||
//
|
||||
// If a property is synthesized with 'assign' attribute and the user didn't
|
||||
// set a lifetime attribute, change the property to 'weak' or add
|
||||
// __unsafe_unretained if the ARC runtime is not available.
|
||||
// - 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.
|
||||
//
|
||||
// @interface Foo : NSObject {
|
||||
// NSObject *x;
|
||||
|
@ -32,6 +35,7 @@
|
|||
#include "clang/Sema/SemaDiagnostic.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Lex/Lexer.h"
|
||||
#include <map>
|
||||
|
||||
using namespace clang;
|
||||
using namespace arcmt;
|
||||
|
@ -40,35 +44,36 @@ using llvm::StringRef;
|
|||
|
||||
namespace {
|
||||
|
||||
class AssignPropertiesTrans {
|
||||
class PropertiesRewriter {
|
||||
MigrationPass &Pass;
|
||||
|
||||
struct PropData {
|
||||
ObjCPropertyDecl *PropD;
|
||||
ObjCIvarDecl *IvarD;
|
||||
bool ShouldChangeToWeak;
|
||||
SourceLocation ArcPropAssignErrorLoc;
|
||||
ObjCPropertyImplDecl *ImplD;
|
||||
|
||||
PropData(ObjCPropertyDecl *propD) : PropD(propD), IvarD(0), ImplD(0) { }
|
||||
};
|
||||
|
||||
typedef llvm::SmallVector<PropData, 2> PropsTy;
|
||||
typedef llvm::DenseMap<unsigned, PropsTy> PropsMapTy;
|
||||
PropsMapTy PropsMap;
|
||||
typedef llvm::SmallVector<PropData, 2> PropsTy;
|
||||
typedef std::map<unsigned, PropsTy> AtPropDeclsTy;
|
||||
AtPropDeclsTy AtProps;
|
||||
|
||||
public:
|
||||
AssignPropertiesTrans(MigrationPass &pass) : Pass(pass) { }
|
||||
PropertiesRewriter(MigrationPass &pass) : Pass(pass) { }
|
||||
|
||||
void doTransform(ObjCImplementationDecl *D) {
|
||||
SourceManager &SM = Pass.Ctx.getSourceManager();
|
||||
ObjCInterfaceDecl *iface = D->getClassInterface();
|
||||
if (!iface)
|
||||
return;
|
||||
|
||||
ObjCInterfaceDecl *IFace = D->getClassInterface();
|
||||
for (ObjCInterfaceDecl::prop_iterator
|
||||
I = IFace->prop_begin(), E = IFace->prop_end(); I != E; ++I) {
|
||||
ObjCPropertyDecl *propD = *I;
|
||||
unsigned loc = SM.getInstantiationLoc(propD->getAtLoc()).getRawEncoding();
|
||||
PropsTy &props = PropsMap[loc];
|
||||
props.push_back(PropData());
|
||||
props.back().PropD = propD;
|
||||
props.back().IvarD = 0;
|
||||
props.back().ShouldChangeToWeak = false;
|
||||
propI = iface->prop_begin(),
|
||||
propE = iface->prop_end(); propI != propE; ++propI) {
|
||||
if (propI->getAtLoc().isInvalid())
|
||||
continue;
|
||||
PropsTy &props = AtProps[propI->getAtLoc().getRawEncoding()];
|
||||
props.push_back(*propI);
|
||||
}
|
||||
|
||||
typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl>
|
||||
|
@ -76,111 +81,117 @@ public:
|
|||
for (prop_impl_iterator
|
||||
I = prop_impl_iterator(D->decls_begin()),
|
||||
E = prop_impl_iterator(D->decls_end()); I != E; ++I) {
|
||||
VisitObjCPropertyImplDecl(*I);
|
||||
}
|
||||
|
||||
for (PropsMapTy::iterator
|
||||
I = PropsMap.begin(), E = PropsMap.end(); I != E; ++I) {
|
||||
SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
|
||||
PropsTy &props = I->second;
|
||||
if (shouldApplyWeakToAllProp(props)) {
|
||||
if (changeAssignToWeak(atLoc)) {
|
||||
// Couldn't add the 'weak' property attribute,
|
||||
// try adding __unsafe_unretained.
|
||||
applyUnsafeUnretained(props);
|
||||
} else {
|
||||
for (PropsTy::iterator
|
||||
PI = props.begin(), PE = props.end(); PI != PE; ++PI) {
|
||||
applyWeak(*PI);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We should not add 'weak' attribute since not all properties need it.
|
||||
// So just add __unsafe_unretained to the ivars.
|
||||
applyUnsafeUnretained(props);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool shouldApplyWeakToAllProp(PropsTy &props) {
|
||||
for (PropsTy::iterator
|
||||
PI = props.begin(), PE = props.end(); PI != PE; ++PI) {
|
||||
if (!PI->ShouldChangeToWeak)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void applyWeak(PropData &prop) {
|
||||
assert(canApplyWeak(Pass.Ctx, prop.IvarD->getType()));
|
||||
|
||||
Transaction Trans(Pass.TA);
|
||||
Pass.TA.insert(prop.IvarD->getLocation(), "__weak ");
|
||||
Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
|
||||
prop.ArcPropAssignErrorLoc);
|
||||
}
|
||||
|
||||
void applyUnsafeUnretained(PropsTy &props) {
|
||||
for (PropsTy::iterator
|
||||
PI = props.begin(), PE = props.end(); PI != PE; ++PI) {
|
||||
if (PI->ShouldChangeToWeak) {
|
||||
Transaction Trans(Pass.TA);
|
||||
Pass.TA.insert(PI->IvarD->getLocation(), "__unsafe_unretained ");
|
||||
Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
|
||||
PI->ArcPropAssignErrorLoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
|
||||
SourceManager &SM = Pass.Ctx.getSourceManager();
|
||||
|
||||
if (D->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
|
||||
return true;
|
||||
ObjCPropertyDecl *propD = D->getPropertyDecl();
|
||||
if (!propD || propD->isInvalidDecl())
|
||||
return true;
|
||||
ObjCIvarDecl *ivarD = D->getPropertyIvarDecl();
|
||||
if (!ivarD || ivarD->isInvalidDecl())
|
||||
return true;
|
||||
if (!(propD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign))
|
||||
return true;
|
||||
if (isa<AttributedType>(ivarD->getType().getTypePtr()))
|
||||
return true;
|
||||
if (ivarD->getType().getLocalQualifiers().getObjCLifetime()
|
||||
!= Qualifiers::OCL_Strong)
|
||||
return true;
|
||||
if (!Pass.TA.hasDiagnostic(
|
||||
diag::err_arc_assign_property_ownership, D->getLocation()))
|
||||
return true;
|
||||
|
||||
// There is a "error: existing ivar for assign property must be
|
||||
// __unsafe_unretained"; fix it.
|
||||
|
||||
if (!canApplyWeak(Pass.Ctx, ivarD->getType())) {
|
||||
// We will just add __unsafe_unretained to the ivar.
|
||||
Transaction Trans(Pass.TA);
|
||||
Pass.TA.insert(ivarD->getLocation(), "__unsafe_unretained ");
|
||||
Pass.TA.clearDiagnostic(
|
||||
diag::err_arc_assign_property_ownership, D->getLocation());
|
||||
} else {
|
||||
// Mark that we want the ivar to become weak.
|
||||
unsigned loc = SM.getInstantiationLoc(propD->getAtLoc()).getRawEncoding();
|
||||
PropsTy &props = PropsMap[loc];
|
||||
ObjCPropertyImplDecl *implD = *I;
|
||||
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->ShouldChangeToWeak = true;
|
||||
I->ArcPropAssignErrorLoc = D->getLocation();
|
||||
I->ImplD = implD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
for (AtPropDeclsTy::iterator
|
||||
I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
|
||||
SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
|
||||
PropsTy &props = I->second;
|
||||
QualType ty = getPropertyType(props);
|
||||
if (!ty->isObjCRetainableType())
|
||||
continue;
|
||||
if (hasIvarWithExplicitOwnership(props))
|
||||
continue;
|
||||
|
||||
Transaction Trans(Pass.TA);
|
||||
rewriteProperty(props, atLoc);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool changeAssignToWeak(SourceLocation atLoc) {
|
||||
void rewriteProperty(PropsTy &props, SourceLocation atLoc) const {
|
||||
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) {
|
||||
rewriteAttribute("retain", "strong", atLoc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (propAttrs & ObjCPropertyDecl::OBJC_PR_assign)
|
||||
return rewriteAssign(props, atLoc);
|
||||
|
||||
return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
|
||||
}
|
||||
|
||||
void rewriteAssign(PropsTy &props, SourceLocation atLoc) const {
|
||||
bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props));
|
||||
|
||||
bool rewroteAttr = rewriteAttribute("assign",
|
||||
canUseWeak ? "weak" : "unsafe_unretained",
|
||||
atLoc);
|
||||
if (!rewroteAttr)
|
||||
canUseWeak = false;
|
||||
|
||||
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
|
||||
if (isUserDeclared(I->IvarD))
|
||||
Pass.TA.insert(I->IvarD->getLocation(),
|
||||
canUseWeak ? "__weak " : "__unsafe_unretained ");
|
||||
if (I->ImplD)
|
||||
Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
|
||||
I->ImplD->getLocation());
|
||||
}
|
||||
}
|
||||
|
||||
void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
|
||||
SourceLocation atLoc) const {
|
||||
ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
|
||||
if ((propAttrs & ObjCPropertyDecl::OBJC_PR_readonly) &&
|
||||
hasNoBackingIvars(props))
|
||||
return;
|
||||
|
||||
bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props));
|
||||
bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained",
|
||||
atLoc);
|
||||
if (!addedAttr)
|
||||
canUseWeak = false;
|
||||
|
||||
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
|
||||
if (isUserDeclared(I->IvarD))
|
||||
Pass.TA.insert(I->IvarD->getLocation(),
|
||||
canUseWeak ? "__weak " : "__unsafe_unretained ");
|
||||
if (I->ImplD) {
|
||||
Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
|
||||
I->ImplD->getLocation());
|
||||
Pass.TA.clearDiagnostic(
|
||||
diag::err_arc_objc_property_default_assign_on_object,
|
||||
I->ImplD->getLocation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool rewriteAttribute(llvm::StringRef fromAttr, llvm::StringRef toAttr,
|
||||
SourceLocation atLoc) const {
|
||||
if (atLoc.isMacroID())
|
||||
return false;
|
||||
|
||||
SourceManager &SM = Pass.Ctx.getSourceManager();
|
||||
|
||||
// Break down the source location.
|
||||
|
@ -190,7 +201,7 @@ private:
|
|||
bool invalidTemp = false;
|
||||
llvm::StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
|
||||
if (invalidTemp)
|
||||
return true;
|
||||
return false;
|
||||
|
||||
const char *tokenBegin = file.data() + locInfo.second;
|
||||
|
||||
|
@ -200,61 +211,154 @@ private:
|
|||
file.begin(), tokenBegin, file.end());
|
||||
Token tok;
|
||||
lexer.LexFromRawLexer(tok);
|
||||
if (tok.isNot(tok::at)) return true;
|
||||
if (tok.isNot(tok::at)) return false;
|
||||
lexer.LexFromRawLexer(tok);
|
||||
if (tok.isNot(tok::raw_identifier)) return true;
|
||||
if (tok.isNot(tok::raw_identifier)) return false;
|
||||
if (llvm::StringRef(tok.getRawIdentifierData(), tok.getLength())
|
||||
!= "property")
|
||||
return true;
|
||||
return false;
|
||||
lexer.LexFromRawLexer(tok);
|
||||
if (tok.isNot(tok::l_paren)) return true;
|
||||
if (tok.isNot(tok::l_paren)) return false;
|
||||
|
||||
SourceLocation LParen = tok.getLocation();
|
||||
SourceLocation assignLoc;
|
||||
bool isEmpty = false;
|
||||
lexer.LexFromRawLexer(tok);
|
||||
if (tok.is(tok::r_paren))
|
||||
return false;
|
||||
|
||||
while (1) {
|
||||
if (tok.isNot(tok::raw_identifier)) return false;
|
||||
llvm::StringRef ident(tok.getRawIdentifierData(), tok.getLength());
|
||||
if (ident == fromAttr) {
|
||||
Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr);
|
||||
return true;
|
||||
}
|
||||
|
||||
do {
|
||||
lexer.LexFromRawLexer(tok);
|
||||
} while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren));
|
||||
if (tok.is(tok::r_paren))
|
||||
break;
|
||||
lexer.LexFromRawLexer(tok);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool addAttribute(llvm::StringRef attr, SourceLocation atLoc) const {
|
||||
if (atLoc.isMacroID())
|
||||
return false;
|
||||
|
||||
SourceManager &SM = Pass.Ctx.getSourceManager();
|
||||
|
||||
// Break down the source location.
|
||||
std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
|
||||
|
||||
// Try to load the file buffer.
|
||||
bool invalidTemp = false;
|
||||
llvm::StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
|
||||
if (invalidTemp)
|
||||
return false;
|
||||
|
||||
const char *tokenBegin = file.data() + locInfo.second;
|
||||
|
||||
// Lex from the start of the given location.
|
||||
Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
|
||||
Pass.Ctx.getLangOptions(),
|
||||
file.begin(), tokenBegin, file.end());
|
||||
Token tok;
|
||||
lexer.LexFromRawLexer(tok);
|
||||
if (tok.isNot(tok::at)) return false;
|
||||
lexer.LexFromRawLexer(tok);
|
||||
if (tok.isNot(tok::raw_identifier)) return false;
|
||||
if (llvm::StringRef(tok.getRawIdentifierData(), tok.getLength())
|
||||
!= "property")
|
||||
return false;
|
||||
lexer.LexFromRawLexer(tok);
|
||||
|
||||
if (tok.isNot(tok::l_paren)) {
|
||||
Pass.TA.insert(tok.getLocation(), std::string("(") + attr.str() + ") ");
|
||||
return true;
|
||||
}
|
||||
|
||||
lexer.LexFromRawLexer(tok);
|
||||
if (tok.is(tok::r_paren)) {
|
||||
isEmpty = true;
|
||||
} else {
|
||||
while (1) {
|
||||
if (tok.isNot(tok::raw_identifier)) return true;
|
||||
llvm::StringRef ident(tok.getRawIdentifierData(), tok.getLength());
|
||||
if (ident == "assign")
|
||||
assignLoc = tok.getLocation();
|
||||
|
||||
do {
|
||||
lexer.LexFromRawLexer(tok);
|
||||
} while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren));
|
||||
if (tok.is(tok::r_paren))
|
||||
break;
|
||||
lexer.LexFromRawLexer(tok);
|
||||
Pass.TA.insert(tok.getLocation(), attr);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tok.isNot(tok::raw_identifier)) return false;
|
||||
|
||||
Pass.TA.insert(tok.getLocation(), std::string(attr) + ", ");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hasIvarWithExplicitOwnership(PropsTy &props) const {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Transaction Trans(Pass.TA);
|
||||
if (assignLoc.isValid())
|
||||
Pass.TA.replaceText(assignLoc, "assign", "weak");
|
||||
else
|
||||
Pass.TA.insertAfterToken(LParen, isEmpty ? "weak" : "weak, ");
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hasNoBackingIvars(PropsTy &props) const {
|
||||
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
|
||||
if (isUserDeclared(I->IvarD))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isUserDeclared(ObjCIvarDecl *ivarD) const {
|
||||
return ivarD && !ivarD->getSynthesize();
|
||||
}
|
||||
|
||||
QualType getPropertyType(PropsTy &props) const {
|
||||
assert(!props.empty());
|
||||
QualType ty = props[0].PropD->getType();
|
||||
|
||||
#ifndef NDEBUG
|
||||
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
|
||||
assert(ty == I->PropD->getType());
|
||||
#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;
|
||||
}
|
||||
};
|
||||
|
||||
class PropertiesChecker : public RecursiveASTVisitor<PropertiesChecker> {
|
||||
class ImplementationChecker :
|
||||
public RecursiveASTVisitor<ImplementationChecker> {
|
||||
MigrationPass &Pass;
|
||||
|
||||
public:
|
||||
PropertiesChecker(MigrationPass &pass) : Pass(pass) { }
|
||||
ImplementationChecker(MigrationPass &pass) : Pass(pass) { }
|
||||
|
||||
bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) {
|
||||
AssignPropertiesTrans(Pass).doTransform(D);
|
||||
PropertiesRewriter(Pass).doTransform(D);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void trans::changeIvarsOfAssignProperties(MigrationPass &pass) {
|
||||
PropertiesChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
|
||||
void trans::rewriteProperties(MigrationPass &pass) {
|
||||
ImplementationChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
|
||||
}
|
||||
|
|
|
@ -265,7 +265,7 @@ void trans::collectRemovables(Stmt *S, ExprSet &exprs) {
|
|||
|
||||
static void independentTransforms(MigrationPass &pass) {
|
||||
rewriteAutoreleasePool(pass);
|
||||
changeIvarsOfAssignProperties(pass);
|
||||
rewriteProperties(pass);
|
||||
removeRetainReleaseDealloc(pass);
|
||||
rewriteUnusedInitDelegate(pass);
|
||||
removeZeroOutPropsInDealloc(pass);
|
||||
|
|
|
@ -34,7 +34,7 @@ void rewriteUnbridgedCasts(MigrationPass &pass);
|
|||
void makeAssignARCSafe(MigrationPass &pass);
|
||||
void removeRetainReleaseDealloc(MigrationPass &pass);
|
||||
void removeZeroOutPropsInDealloc(MigrationPass &pass);
|
||||
void changeIvarsOfAssignProperties(MigrationPass &pass);
|
||||
void rewriteProperties(MigrationPass &pass);
|
||||
void rewriteBlockObjCVariable(MigrationPass &pass);
|
||||
void rewriteUnusedInitDelegate(MigrationPass &pass);
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
@interface Foo : NSObject {
|
||||
NSObject *__unsafe_unretained x;
|
||||
}
|
||||
@property (readonly,assign) id x;
|
||||
@property (readonly,unsafe_unretained) id x;
|
||||
@end
|
||||
|
||||
@implementation Foo
|
||||
|
|
|
@ -15,7 +15,6 @@ typedef _NSCachedAttributedString *BadClassForWeak;
|
|||
|
||||
@interface Foo : NSObject {
|
||||
Foo *x, *w, *q1, *q2;
|
||||
Foo *z1, *__unsafe_unretained z2;
|
||||
WeakOptOut *oo;
|
||||
BadClassForWeak bcw;
|
||||
id not_safe1;
|
||||
|
@ -24,15 +23,17 @@ typedef _NSCachedAttributedString *BadClassForWeak;
|
|||
}
|
||||
@property (readonly,assign) Foo *x;
|
||||
@property (assign) Foo *w;
|
||||
@property (assign) Foo *q1, *q2;
|
||||
@property (assign) Foo *z1, *z2;
|
||||
@property Foo *q1, *q2;
|
||||
@property (assign) WeakOptOut *oo;
|
||||
@property (assign) BadClassForWeak bcw;
|
||||
@property (assign) id not_safe1;
|
||||
@property (assign) NSObject *not_safe2;
|
||||
@property (assign) Forw *not_safe3;
|
||||
@property () NSObject *not_safe2;
|
||||
@property Forw *not_safe3;
|
||||
|
||||
@property (assign) Foo *no_back_ivar;
|
||||
@end
|
||||
|
||||
@implementation Foo
|
||||
@synthesize x,w,q1,q2,z1,z2,oo,bcw,not_safe1,not_safe2,not_safe3;
|
||||
@synthesize x,w,q1,q2,oo,bcw,not_safe1,not_safe2,not_safe3;
|
||||
@synthesize no_back_ivar;
|
||||
@end
|
||||
|
|
|
@ -15,7 +15,6 @@ typedef _NSCachedAttributedString *BadClassForWeak;
|
|||
|
||||
@interface Foo : NSObject {
|
||||
Foo *__weak x, *__weak w, *__weak q1, *__weak q2;
|
||||
Foo *__unsafe_unretained z1, *__unsafe_unretained z2;
|
||||
WeakOptOut *__unsafe_unretained oo;
|
||||
BadClassForWeak __unsafe_unretained bcw;
|
||||
id __unsafe_unretained not_safe1;
|
||||
|
@ -25,14 +24,16 @@ typedef _NSCachedAttributedString *BadClassForWeak;
|
|||
@property (readonly,weak) Foo *x;
|
||||
@property (weak) Foo *w;
|
||||
@property (weak) Foo *q1, *q2;
|
||||
@property (assign) Foo *z1, *z2;
|
||||
@property (assign) WeakOptOut *oo;
|
||||
@property (assign) BadClassForWeak bcw;
|
||||
@property (assign) id not_safe1;
|
||||
@property (assign) NSObject *not_safe2;
|
||||
@property (assign) Forw *not_safe3;
|
||||
@property (unsafe_unretained) WeakOptOut *oo;
|
||||
@property (unsafe_unretained) BadClassForWeak bcw;
|
||||
@property (unsafe_unretained) id not_safe1;
|
||||
@property (unsafe_unretained) NSObject *not_safe2;
|
||||
@property (unsafe_unretained) Forw *not_safe3;
|
||||
|
||||
@property (weak) Foo *no_back_ivar;
|
||||
@end
|
||||
|
||||
@implementation Foo
|
||||
@synthesize x,w,q1,q2,z1,z2,oo,bcw,not_safe1,not_safe2,not_safe3;
|
||||
@synthesize x,w,q1,q2,oo,bcw,not_safe1,not_safe2,not_safe3;
|
||||
@synthesize no_back_ivar;
|
||||
@end
|
||||
|
|
|
@ -20,7 +20,7 @@ id IhaveSideEffect();
|
|||
@interface Foo : NSObject {
|
||||
id bar;
|
||||
}
|
||||
@property (retain) id bar;
|
||||
@property (strong) id bar;
|
||||
-(void)test:(id)obj;
|
||||
@end
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ id IhaveSideEffect();
|
|||
@interface Foo : NSObject {
|
||||
id bar;
|
||||
}
|
||||
@property (retain) id bar;
|
||||
@property (strong) id bar;
|
||||
-(void)test:(id)obj;
|
||||
@end
|
||||
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
#define nil ((void*) 0)
|
||||
|
||||
@interface Foo
|
||||
@property (retain) id x;
|
||||
@property (retain) id y;
|
||||
@property (retain) id w;
|
||||
@property (retain) id z;
|
||||
@property (strong) id x;
|
||||
@property (strong) id y;
|
||||
@property (strong) id w;
|
||||
@property (strong) id z;
|
||||
@end
|
||||
|
||||
@implementation Foo
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
// RUN: diff %t %s.result
|
||||
|
||||
@interface Foo
|
||||
@property (retain) id x;
|
||||
@property (retain) id y;
|
||||
@property (retain) id w;
|
||||
@property (retain) id z;
|
||||
@property (strong) id x;
|
||||
@property (strong) id y;
|
||||
@property (strong) id w;
|
||||
@property (strong) id z;
|
||||
@property (strong) id q;
|
||||
@end
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
|||
@end
|
||||
|
||||
@interface Bar
|
||||
@property (retain) Foo *a;
|
||||
@property (strong) Foo *a;
|
||||
- (void) setA:(Foo*) val;
|
||||
- (id) a;
|
||||
@end
|
||||
|
|
|
@ -9,7 +9,7 @@ id IhaveSideEffect();
|
|||
@interface Foo : NSObject {
|
||||
id bar;
|
||||
}
|
||||
@property (retain) id bar;
|
||||
@property (strong) id bar;
|
||||
-(id)test:(id)obj;
|
||||
-(id)something;
|
||||
@end
|
||||
|
|
Loading…
Reference in New Issue