If i understood correctly we could classify void * as a "C retainable pointer type".
So, assigning it to an Objective-C object will be implicitly bridged. However, compiler raises error that explicit bridging is required.
const void * somePtr = (void *)0x12345678;
- (void)someMethod:(id)sender
{
NSObject *obj = (NSObject *)somePtr;
}
Also, i checked the null pointer constant and it compiles without explicit bridging.
NSObject *obj = (void *)0;
I am using XCode 4.5(Clang 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)).
Question:
I know it's a little bit weird to assign some arbitrary/irrelevant pointer to NSObject but i want to make sure if am correctly understanding the rules. I am little bit suspicious about the "C retainable pointer type". description; especially about the intention of (possibly qualified) and (possibly qualifier). What pointer types could we classify as "C retainable pointer type"?
Also, does it actually mean a global variable from system by the "system global variable" statement?
3.3.2. Conversion to retainable object pointer type of expressions with known semantics [beginning Apple 4.0, LLVM 3.1]
An expression is known retain-agnostic if it is:
- an Objective-C string literal,
- a load from a const system global variable of C retainable pointer type,
- or a null pointer constant.
If the cast operand is known unretained or known retain-agnostic, the conversion is treated as a __bridge cast.
7.8. C retainable pointer types
A type is a C retainable pointer type if it is a pointer to (possibly qualified) void or a pointer to a (possibly qualifier) struct or class type.
http://clang.llvm.org/docs/AutomaticReferenceCounting.html
Although it's not stated in the document you linked, I believe the “system” part of “a const
system global variable” means the variable was defined while the pragma clang arc_cf_code_audited
was in effect.
Take a look at the top of CFNumber.h
and you will find this:
CF_IMPLICIT_BRIDGING_ENABLED
and near the end you will find this:
CF_IMPLICIT_BRIDGING_DISABLED
These macros are defined in CFBase.h
to begin and end the clang arc_cf_code_audited
pragma, it it's defined.
It seems that const system global variables actually do not require explicit bridging.
i.e. kCFBooleanTrue(CFBoolean instance), kCFNumberNaN or kABPersonPhoneMobileLabel.
NSObject *obj = (NSObject *)kCFBooleanTrue;
Note that CFBoolean is not toll free bridged but it could be still implicitly bridged by compiler.
I define global constants but could not get them compiled with implicit bridging.
So, i wonder how could compiler determine if a variable comes from system or not?
(Or may be it is checking if type comes from CoreFoundation.framework which is not a neat solution...)
--- EDIT ---
Referring to rob mayoff's answer, i tried implicit bridging but it still did not work. May be there is a compiler flag to determine the file as a Core Foundation file.
NSObject *obj = (NSObject *)myGlobal;
"mytest.h" File
#ifndef mytest_h
#define mytest_h
#pragma clang arc_cf_code_audited begin
typedef const struct MyStruct * MyStructPtr;
CF_EXPORT
const MyStructPtr myGlobal;
#pragma clang arc_cf_code_audited end
#endif
"mytest.c" File
#include "mytest.h"
struct MyStruct {
int a;
};
static struct MyStruct __myglobal = { 123 };
const MyStructPtr myGlobal = &__myglobal;
--- EDIT ---
I also modified the CFNumber.h header file in CoreFoundation.framework and removed CF_IMPLICIT_BRIDGING_ENABLED/CF_IMPLICIT_BRIDGING_DISABLED, then clean/build the project and yet it did not disable implicit bridging for those constants.