r230534 - Allow (Object *)kMyGlobalCFObj casts without bridging

Ben Langmuir blangmuir at apple.com
Wed Feb 25 12:09:06 PST 2015


Author: benlangmuir
Date: Wed Feb 25 14:09:06 2015
New Revision: 230534

URL: http://llvm.org/viewvc/llvm-project?rev=230534&view=rev
Log:
Allow (Object *)kMyGlobalCFObj casts without bridging

Previously we allowed these casts only for constants declared in system
headers, which we assume are retain/release-neutral. Now also allow them
for constants in user headers, treating them as +0.  Practically, this
means that we will now allow:
id x = (id)kMyGlobalConst;

But unlike with system headers we cannot mix them with +1 values:
id y = (id)(b ? kMyGlobalConst : [Obj newValAtPlusOne]); // error
id z = (id)(b ? kSystemGlobalConst: [Obj newValAtPlusOne]); // OK

Thanks to John for suggesting this improvement.

Modified:
    cfe/trunk/docs/AutomaticReferenceCounting.rst
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/test/ARCMT/nonobjc-to-objc-cast.m
    cfe/trunk/test/ARCMT/nonobjc-to-objc-cast.m.result
    cfe/trunk/test/SemaObjC/arc-dict-bridged-cast.m
    cfe/trunk/test/SemaObjC/arc-unbridged-cast.m

