diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/ARCMigrate/TransBlockObjCVariable.cpp | 4 | ||||
-rw-r--r-- | clang/lib/ARCMigrate/TransProperties.cpp | 4 | ||||
-rw-r--r-- | clang/lib/ARCMigrate/Transforms.cpp | 55 | ||||
-rw-r--r-- | clang/lib/ARCMigrate/Transforms.h | 3 | ||||
-rw-r--r-- | clang/test/ARCMT/assign-prop-with-arc-runtime.m | 30 | ||||
-rw-r--r-- | clang/test/ARCMT/assign-prop-with-arc-runtime.m.result | 30 |
6 files changed, 108 insertions, 18 deletions
diff --git a/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp b/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp index 97695cbccfa..0e342b7a8f8 100644 --- a/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp +++ b/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp @@ -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"); } } diff --git a/clang/lib/ARCMigrate/TransProperties.cpp b/clang/lib/ARCMigrate/TransProperties.cpp index 0efc4c0fadf..82ef717f315 100644 --- a/clang/lib/ARCMigrate/TransProperties.cpp +++ b/clang/lib/ARCMigrate/TransProperties.cpp @@ -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 "); diff --git a/clang/lib/ARCMigrate/Transforms.cpp b/clang/lib/ARCMigrate/Transforms.cpp index 546829120c0..c2f85f65b76 100644 --- a/clang/lib/ARCMigrate/Transforms.cpp +++ b/clang/lib/ARCMigrate/Transforms.cpp @@ -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 diff --git a/clang/lib/ARCMigrate/Transforms.h b/clang/lib/ARCMigrate/Transforms.h index 21064973bf7..d52fba01307 100644 --- a/clang/lib/ARCMigrate/Transforms.h +++ b/clang/lib/ARCMigrate/Transforms.h @@ -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 diff --git a/clang/test/ARCMT/assign-prop-with-arc-runtime.m b/clang/test/ARCMT/assign-prop-with-arc-runtime.m index 8d9f21115c5..e9416fe0292 100644 --- a/clang/test/ARCMT/assign-prop-with-arc-runtime.m +++ b/clang/test/ARCMT/assign-prop-with-arc-runtime.m @@ -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 diff --git a/clang/test/ARCMT/assign-prop-with-arc-runtime.m.result b/clang/test/ARCMT/assign-prop-with-arc-runtime.m.result index 2d74ae2ed9f..349bfa28c45 100644 --- a/clang/test/ARCMT/assign-prop-with-arc-runtime.m.result +++ b/clang/test/ARCMT/assign-prop-with-arc-runtime.m.result @@ -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 |