726 lines · plain
1==================2Source Annotations3==================4 5The Clang frontend supports several source-level annotations in the form of6`GCC-style attributes <https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html>`_7and pragmas that can help make using the Clang Static Analyzer more useful.8These annotations can both help suppress false positives as well as enhance the9analyzer's ability to find bugs.10 11This page gives a practical overview of such annotations. For more technical12specifics regarding Clang-specific annotations please see the Clang's list of13`language extensions <https://clang.llvm.org/docs/LanguageExtensions.html>`_.14Details of "standard" GCC attributes (that Clang also supports) can15be found in the `GCC manual <https://gcc.gnu.org/onlinedocs/gcc/>`_, with the16majority of the relevant attributes being in the section on17`function attributes <https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_.18 19Note that attributes that are labeled **Clang-specific** are not20recognized by GCC. Their use can be conditioned using preprocessor macros21(examples included on this page).22 23.. contents::24 :local:25 26General Purpose Annotations27___________________________28 29Null Pointer Checking30#####################31 32Attribute 'nonnull'33-------------------34 35The analyzer recognizes the GCC attribute 'nonnull', which indicates that a36function expects that a given function parameter is not a null pointer.37Specific details of the syntax of using the 'nonnull' attribute can be found in38`GCC's documentation <https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-nonnull-function-attribute>`_.39 40Both the Clang compiler and GCC will flag warnings for simple cases where a41null pointer is directly being passed to a function with a 'nonnull' parameter42(e.g., as a constant). The analyzer extends this checking by using its deeper43symbolic analysis to track what pointer values are potentially null and then44flag warnings when they are passed in a function call via a 'nonnull'45parameter.46 47**Example**48 49.. code-block:: c50 51 int bar(int*p, int q, int *r) __attribute__((nonnull(1,3)));52 53 int foo(int *p, int *q) {54 return !p ? bar(q, 2, p)55 : bar(p, 2, q);56 }57 58Running ``scan-build`` over this source produces the following output:59 60.. image:: ../images/example_attribute_nonnull.png61 62.. _custom_assertion_handlers:63 64Custom Assertion Handlers65#########################66 67The analyzer exploits code assertions by pruning off paths where the68assertion condition is false. The idea is capture any program invariants69specified in the assertion that the developer may know but is not immediately70apparent in the code itself. In this way assertions make implicit assumptions71explicit in the code, which not only makes the analyzer more accurate when72finding bugs, but can help others better able to understand your code as well.73It can also help remove certain kinds of analyzer false positives by pruning off74false paths.75 76In order to exploit assertions, however, the analyzer must understand when it77encounters an "assertion handler". Typically assertions are78implemented with a macro, with the macro performing a check for the assertion79condition and, when the check fails, calling an assertion handler. For80example, consider the following code fragment:81 82.. code-block:: c83 84 void foo(int *p) {85 assert(p != NULL);86 }87 88When this code is preprocessed on Mac OS X it expands to the following:89 90.. code-block:: c91 92 void foo(int *p) {93 (__builtin_expect(!(p != NULL), 0) ? __assert_rtn(__func__, "t.c", 4, "p != NULL") : (void)0);94 }95 96In this example, the assertion handler is ``__assert_rtn``. When called,97most assertion handlers typically print an error and terminate the program. The98analyzer can exploit such semantics by ending the analysis of a path once it99hits a call to an assertion handler.100 101The trick, however, is that the analyzer needs to know that a called function102is an assertion handler; otherwise the analyzer might assume the function call103returns and it will continue analyzing the path where the assertion condition104failed. This can lead to false positives, as the assertion condition usually105implies a safety condition (e.g., a pointer is not null) prior to performing106some action that depends on that condition (e.g., dereferencing a pointer).107 108The analyzer knows about several well-known assertion handlers, but can109automatically infer if a function should be treated as an assertion handler if110it is annotated with the 'noreturn' attribute or the (Clang-specific)111'analyzer_noreturn' attribute. Note that, currently, clang does not support112these attributes on Objective-C methods and C++ methods.113 114Attribute 'noreturn'115--------------------116 117The 'noreturn' attribute is a GCC attribute that can be placed on the118declarations of functions. It means exactly what its name implies: a function119with a 'noreturn' attribute should never return.120 121Specific details of the syntax of using the 'noreturn' attribute can be found122in `GCC's documentation <https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-noreturn-function-attribute>`__.123 124Not only does the analyzer exploit this information when pruning false paths,125but the compiler also takes it seriously and will generate different code (and126possibly better optimized) under the assumption that the function does not127return.128 129**Example**130 131On Mac OS X, the function prototype for ``__assert_rtn`` (declared in132``assert.h``) is specifically annotated with the 'noreturn' attribute:133 134.. code-block:: c135 136 void __assert_rtn(const char *, const char *, int, const char *) __attribute__((__noreturn__));137 138Attribute 'analyzer_noreturn' (Clang-specific)139----------------------------------------------140 141The Clang-specific 'analyzer_noreturn' attribute is almost identical to142'noreturn' except that it is ignored by the compiler for the purposes of code143generation.144 145This attribute is useful for annotating assertion handlers that actually146*can* return, but for the purpose of using the analyzer we want to147pretend that such functions do not return.148 149Because this attribute is Clang-specific, its use should be conditioned with150the use of preprocessor macros.151 152**Example**153 154.. code-block:: c155 156 #ifndef CLANG_ANALYZER_NORETURN157 #if __has_feature(attribute_analyzer_noreturn)158 #define CLANG_ANALYZER_NORETURN __attribute__((analyzer_noreturn))159 #else160 #define CLANG_ANALYZER_NORETURN161 #endif162 #endif163 164 void my_assert_rtn(const char *, const char *, int, const char *) CLANG_ANALYZER_NORETURN;165 166Dynamic Memory Modeling Annotations167###################################168 169If a project uses custom functions for dynamic memory management (that e.g. act as wrappers around ``malloc``/``free`` or ``new``/``delete`` in C++) and the analyzer cannot "see" the _definitions_ of these functions, it's possible to annotate their declarations to let the analyzer model their behavior. (Otherwise the analyzer cannot know that the opaque ``my_free()`` is basically equivalent to a standard ``free()`` call.)170 171.. note::172 **This page only provides a brief list of these annotations.** For a full documentation, see the main `Attributes in Clang <../../AttributeReference.html#ownership-holds-ownership-returns-ownership-takes-clang-static-analyzer>`_ page.173 174Attribute 'ownership_returns' (Clang-specific)175----------------------------------------------176 177Use this attribute to mark functions that return dynamically allocated memory. Takes a single argument, the type of the allocation (e.g. ``malloc`` or ``new``).178 179.. code-block:: c180 181 void __attribute((ownership_returns(malloc))) *my_malloc(size_t);182 183Attribute 'ownership_takes' (Clang-specific)184--------------------------------------------185 186Use this attribute to mark functions that deallocate memory. Takes two arguments: the type of the allocation (e.g. ``malloc`` or ``new``) and the index of the parameter that is being deallocated (counting from 1).187 188.. code-block:: c189 190 void __attribute((ownership_takes(malloc, 1))) my_free(void *);191 192Attribute 'ownership_holds' (Clang-specific)193--------------------------------------------194 195Use this attribute to mark functions that take ownership of memory and will deallocate it at some unspecified point in the future. Takes two arguments: the type of the allocation (e.g. ``malloc`` or ``new``) and the index of the parameter that is being held (counting from 1).196 197.. code-block:: c198 199 void __attribute((ownership_holds(malloc, 2))) store_in_table(int key, record_t *val);200 201The annotations ``ownership_takes`` and ``ownership_holds`` both prevent memory leak reports (concerning the specified argument); the difference between them is that using taken memory is a use-after-free error, while using held memory is assumed to be legitimate.202 203Mac OS X API Annotations204________________________205 206.. _cocoa_mem:207 208Cocoa & Core Foundation Memory Management Annotations209#####################################################210 211The analyzer supports the proper management of retain counts for212both Cocoa and Core Foundation objects. This checking is largely based on213enforcing Cocoa and Core Foundation naming conventions for Objective-C methods214(Cocoa) and C functions (Core Foundation). Not strictly following these215conventions can cause the analyzer to miss bugs or flag false positives.216 217One can educate the analyzer (and others who read your code) about methods or218functions that deviate from the Cocoa and Core Foundation conventions using the219attributes described here. However, you should consider using proper naming220conventions or the `objc_method_family <https://clang.llvm.org/docs/LanguageExtensions.html#the-objc-method-family-attribute>`_221attribute, if applicable.222 223.. _ns_returns_retained:224 225Attribute 'ns_returns_retained' (Clang-specific)226------------------------------------------------227 228The GCC-style (Clang-specific) attribute 'ns_returns_retained' allows one to229annotate an Objective-C method or C function as returning a retained Cocoa230object that the caller is responsible for releasing (via sending a231``release`` message to the object). The Foundation framework defines a232macro ``NS_RETURNS_RETAINED`` that is functionally equivalent to the233one shown below.234 235**Placing on Objective-C methods**: For Objective-C methods, this236annotation essentially tells the analyzer to treat the method as if its name237begins with "alloc" or "new" or contains the word238"copy".239 240**Placing on C functions**: For C functions returning Cocoa objects, the241analyzer typically does not make any assumptions about whether or not the object242is returned retained. Explicitly adding the 'ns_returns_retained' attribute to C243functions allows the analyzer to perform extra checking.244 245**Example**246 247.. code-block:: objc248 249 #import <Foundation/Foundation.h>;250 251 #ifndef __has_feature // Optional.252 #define __has_feature(x) 0 // Compatibility with non-clang compilers.253 #endif254 255 #ifndef NS_RETURNS_RETAINED256 #if __has_feature(attribute_ns_returns_retained)257 #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))258 #else259 #define NS_RETURNS_RETAINED260 #endif261 #endif262 263 @interface MyClass : NSObject {}264 - (NSString*) returnsRetained NS_RETURNS_RETAINED;265 - (NSString*) alsoReturnsRetained;266 @end267 268 @implementation MyClass269 - (NSString*) returnsRetained {270 return [[NSString alloc] initWithCString:"no leak here"];271 }272 - (NSString*) alsoReturnsRetained {273 return [[NSString alloc] initWithCString:"flag a leak"];274 }275 @end276 277Running ``scan-build`` on this source file produces the following output:278 279.. image:: ../images/example_ns_returns_retained.png280 281.. _ns_returns_not_retained:282 283Attribute 'ns_returns_not_retained' (Clang-specific)284----------------------------------------------------285 286The 'ns_returns_not_retained' attribute is the complement of287'`ns_returns_retained`_'. Where a function or method may appear to obey the288Cocoa conventions and return a retained Cocoa object, this attribute can be289used to indicate that the object reference returned should not be considered as290an "owning" reference being returned to the caller. The Foundation291framework defines a macro ``NS_RETURNS_NOT_RETAINED`` that is functionally292equivalent to the one shown below.293 294Usage is identical to `ns_returns_retained`_. When using the295attribute, be sure to declare it within the proper macro that checks for296its availability, as it is not available in earlier versions of the analyzer:297 298.. code-block:objc299 300 #ifndef __has_feature // Optional.301 #define __has_feature(x) 0 // Compatibility with non-clang compilers.302 #endif303 304 #ifndef NS_RETURNS_NOT_RETAINED305 #if __has_feature(attribute_ns_returns_not_retained)306 #define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))307 #else308 #define NS_RETURNS_NOT_RETAINED309 #endif310 #endif311 312.. _cf_returns_retained:313 314Attribute 'cf_returns_retained' (Clang-specific)315------------------------------------------------316 317The GCC-style (Clang-specific) attribute 'cf_returns_retained' allows one to318annotate an Objective-C method or C function as returning a retained Core319Foundation object that the caller is responsible for releasing. The320CoreFoundation framework defines a macro ``CF_RETURNS_RETAINED`` that is321functionally equivalent to the one shown below.322 323**Placing on Objective-C methods**: With respect to Objective-C methods.,324this attribute is identical in its behavior and usage to 'ns_returns_retained'325except for the distinction of returning a Core Foundation object instead of a326Cocoa object.327 328This distinction is important for the following reason: as Core Foundation is a329C API, the analyzer cannot always tell that a pointer return value refers to a330Core Foundation object. In contrast, it is trivial for the analyzer to331recognize if a pointer refers to a Cocoa object (given the Objective-C type332system).333 334**Placing on C functions**: When placing the attribute335'cf_returns_retained' on the declarations of C functions, the analyzer336interprets the function as:337 3381. Returning a Core Foundation Object3392. Treating the function as if it its name contained the keywords340 "create" or "copy". This means the returned object as a341 +1 retain count that must be released by the caller, either by sending a342 ``release`` message (via toll-free bridging to an Objective-C object343 pointer), or calling ``CFRelease`` or a similar function.344 345**Example**346 347.. code-block:objc348 349 #import <Cocoa/Cocoa.h>350 351 #ifndef __has_feature // Optional.352 #define __has_feature(x) 0 // Compatibility with non-clang compilers.353 #endif354 355 #ifndef CF_RETURNS_RETAINED356 #if __has_feature(attribute_cf_returns_retained)357 #define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))358 #else359 #define CF_RETURNS_RETAINED360 #endif361 #endif362 363 @interface MyClass : NSObject {}364 - (NSDate*) returnsCFRetained CF_RETURNS_RETAINED;365 - (NSDate*) alsoReturnsRetained;366 - (NSDate*) returnsNSRetained NS_RETURNS_RETAINED;367 @end368 369 CF_RETURNS_RETAINED370 CFDateRef returnsRetainedCFDate() {371 return CFDateCreate(0, CFAbsoluteTimeGetCurrent());372 }373 374 @implementation MyClass375 - (NSDate*) returnsCFRetained {376 return (NSDate*) returnsRetainedCFDate(); // No leak.377 }378 379 - (NSDate*) alsoReturnsRetained {380 return (NSDate*) returnsRetainedCFDate(); // Always report a leak.381 }382 383 - (NSDate*) returnsNSRetained {384 return (NSDate*) returnsRetainedCFDate(); // Report a leak when using GC.385 }386 @end387 388Running ``scan-build`` on this example produces the following output:389 390.. image:: ../images/example_cf_returns_retained.png391 392Attribute 'cf_returns_not_retained' (Clang-specific)393----------------------------------------------------394 395The 'cf_returns_not_retained' attribute is the complement of396'`cf_returns_retained`_'. Where a function or method may appear to obey the397Core Foundation or Cocoa conventions and return a retained Core Foundation398object, this attribute can be used to indicate that the object reference399returned should not be considered as an "owning" reference being400returned to the caller. The CoreFoundation framework defines a macro401**``CF_RETURNS_NOT_RETAINED``** that is functionally equivalent to the one402shown below.403 404Usage is identical to cf_returns_retained_. When using the attribute, be sure405to declare it within the proper macro that checks for its availability, as it406is not available in earlier versions of the analyzer:407 408.. code-block:objc409 410 #ifndef __has_feature // Optional.411 #define __has_feature(x) 0 // Compatibility with non-clang compilers.412 #endif413 414 #ifndef CF_RETURNS_NOT_RETAINED415 #if __has_feature(attribute_cf_returns_not_retained)416 #define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))417 #else418 #define CF_RETURNS_NOT_RETAINED419 #endif420 #endif421 422.. _ns_consumed:423 424Attribute 'ns_consumed' (Clang-specific)425----------------------------------------426 427The 'ns_consumed' attribute can be placed on a specific parameter in either428the declaration of a function or an Objective-C method. It indicates to the429static analyzer that a ``release`` message is implicitly sent to the430parameter upon completion of the call to the given function or method. The431Foundation framework defines a macro ``NS_RELEASES_ARGUMENT`` that432is functionally equivalent to the ``NS_CONSUMED`` macro shown below.433 434**Example**435 436.. code-block:objc437 438 #ifndef __has_feature // Optional.439 #define __has_feature(x) 0 // Compatibility with non-clang compilers.440 #endif441 442 #ifndef NS_CONSUMED443 #if __has_feature(attribute_ns_consumed)444 #define NS_CONSUMED __attribute__((ns_consumed))445 #else446 #define NS_CONSUMED447 #endif448 #endif449 450 void consume_ns(id NS_CONSUMED x);451 452 void test() {453 id x = [[NSObject alloc] init];454 consume_ns(x); // No leak!455 }456 457 @interface Foo : NSObject458 + (void) releaseArg:(id) NS_CONSUMED x;459 + (void) releaseSecondArg:(id)x second:(id) NS_CONSUMED y;460 @end461 462 void test_method() {463 id x = [[NSObject alloc] init];464 [Foo releaseArg:x]; // No leak!465 }466 467 void test_method2() {468 id a = [[NSObject alloc] init];469 id b = [[NSObject alloc] init];470 [Foo releaseSecondArg:a second:b]; // 'a' is leaked, but 'b' is released.471 }472 473Attribute 'cf_consumed' (Clang-specific)474----------------------------------------475 476The 'cf_consumed' attribute is practically identical to ns_consumed_. The477attribute can be placed on a specific parameter in either the declaration of a478function or an Objective-C method. It indicates to the static analyzer that the479object reference is implicitly passed to a call to ``CFRelease`` upon480completion of the call to the given function or method. The CoreFoundation481framework defines a macro ``CF_RELEASES_ARGUMENT`` that is functionally482equivalent to the ``CF_CONSUMED`` macro shown below.483 484Operationally this attribute is nearly identical to 'ns_consumed'.485 486**Example**487 488.. code-block:objc489 490 #ifndef __has_feature // Optional.491 #define __has_feature(x) 0 // Compatibility with non-clang compilers.492 #endif493 494 #ifndef CF_CONSUMED495 #if __has_feature(attribute_cf_consumed)496 #define CF_CONSUMED __attribute__((cf_consumed))497 #else498 #define CF_CONSUMED499 #endif500 #endif501 502 void consume_cf(id CF_CONSUMED x);503 void consume_CFDate(CFDateRef CF_CONSUMED x);504 505 void test() {506 id x = [[NSObject alloc] init];507 consume_cf(x); // No leak!508 }509 510 void test2() {511 CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent());512 consume_CFDate(date); // No leak, including under GC!513 514 }515 516 @interface Foo : NSObject517 + (void) releaseArg:(CFDateRef) CF_CONSUMED x;518 @end519 520 void test_method() {521 CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent());522 [Foo releaseArg:date]; // No leak!523 }524 525.. _ns_consumes_self:526 527Attribute 'ns_consumes_self' (Clang-specific)528---------------------------------------------529 530The 'ns_consumes_self' attribute can be placed only on an Objective-C method531declaration. It indicates that the receiver of the message is532"consumed" (a single reference count decremented) after the message533is sent. This matches the semantics of all "init" methods.534 535One use of this attribute is declare your own init-like methods that do not536follow the standard Cocoa naming conventions.537 538**Example**539 540.. code-block:objc541 #ifndef __has_feature542 #define __has_feature(x) 0 // Compatibility with non-clang compilers.543 #endif544 545 #ifndef NS_CONSUMES_SELF546 #if __has_feature((attribute_ns_consumes_self))547 #define NS_CONSUMES_SELF __attribute__((ns_consumes_self))548 #else549 #define NS_CONSUMES_SELF550 #endif551 #endif552 553 @interface MyClass : NSObject554 - initWith:(MyClass *)x;555 - nonstandardInitWith:(MyClass *)x NS_CONSUMES_SELF NS_RETURNS_RETAINED;556 @end557 558In this example, ``-nonstandardInitWith:`` has the same ownership559semantics as the init method ``-initWith:``. The static analyzer will560observe that the method consumes the receiver, and then returns an object with561a +1 retain count.562 563The Foundation framework defines a macro ``NS_REPLACES_RECEIVER`` which is564functionally equivalent to the combination of ``NS_CONSUMES_SELF`` and565``NS_RETURNS_RETAINED`` shown above.566 567Libkern Memory Management Annotations568#####################################569 570`Libkern <https://developer.apple.com/documentation/kernel/osobject?language=objc>`_571requires developers to inherit all heap allocated objects from ``OSObject`` and572to perform manual reference counting. The reference counting model is very573similar to MRR (manual retain-release) mode in574`Objective-C <https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html>`_575or to CoreFoundation reference counting.576Freshly-allocated objects start with a reference count of 1, and calls to577``retain`` increment it, while calls to ``release`` decrement it. The object is578deallocated whenever its reference count reaches zero.579 580Manually incrementing and decrementing reference counts is error-prone:581over-retains lead to leaks, and over-releases lead to uses-after-free.582The analyzer can help the programmer to check for unbalanced583retain/release calls.584 585The reference count checking is based on the principle of *locality*: it should586be possible to establish correctness (lack of leaks/uses after free) by looking587at each function body, and the declarations (not the definitions) of all the588functions it interacts with.589 590In order to support such reasoning, it should be possible to *summarize* the591behavior of each function, with respect to reference count of its returned592values and attributes.593 594By default, the following summaries are assumed:595 596- All functions starting with ``get`` or ``Get``, unless they are returning597 subclasses of ``OSIterator``, are assumed to be returning at +0. That is, the598 caller has no reference count *obligations* with respect to the reference599 count of the returned object and should leave it untouched.600 601- All other functions are assumed to return at +1. That is, the caller has an602 *obligation* to release such objects.603 604- Functions are assumed not to change the reference count of their parameters,605 including the implicit ``this`` parameter.606 607These summaries can be overriden with the following608`attributes <https://clang.llvm.org/docs/AttributeReference.html#os-returns-not-retained>`_:609 610Attribute 'os_returns_retained'611-------------------------------612 613The ``os_returns_retained`` attribute (accessed through the macro614``LIBKERN_RETURNS_RETAINED``) plays a role identical to `ns_returns_retained`_615for functions returning ``OSObject`` subclasses. The attribute indicates that616it is a callers responsibility to release the returned object.617 618Attribute 'os_returns_not_retained'619-----------------------------------620 621The ``os_returns_not_retained`` attribute (accessed through the macro622``LIBKERN_RETURNS_NOT_RETAINED``) plays a role identical to623`ns_returns_not_retained`_ for functions returning ``OSObject`` subclasses. The624attribute indicates that the caller should not change the retain count of the625returned object.626 627 628**Example**629 630.. code-block:objc631 632 class MyClass {633 OSObject *f;634 LIBKERN_RETURNS_NOT_RETAINED OSObject *myFieldGetter();635 }636 637 // Note that the annotation only has to be applied to the function declaration.638 OSObject * MyClass::myFieldGetter() {639 return f;640 }641 642Attribute 'os_consumed'643-----------------------644 645Similarly to `ns_consumed`_ attribute, ``os_consumed`` (accessed through646``LIBKERN_CONSUMED``) attribute, applied to a parameter, indicates that the647call to the function *consumes* the parameter: the callee should either release648it or store it and release it in the destructor, while the caller should assume649one is subtracted from the reference count after the call.650 651.. code-block:objc652 IOReturn addToList(LIBKERN_CONSUMED IOPMinformee *newInformee);653 654Attribute 'os_consumes_this'655----------------------------656 657Similarly to `ns_consumes_self`_, the ``os_consumes_self`` attribute indicates658that the method call *consumes* the implicit ``this`` argument: the caller659should assume one was subtracted from the reference count of the object after660the call, and the callee has on obligation to either release the argument, or661store it and eventually release it in the destructor.662 663 664.. code-block:objc665 void addThisToList(OSArray *givenList) LIBKERN_CONSUMES_THIS;666 667Out Parameters668--------------669 670A function can also return an object to a caller by a means of an out parameter671(a pointer-to-OSObject-pointer is passed, and a callee writes a pointer to an672object into an argument). Currently the analyzer does not track unannotated out673parameters by default, but with annotations we distinguish four separate cases:674 675**1. Non-retained out parameters**, identified using676``LIBKERN_RETURNS_NOT_RETAINED`` applied to parameters, e.g.:677 678.. code-block:objc679 void getterViaOutParam(LIBKERN_RETURNS_NOT_RETAINED OSObject **obj)680 681Such functions write a non-retained object into an out parameter, and the682caller has no further obligations.683 684**2. Retained out parameters**, identified using ``LIBKERN_RETURNS_RETAINED``:685 686.. code-block:objc687 void getterViaOutParam(LIBKERN_RETURNS_NOT_RETAINED OSObject **obj)688 689In such cases a retained object is written into an out parameter, which the caller has then to release in order to avoid a leak.690 691These two cases are simple - but in practice a functions returning an692out-parameter usually also return a return code, and then an out parameter may693or may not be written, which conditionally depends on the exit code, e.g.:694 695.. code-block:objc696 bool maybeCreateObject(LIBKERN_RETURNS_RETAINED OSObject **obj);697 698For such functions, the usual semantics is that an object is written into on "success", and not written into on "failure".699 700For ``LIBKERN_RETURNS_RETAINED`` we assume the following definition of701success:702 703- For functions returning ``OSReturn`` or ``IOReturn`` (any typedef to704 ``kern_return_t``) success is defined as having an output of zero705 (``kIOReturnSuccess`` is zero).706 707- For all others, success is non-zero (e.g. non-nullptr for pointers)708 709**3. Retained out parameters on zero return** The annotation710``LIBKERN_RETURNS_RETAINED_ON_ZERO`` states that a retained object is written711into if and only if the function returns a zero value:712 713.. code-block:objc714 bool OSUnserializeXML(void *data, LIBKERN_RETURNS_RETAINED_ON_ZERO OSString **errString);715 716Then the caller has to release an object if the function has returned zero.717 718**4. Retained out parameters on non-zero return** Similarly,719``LIBKERN_RETURNS_RETAINED_ON_NONZERO`` specifies that a retained object is720written into the parameter if and only if the function has returned a non-zero721value.722 723Note that for non-retained out parameters conditionals do not matter, as the724caller has no obligations regardless of whether an object is written into or725not.726