Skip to content
Snippets Groups Projects
Commit ce9b7399 authored by Argyrios Kyrtzidis's avatar Argyrios Kyrtzidis
Browse files

[arcmt] Before applying '__weak' check whether the objc class is annotated...

[arcmt] Before applying '__weak' check whether the objc class is annotated with objc_arc_weak_reference_unavailable
or is in a list of classes not supporting 'weak'.

rdar://9489367.

llvm-svn: 135002
parent c0f6af21
No related branches found
No related tags found
No related merge requests found
......@@ -98,12 +98,12 @@ public:
BlocksAttr *attr = var->getAttr<BlocksAttr>();
if(!attr)
continue;
bool hasWeak = Pass.Ctx.getLangOptions().ObjCRuntimeHasWeak;
bool useWeak = canApplyWeak(Pass.Ctx, var->getType());
SourceManager &SM = Pass.Ctx.getSourceManager();
Transaction Trans(Pass.TA);
Pass.TA.replaceText(SM.getInstantiationLoc(attr->getLocation()),
"__block",
hasWeak ? "__weak" : "__unsafe_unretained");
useWeak ? "__weak" : "__unsafe_unretained");
}
}
......
......@@ -112,7 +112,7 @@ public:
}
void applyWeak(PropData &prop) {
assert(Pass.Ctx.getLangOptions().ObjCRuntimeHasWeak);
assert(canApplyWeak(Pass.Ctx, prop.IvarD->getType()));
Transaction Trans(Pass.TA);
Pass.TA.insert(prop.IvarD->getLocation(), "__weak ");
......@@ -157,7 +157,7 @@ public:
// There is a "error: existing ivar for assign property must be
// __unsafe_unretained"; fix it.
if (!Pass.Ctx.getLangOptions().ObjCRuntimeHasWeak) {
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 ");
......
......@@ -29,6 +29,61 @@ using llvm::StringRef;
// Helpers.
//===----------------------------------------------------------------------===//
/// \brief True if the class is one that does not support weak.
static bool isClassInWeakBlacklist(ObjCInterfaceDecl *cls) {
if (!cls)
return false;
bool inList = llvm::StringSwitch<bool>(cls->getName())
.Case("NSColorSpace", true)
.Case("NSFont", true)
.Case("NSFontPanel", true)
.Case("NSImage", true)
.Case("NSLazyBrowserCell", true)
.Case("NSWindow", true)
.Case("NSWindowController", true)
.Case("NSMenuView", true)
.Case("NSPersistentUIWindowInfo", true)
.Case("NSTableCellView", true)
.Case("NSATSTypeSetter", true)
.Case("NSATSGlyphStorage", true)
.Case("NSLineFragmentRenderingContext", true)
.Case("NSAttributeDictionary", true)
.Case("NSParagraphStyle", true)
.Case("NSTextTab", true)
.Case("NSSimpleHorizontalTypesetter", true)
.Case("_NSCachedAttributedString", true)
.Case("NSStringDrawingTextStorage", true)
.Case("NSTextView", true)
.Case("NSSubTextStorage", true)
.Default(false);
if (inList)
return true;
return isClassInWeakBlacklist(cls->getSuperClass());
}
bool trans::canApplyWeak(ASTContext &Ctx, QualType type) {
if (!Ctx.getLangOptions().ObjCRuntimeHasWeak)
return false;
QualType T = type;
while (const PointerType *ptr = T->getAs<PointerType>())
T = ptr->getPointeeType();
if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) {
ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl();
if (!Class || Class->getName() == "NSObject")
return false; // id/NSObject is not safe for weak.
if (Class->isArcWeakrefUnavailable())
return false;
if (isClassInWeakBlacklist(Class))
return false;
}
return true;
}
/// \brief 'Loc' is the end of a statement range. This returns the location
/// immediately after the semicolon following the statement.
/// If no semicolon is found or the location is inside a macro, the returned
......
......@@ -44,6 +44,9 @@ void removeEmptyStatementsAndDealloc(MigrationPass &pass);
// Helpers.
//===----------------------------------------------------------------------===//
/// \brief Determine whether we can add weak to the given type.
bool canApplyWeak(ASTContext &Ctx, QualType type);
/// \brief 'Loc' is the end of a statement range. This returns the location
/// immediately after the semicolon following the statement.
/// If no semicolon is found or the location is inside a macro, the returned
......
......@@ -4,16 +4,32 @@
#include "Common.h"
__attribute__((objc_arc_weak_reference_unavailable))
@interface WeakOptOut
@end
@class _NSCachedAttributedString;
typedef _NSCachedAttributedString *BadClassForWeak;
@interface Foo : NSObject {
NSObject *x, *w, *q1, *q2;
NSObject *z1, *__unsafe_unretained z2;
Foo *x, *w, *q1, *q2;
Foo *z1, *__unsafe_unretained z2;
WeakOptOut *oo;
BadClassForWeak bcw;
id not_safe1;
NSObject *not_safe2;
}
@property (readonly,assign) id x;
@property (assign) id w;
@property (assign) id q1, q2;
@property (assign) id z1, z2;
@property (readonly,assign) Foo *x;
@property (assign) Foo *w;
@property (assign) 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;
@end
@implementation Foo
@synthesize x,w,q1,q2,z1,z2;
@synthesize x,w,q1,q2,z1,z2,oo,bcw,not_safe1,not_safe2;
@end
......@@ -4,16 +4,32 @@
#include "Common.h"
__attribute__((objc_arc_weak_reference_unavailable))
@interface WeakOptOut
@end
@class _NSCachedAttributedString;
typedef _NSCachedAttributedString *BadClassForWeak;
@interface Foo : NSObject {
NSObject *__weak x, *__weak w, *__weak q1, *__weak q2;
NSObject *__unsafe_unretained z1, *__unsafe_unretained z2;
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;
NSObject *__unsafe_unretained not_safe2;
}
@property (readonly,weak) id x;
@property (weak) id w;
@property (weak) id q1, q2;
@property (assign) id z1, z2;
@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;
@end
@implementation Foo
@synthesize x,w,q1,q2,z1,z2;
@synthesize x,w,q1,q2,z1,z2,oo,bcw,not_safe1,not_safe2;
@end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment