[Sema][ObjC] Check whether a variable has a definition, rather than

checking its storage class, when determining whether casting a C pointer
to an ObjC pointer is allowed.

This change allows casting variables whose declarations are directly
contained in a linkage specification to an ObjC pointer type. Those
variables are treated as if they contain the extern specifier for the
purpose of determining whether they are definitions or not.

rdar://problem/29249853

Differential Revision: https://reviews.llvm.org/D31673

llvm-svn: 299992
This commit is contained in:
Akira Hatanaka 2017-04-11 22:01:33 +00:00
parent caf24d2b6c
commit ad51539597
2 changed files with 17 additions and 1 deletions

View File

@ -3355,7 +3355,7 @@ namespace {
if (isAnyRetainable(TargetClass) && if (isAnyRetainable(TargetClass) &&
isAnyRetainable(SourceClass) && isAnyRetainable(SourceClass) &&
var && var &&
var->getStorageClass() == SC_Extern && !var->hasDefinition(Context) &&
var->getType().isConstQualified()) { var->getType().isConstQualified()) {
// In system headers, they can also be assumed to be immune to retains. // In system headers, they can also be assumed to be immune to retains.

View File

@ -52,3 +52,19 @@ void testObjCBridgeId() {
ref = (__bridge_retained CFAnnotatedObjectRef) CreateSomething(); ref = (__bridge_retained CFAnnotatedObjectRef) CreateSomething();
ref = (__bridge_retained CFAnnotatedObjectRef) CreateNSString(); ref = (__bridge_retained CFAnnotatedObjectRef) CreateNSString();
} }
struct __CFAnnotatedObject {
} cf0;
extern const CFAnnotatedObjectRef r0;
extern const CFAnnotatedObjectRef r1 = &cf0;
extern "C" const CFAnnotatedObjectRef r2;
extern "C" const CFAnnotatedObjectRef r3 = &cf0;
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'}}
}