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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits