]> granicus.if.org Git - clang/commitdiff
[arcmt] Before applying '__weak' check whether the objc class is annotated with objc_...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 12 Jul 2011 22:05:17 +0000 (22:05 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 12 Jul 2011 22:05:17 +0000 (22:05 +0000)
or is in a list of classes not supporting 'weak'.

rdar://9489367.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@135002 91177308-0d34-0410-b5e6-96231b3b80d8

lib/ARCMigrate/TransBlockObjCVariable.cpp
lib/ARCMigrate/TransProperties.cpp
lib/ARCMigrate/Transforms.cpp
lib/ARCMigrate/Transforms.h
test/ARCMT/assign-prop-with-arc-runtime.m
test/ARCMT/assign-prop-with-arc-runtime.m.result

index 97695cbccfa580b59d526b336719f3e6c3daf179..0e342b7a8f8c443914d6b669307ec347f9b16d30 100644 (file)
@@ -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");
       }
 
     }
index 0efc4c0fadf0113803123d3a50b239940544cb8d..82ef717f31558713d22bcca18c8b086a0e08e30a 100644 (file)
@@ -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 ");
index 546829120c06880cffd95809cda5e1270094cfea..c2f85f65b76b0ac45c91a6e84184d8a8a518d875 100644 (file)
@@ -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
index 21064973bf71607eb25e6eca6d52950fdc30a856..d52fba013078dfd1fd9f8647e596fb4003257d5e 100644 (file)
@@ -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
index 8d9f21115c5365c07f0a932b20ed748a5ca23ce8..e9416fe029291ad4b846787b1edf0114322c6fce 100644 (file)
@@ -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
index 2d74ae2ed9f7d8bf9551e11e69e1f7b929132872..349bfa28c45d8192d7eade6b2bcd4d44fec29d7f 100644 (file)
@@ -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