From 1e36882b5291d5a7209be4f9c99b9713828afac4 Mon Sep 17 00:00:00 2001 From: Erik Pilkington Date: Fri, 4 Jan 2019 18:33:06 +0000 Subject: [ObjCARC] Add an new attribute, objc_externally_retained This attribute, called "objc_externally_retained", exposes clang's notion of pseudo-__strong variables in ARC. Pseudo-strong variables "borrow" their initializer, meaning that they don't retain/release it, instead assuming that someone else is keeping their value alive. If a function is annotated with this attribute, implicitly strong parameters of that function aren't implicitly retained/released in the function body, and are implicitly const. This is useful to expose for performance reasons, most functions don't need the extra safety of the retain/release, so programmers can opt out as needed. This attribute can also apply to declarations of local variables, with similar effect. Differential revision: https://reviews.llvm.org/D55865 llvm-svn: 350422 --- clang/docs/AutomaticReferenceCounting.rst | 87 ++++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 14 deletions(-) (limited to 'clang/docs') diff --git a/clang/docs/AutomaticReferenceCounting.rst b/clang/docs/AutomaticReferenceCounting.rst index d8cda0c05f9e..3e51d2f5d79e 100644 --- a/clang/docs/AutomaticReferenceCounting.rst +++ b/clang/docs/AutomaticReferenceCounting.rst @@ -1734,20 +1734,78 @@ A program is ill-formed if it refers to the ``NSAutoreleasePool`` class. rest of the language. Not draining the pool during an unwind is apparently required by the Objective-C exceptions implementation. +.. _arc.misc.externally_retained: + +Externally-Retained Variables +----------------------------- + +In some situations, variables with strong ownership are considered +externally-retained by the implementation. This means that the variable is +retained elsewhere, and therefore the implementation can elide retaining and +releasing its value. Such a variable is implicitly ``const`` for safety. In +contrast with ``__unsafe_unretained``, an externally-retained variable still +behaves as a strong variable outside of initialization and destruction. For +instance, when an externally-retained variable is captured in a block the value +of the variable is retained and released on block capture and destruction. It +also affects C++ features such as lambda capture, ``decltype``, and template +argument deduction. + +Implicitly, the implementation assumes that the :ref:`self parameter in a +non-init method ` and the :ref:`variable in a for-in loop +` are externally-retained. + +Externally-retained semantics can also be opted into with the +``objc_externally_retained`` attribute. This attribute can apply to strong local +variables, functions, methods, or blocks: + +.. code-block:: objc + + @class WobbleAmount; + + @interface Widget : NSObject + -(void)wobble:(WobbleAmount *)amount; + @end + + @implementation Widget + + -(void)wobble:(WobbleAmount *)amount + __attribute__((objc_externally_retained)) { + // 'amount' and 'alias' aren't retained on entry, nor released on exit. + __attribute__((objc_externally_retained)) WobbleAmount *alias = amount; + } + @end + +Annotating a function with this attribute makes every parameter with strong +retainable object pointer type externally-retained, unless the variable was +explicitly qualified with ``__strong``. For instance, ``first_param`` is +externally-retained (and therefore ``const``) below, but not ``second_param``: + +.. code-block:: objc + + __attribute__((objc_externally_retained)) + void f(NSArray *first_param, __strong NSArray *second_param) { + // ... + } + +You can test if your compiler has support for ``objc_externally_retained`` with +``__has_attribute``: + +.. code-block:: objc + + #if __has_attribute(objc_externally_retained) + // Use externally retained... + #endif + .. _arc.misc.self: ``self`` -------- -The ``self`` parameter variable of an Objective-C method is never actually -retained by the implementation. It is undefined behavior, or at least -dangerous, to cause an object to be deallocated during a message send to that -object. - -To make this safe, for Objective-C instance methods ``self`` is implicitly -``const`` unless the method is in the :ref:`init family -`. Further, ``self`` is **always** implicitly -``const`` within a class method. +The ``self`` parameter variable of an non-init Objective-C method is considered +:ref:`externally-retained ` by the implementation. +It is undefined behavior, or at least dangerous, to cause an object to be +deallocated during a message send to that object. In an init method, ``self`` +follows the :ref:``init family rules ``. .. admonition:: Rationale @@ -1758,9 +1816,9 @@ To make this safe, for Objective-C instance methods ``self`` is implicitly without this retain and release. Since it's extremely uncommon to actually do so, even unintentionally, and since there's no natural way for the programmer to remove this retain/release pair otherwise (as there is for - other parameters by, say, making the variable ``__unsafe_unretained``), we - chose to make this optimizing assumption and shift some amount of risk to the - user. + other parameters by, say, making the variable ``objc_externally_retained`` or + qualifying it with ``__unsafe_unretained``), we chose to make this optimizing + assumption and shift some amount of risk to the user. .. _arc.misc.enumeration: @@ -1769,8 +1827,9 @@ Fast enumeration iteration variables If a variable is declared in the condition of an Objective-C fast enumeration loop, and the variable has no explicit ownership qualifier, then it is -qualified with ``const __strong`` and objects encountered during the -enumeration are not actually retained. +implicitly :ref:`externally-retained ` so that +objects encountered during the enumeration are not actually retained and +released. .. admonition:: Rationale -- cgit v1.2.3