ahatanak created this revision.

ARCCastChecker::VisitDeclRefExpr allows casting a constant pointer declared in 
a header file to an ObjC pointer type. However, it rejects a cast from a 
variable declared with a language linkage specification (e.g., extern "C") to 
an ObjC pointer type.

According to the standard, declarations directly contained in a language 
linkage specification (single line "extern C") are treated as if they contain 
the extern specifier for the purpose of determining whether they are 
definitions, so such variables should be treated as declarations unless they 
have initializers.

This patch replaces the call to VarDecl::getStorageClass (which returns SC_None 
for extern "C" variables) with a call to VarDecl::isThisDeclarationADefinition 
to detect variable declarations more precisely.

rdar://problem/29249853


https://reviews.llvm.org/D31673

Files:
  lib/Sema/SemaExprObjC.cpp
  test/SemaObjCXX/arc-bridged-cast.mm


Index: test/SemaObjCXX/arc-bridged-cast.mm
===================================================================
--- test/SemaObjCXX/arc-bridged-cast.mm
+++ test/SemaObjCXX/arc-bridged-cast.mm
@@ -52,3 +52,16 @@
   ref = (__bridge_retained CFAnnotatedObjectRef) CreateSomething();
   ref = (__bridge_retained CFAnnotatedObjectRef) CreateNSString();
 }
+
+extern const CFAnnotatedObjectRef r0;
+extern const CFAnnotatedObjectRef r1 = 0;
+extern "C" const CFAnnotatedObjectRef r2;
+extern "C" const CFAnnotatedObjectRef r3 = 0;
+
+void testExternC() {
+  id obj;
+  obj = (id)r0;
+  obj = (id)r1; // expected-error{{cast of C pointer type 
'CFAnnotatedObjectRef' (aka 'const __CFAnnotatedObject *') to Objective-C 
pointer type 'id' requires a bridged cast}} expected-note{{use __bridge to 
convert directly}} expected-note{{use __bridge_transfer to transfer ownership 
of a +1 'CFAnnotatedObjectRef'}}
+  obj = (id)r2;
+  obj = (id)r3; // expected-error{{cast of C pointer type 
'CFAnnotatedObjectRef' (aka 'const __CFAnnotatedObject *') to Objective-C 
pointer type 'id' requires a bridged cast}} expected-note{{use __bridge to 
convert directly}} expected-note{{use __bridge_transfer to transfer ownership 
of a +1 'CFAnnotatedObjectRef'}}
+}
Index: lib/Sema/SemaExprObjC.cpp
===================================================================
--- lib/Sema/SemaExprObjC.cpp
+++ lib/Sema/SemaExprObjC.cpp
@@ -3355,7 +3355,7 @@
       if (isAnyRetainable(TargetClass) &&
           isAnyRetainable(SourceClass) &&
           var &&
-          var->getStorageClass() == SC_Extern &&
+          !var->isThisDeclarationADefinition() &&
           var->getType().isConstQualified()) {
 
         // In system headers, they can also be assumed to be immune to retains.


Index: test/SemaObjCXX/arc-bridged-cast.mm
===================================================================
--- test/SemaObjCXX/arc-bridged-cast.mm
+++ test/SemaObjCXX/arc-bridged-cast.mm
@@ -52,3 +52,16 @@
   ref = (__bridge_retained CFAnnotatedObjectRef) CreateSomething();
   ref = (__bridge_retained CFAnnotatedObjectRef) CreateNSString();
 }
+
+extern const CFAnnotatedObjectRef r0;
+extern const CFAnnotatedObjectRef r1 = 0;
+extern "C" const CFAnnotatedObjectRef r2;
+extern "C" const CFAnnotatedObjectRef r3 = 0;
+
+void testExternC() {
+  id obj;
+  obj = (id)r0;
+  obj = (id)r1; // expected-error{{cast of C pointer type 'CFAnnotatedObjectRef' (aka 'const __CFAnnotatedObject *') to Objective-C pointer type 'id' requires a bridged cast}} expected-note{{use __bridge to convert directly}} expected-note{{use __bridge_transfer to transfer ownership of a +1 'CFAnnotatedObjectRef'}}
+  obj = (id)r2;
+  obj = (id)r3; // expected-error{{cast of C pointer type 'CFAnnotatedObjectRef' (aka 'const __CFAnnotatedObject *') to Objective-C pointer type 'id' requires a bridged cast}} expected-note{{use __bridge to convert directly}} expected-note{{use __bridge_transfer to transfer ownership of a +1 'CFAnnotatedObjectRef'}}
+}
Index: lib/Sema/SemaExprObjC.cpp
===================================================================
--- lib/Sema/SemaExprObjC.cpp
+++ lib/Sema/SemaExprObjC.cpp
@@ -3355,7 +3355,7 @@
       if (isAnyRetainable(TargetClass) &&
           isAnyRetainable(SourceClass) &&
           var &&
-          var->getStorageClass() == SC_Extern &&
+          !var->isThisDeclarationADefinition() &&
           var->getType().isConstQualified()) {
 
         // In system headers, they can also be assumed to be immune to retains.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to