ARC - implicit bridging

2019-04-09 09:32发布

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

2条回答
在下西门庆
2楼-- · 2019-04-09 10:19

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.

查看更多
该账号已被封号
3楼-- · 2019-04-09 10:21

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.

查看更多
登录 后发表回答