Modified: cfe/trunk/docs/AutomaticReferenceCounting.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/AutomaticReferenceCounting.rst?rev=230534&r1=230533&r2=230534&view=diff
==============================================================================
--- cfe/trunk/docs/AutomaticReferenceCounting.rst (original)
+++ cfe/trunk/docs/AutomaticReferenceCounting.rst Wed Feb 25 14:09:06 2015
@@ -594,7 +594,9 @@ retainable pointer type <arc.misc.c-reta
 * a message send, and the declared method either has the
   ``cf_returns_not_retained`` attribute or it has neither the
   ``cf_returns_retained`` attribute nor a :ref:`selector family
-  <arc.method-families>` that implies a retained result.
+  <arc.method-families>` that implies a retained result, or
+* :when-revised:`[beginning LLVM 3.6]` :revision:`a load from a` ``const``
+  :revision:`non-system global variable.`
 
 An expression is :arc-term:`known retained` if it is an rvalue of :ref:`C
 retainable pointer type <arc.misc.c-retainable>` and it is:
@@ -631,6 +633,12 @@ retain-agnostic, the conversion is treat
   to an ObjC-typed local, and then calling ``CFRelease`` when done  ---  are a
   bit too likely to be accidentally accepted, leading to mysterious behavior.
 
+  For loads from ``const`` global variables of :ref:`C retainable pointer type
+  <arc.misc.c-retainable>`, it is reasonable to assume that global system
+  constants were initialitzed with true constants (e.g. string literals), but
+  user constants might have been initialized with something dynamically
+  allocated, using a global initializer.
+
 .. _arc.objects.restrictions.conversion-exception-contextual:
 
 Conversion from retainable object pointer type in certain contexts

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=230534&r1=230533&r2=230534&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Wed Feb 25 14:09:06 2015
@@ -3031,17 +3031,20 @@ namespace {
 
     /// Some declaration references are okay.
     ACCResult VisitDeclRefExpr(DeclRefExpr *e) {
-      // References to global constants from system headers are okay.
-      // These are things like 'kCFStringTransformToLatin'.  They are
-      // can also be assumed to be immune to retains.
       VarDecl *var = dyn_cast<VarDecl>(e->getDecl());
+      // References to global constants are okay.
       if (isAnyRetainable(TargetClass) &&
           isAnyRetainable(SourceClass) &&
           var &&
           var->getStorageClass() == SC_Extern &&
-          var->getType().isConstQualified() &&
-          Context.getSourceManager().isInSystemHeader(var->getLocation())) {
-        return ACC_bottom;
+          var->getType().isConstQualified()) {
+
+        // In system headers, they can also be assumed to be immune to retains.
+        // These are things like 'kCFStringTransformToLatin'.
+        if (Context.getSourceManager().isInSystemHeader(var->getLocation()))
+          return ACC_bottom;
+
+        return ACC_plusZero;
       }
 
       // Nothing else.

Modified: cfe/trunk/test/ARCMT/nonobjc-to-objc-cast.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/nonobjc-to-objc-cast.m?rev=230534&r1=230533&r2=230534&view=diff
==============================================================================
--- cfe/trunk/test/ARCMT/nonobjc-to-objc-cast.m (original)
+++ cfe/trunk/test/ARCMT/nonobjc-to-objc-cast.m Wed Feb 25 14:09:06 2015
@@ -7,6 +7,7 @@
 typedef const struct __CFString * CFStringRef;
 extern const CFStringRef kUTTypePlainText;
 extern const CFStringRef kUTTypeRTF;
+extern CFStringRef kNonConst;
 
 typedef const struct __CFAllocator * CFAllocatorRef;
 typedef const struct __CFUUID * CFUUIDRef;
@@ -28,11 +29,15 @@ struct StrS {
 @end
 
 void f(BOOL b, id p) {
-  NSString *str = (NSString *)kUTTypePlainText;
-  str = b ? kUTTypeRTF : kUTTypePlainText;
-  str = (NSString *)(b ? kUTTypeRTF : kUTTypePlainText);
+  NSString *str = (NSString *)kUTTypePlainText; // no change
+  str = b ? kUTTypeRTF : kUTTypePlainText; // no change
+  str = (NSString *)(b ? kUTTypeRTF : kUTTypePlainText); // no change
   str = (NSString *)p; // no change.
 
+  str = (NSString *)kNonConst;
+  str = b ? kUTTypeRTF : kNonConst;
+  str = (NSString *)(b ? kUTTypeRTF : kNonConst);
+
   CFUUIDRef   _uuid;
   NSString *_uuidString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, _uuid);
   _uuidString = [(NSString *)CFUUIDCreateString(kCFAllocatorDefault, _uuid) autorelease];

Modified: cfe/trunk/test/ARCMT/nonobjc-to-objc-cast.m.result
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/nonobjc-to-objc-cast.m.result?rev=230534&r1=230533&r2=230534&view=diff
==============================================================================
--- cfe/trunk/test/ARCMT/nonobjc-to-objc-cast.m.result (original)
+++ cfe/trunk/test/ARCMT/nonobjc-to-objc-cast.m.result Wed Feb 25 14:09:06 2015
@@ -7,6 +7,7 @@
 typedef const struct __CFString * CFStringRef;
 extern const CFStringRef kUTTypePlainText;
 extern const CFStringRef kUTTypeRTF;
+extern CFStringRef kNonConst;
 
 typedef const struct __CFAllocator * CFAllocatorRef;
 typedef const struct __CFUUID * CFUUIDRef;
@@ -28,11 +29,15 @@ struct StrS {
 @end
 
 void f(BOOL b, id p) {
-  NSString *str = (__bridge NSString *)kUTTypePlainText;
-  str = (__bridge NSString *)(b ? kUTTypeRTF : kUTTypePlainText);
-  str = (__bridge NSString *)(b ? kUTTypeRTF : kUTTypePlainText);
+  NSString *str = (NSString *)kUTTypePlainText; // no change
+  str = b ? kUTTypeRTF : kUTTypePlainText; // no change
+  str = (NSString *)(b ? kUTTypeRTF : kUTTypePlainText); // no change
   str = (NSString *)p; // no change.
 
+  str = (__bridge NSString *)kNonConst;
+  str = (__bridge NSString *)(b ? kUTTypeRTF : kNonConst);
+  str = (__bridge NSString *)(b ? kUTTypeRTF : kNonConst);
+
   CFUUIDRef   _uuid;
   NSString *_uuidString = (NSString *)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, _uuid));
   _uuidString = (NSString *)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, _uuid));

Modified: cfe/trunk/test/SemaObjC/arc-dict-bridged-cast.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc-dict-bridged-cast.m?rev=230534&r1=230533&r2=230534&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/arc-dict-bridged-cast.m (original)
+++ cfe/trunk/test/SemaObjC/arc-dict-bridged-cast.m Wed Feb 25 14:09:06 2015
@@ -28,19 +28,12 @@ id CFBridgingRelease(CFTypeRef __attribu
 
 NSMutableString *test() {
   NSDictionary *infoDictionary;
-  infoDictionary[kCFBundleNameKey] = 0; // expected-error {{indexing expression is invalid because subscript type 'CFStringRef' (aka 'const struct __CFString *') is not an integral or Objective-C pointer type}} \
-                                        // expected-error {{implicit conversion of C pointer type 'CFStringRef' (aka 'const struct __CFString *') to Objective-C pointer type '__strong id<NSCopying>' requires a bridged cast}} \
-                                        // expected-note {{use __bridge to convert directly (no change in ownership)}} \
-                                        // expected-note {{use CFBridgingRelease call to transfer ownership of a +1 'CFStringRef' (aka 'const struct __CFString *') into ARC}}
+  infoDictionary[kCFBundleNameKey] = 0; // expected-error {{indexing expression is invalid because subscript type 'CFStringRef' (aka 'const struct __CFString *') is not an integral or Objective-C pointer type}}
   return infoDictionary[CFStringCreateMutable(((void*)0), 100)]; // expected-error {{indexing expression is invalid because subscript type 'CFMutableStringRef' (aka 'struct __CFString *') is not an integral or Objective-C pointer type}} \
                                        // expected-error {{implicit conversion of C pointer type 'CFMutableStringRef' (aka 'struct __CFString *') to Objective-C pointer type '__strong id<NSCopying>' requires a bridged cast}} \
                                         // expected-note {{use CFBridgingRelease call to transfer ownership of a +1 'CFMutableStringRef' (aka 'struct __CFString *') into ARC}}
 					
 }
 
-// CHECK: fix-it:"{{.*}}":{31:18-31:18}:"(__bridge __strong id<NSCopying>)("
-// CHECK: fix-it:"{{.*}}":{31:34-31:34}:")"
-// CHECK: fix-it:"{{.*}}":{31:18-31:18}:"CFBridgingRelease("
-// CHECK: fix-it:"{{.*}}":{31:34-31:34}:")"
-// CHECK: fix-it:"{{.*}}":{35:25-35:25}:"CFBridgingRelease("
-// CHECK: fix-it:"{{.*}}":{35:63-35:63}:")"
+// CHECK: fix-it:"{{.*}}":{32:25-32:25}:"CFBridgingRelease("
+// CHECK: fix-it:"{{.*}}":{32:63-32:63}:")"

Modified: cfe/trunk/test/SemaObjC/arc-unbridged-cast.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc-unbridged-cast.m?rev=230534&r1=230533&r2=230534&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/arc-unbridged-cast.m (original)
+++ cfe/trunk/test/SemaObjC/arc-unbridged-cast.m Wed Feb 25 14:09:06 2015
@@ -32,15 +32,20 @@ CFStringRef auditedString(void);
 CFStringRef auditedCreateString(void);
 #pragma clang arc_cf_code_audited end
 
+extern const CFStringRef kUserConst;
+
 void test1(int cond) {
   id x;
   x = (id) auditedString();
+  x = (id) kUserConst;
   x = (id) (cond ? auditedString() : (void*) 0);
   x = (id) (cond ? (void*) 0 : auditedString());
   x = (id) (cond ? (CFStringRef) @"help" : auditedString());
+  x = (id) (cond ? (CFStringRef) @"help" : kUserConst);
 
   x = (id) unauditedString(); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use CFBridgingRelease call to}}
   x = (id) (cond ? unauditedString() : (void*) 0); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use CFBridgingRelease call to}}
+  x = (id) (cond ? unauditedString() : kUserConst); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use CFBridgingRelease call to}}
   x = (id) (cond ? (void*) 0 : unauditedString()); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use CFBridgingRelease call to}}
   x = (id) (cond ? (CFStringRef) @"help" : unauditedString()); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use CFBridgingRelease call to}}
 
@@ -68,11 +73,13 @@ void test1(int cond) {
   x = (id) (cond ? [object makeString] : (void*) 0);
   x = (id) (cond ? (void*) 0 : [object makeString]);
   x = (id) (cond ? (CFStringRef) @"help" : [object makeString]);  
+  x = (id) (cond ? kUserConst : [object makeString]);
 
   x = (id) [object newString];
   x = (id) (cond ? [object newString] : (void*) 0);
   x = (id) (cond ? (void*) 0 : [object newString]);
   x = (id) (cond ? (CFStringRef) @"help" : [object newString]); // a bit questionable
+  x = (id) (cond ? kUserConst : [object newString]); // expected-error{{requires a bridged cast}} expected-note{{use __bridge to}} expected-note{{use CFBridgingRelease call to}}
 }
 
 // rdar://problem/10246264





More information about the cfe-commits mailing list