https://github.com/NagyDonat created https://github.com/llvm/llvm-project/pull/122246
This commit migrates the contents of 'annotations.html' in the old HTML-based documentation of the Clang static analyzer to the new RST-based documentation. During this conversion I reordered the sections of this documentation file by placing the section "Custom Assertion Handlers" as a subsection of "Annotations to Enhance Generic Checks". (The primary motivation was that Sphinx complained about inconsistent section levels; with this change I preserved that sections describing individual annotations are all on the same level.) Apart from this change and the format conversion, I didn't review, validate or edit the contents of this documentation file because I think it would be better to place any additional changes in separate commits. From 4d558f5fff178b9897319b0e63dcf6f955e7eee9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.n...@ericsson.com> Date: Wed, 8 Jan 2025 17:24:34 +0100 Subject: [PATCH] [NFC][analyzer][docs] Migrate 'annotations.html' to RST This commit migrates the contents of 'annotations.html' in the old HTML-based documentation of the Clang static analyzer to the new RST-based documentation. During this conversion I reordered the sections of this documentation file by placing the section "Custom Assertion Handlers" as a subsection of "Annotations to Enhance Generic Checks". (The primary motivation was that Sphinx complained about inconsistent section levels; with this change I preserved that sections describing individual annotations are all on the same level.) Apart from this change and the format conversion, I didn't review, validate or edit the contents of this documentation file because I think it would be better to place any additional changes in separate commits. --- .../images/example_attribute_nonnull.png | Bin .../images/example_cf_returns_retained.png | Bin .../images/example_ns_returns_retained.png | Bin clang/docs/analyzer/user-docs.rst | 1 + clang/docs/analyzer/user-docs/Annotations.rst | 685 ++++++++++++++++ clang/include/clang/Basic/AttrDocs.td | 2 +- clang/www/analyzer/annotations.html | 766 +----------------- 7 files changed, 694 insertions(+), 760 deletions(-) rename clang/{www => docs}/analyzer/images/example_attribute_nonnull.png (100%) rename clang/{www => docs}/analyzer/images/example_cf_returns_retained.png (100%) rename clang/{www => docs}/analyzer/images/example_ns_returns_retained.png (100%) create mode 100644 clang/docs/analyzer/user-docs/Annotations.rst diff --git a/clang/www/analyzer/images/example_attribute_nonnull.png b/clang/docs/analyzer/images/example_attribute_nonnull.png similarity index 100% rename from clang/www/analyzer/images/example_attribute_nonnull.png rename to clang/docs/analyzer/images/example_attribute_nonnull.png diff --git a/clang/www/analyzer/images/example_cf_returns_retained.png b/clang/docs/analyzer/images/example_cf_returns_retained.png similarity index 100% rename from clang/www/analyzer/images/example_cf_returns_retained.png rename to clang/docs/analyzer/images/example_cf_returns_retained.png diff --git a/clang/www/analyzer/images/example_ns_returns_retained.png b/clang/docs/analyzer/images/example_ns_returns_retained.png similarity index 100% rename from clang/www/analyzer/images/example_ns_returns_retained.png rename to clang/docs/analyzer/images/example_ns_returns_retained.png diff --git a/clang/docs/analyzer/user-docs.rst b/clang/docs/analyzer/user-docs.rst index dd53ae143148c0..e265f033a2c540 100644 --- a/clang/docs/analyzer/user-docs.rst +++ b/clang/docs/analyzer/user-docs.rst @@ -12,4 +12,5 @@ Contents: user-docs/FilingBugs user-docs/CrossTranslationUnit user-docs/TaintAnalysisConfiguration + user-docs/Annotations user-docs/FAQ diff --git a/clang/docs/analyzer/user-docs/Annotations.rst b/clang/docs/analyzer/user-docs/Annotations.rst new file mode 100644 index 00000000000000..778047b82d517d --- /dev/null +++ b/clang/docs/analyzer/user-docs/Annotations.rst @@ -0,0 +1,685 @@ +================== +Source Annotations +================== + +The Clang frontend supports several source-level annotations in the form of +`GCC-style attributes <https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html>`_ +and pragmas that can help make using the Clang Static Analyzer more useful. +These annotations can both help suppress false positives as well as enhance the +analyzer's ability to find bugs. + +This page gives a practical overview of such annotations. For more technical +specifics regarding Clang-specific annotations please see the Clang's list of +`language extensions <https://clang.llvm.org/docs/LanguageExtensions.html>`_. +Details of "standard" GCC attributes (that Clang also supports) can +be found in the `GCC manual <https://gcc.gnu.org/onlinedocs/gcc/>`_, with the +majority of the relevant attributes being in the section on +`function attributes <https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_. + +Note that attributes that are labeled **Clang-specific** are not +recognized by GCC. Their use can be conditioned using preprocessor macros +(examples included on this page). + +.. contents:: + :local: + +Annotations to Enhance Generic Checks +_____________________________________ + +Null Pointer Checking +##################### + +Attribute 'nonnull' +------------------- + +The analyzer recognizes the GCC attribute 'nonnull', which indicates that a +function expects that a given function parameter is not a null pointer. +Specific details of the syntax of using the 'nonnull' attribute can be found in +`GCC's documentation <https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-nonnull-function-attribute>`_. + +Both the Clang compiler and GCC will flag warnings for simple cases where a +null pointer is directly being passed to a function with a 'nonnull' parameter +(e.g., as a constant). The analyzer extends this checking by using its deeper +symbolic analysis to track what pointer values are potentially null and then +flag warnings when they are passed in a function call via a 'nonnull' +parameter. + +**Example** + +.. code-block:: c + + int bar(int*p, int q, int *r) __attribute__((nonnull(1,3))); + + int foo(int *p, int *q) { + return !p ? bar(q, 2, p) + : bar(p, 2, q); + } + +Running ``scan-build`` over this source produces the following output: + +.. image:: ../images/example_attribute_nonnull.png + +Custom Assertion Handlers +######################### + +The analyzer exploits code assertions by pruning off paths where the +assertion condition is false. The idea is capture any program invariants +specified in the assertion that the developer may know but is not immediately +apparent in the code itself. In this way assertions make implicit assumptions +explicit in the code, which not only makes the analyzer more accurate when +finding bugs, but can help others better able to understand your code as well. +It can also help remove certain kinds of analyzer false positives by pruning off +false paths. + +In order to exploit assertions, however, the analyzer must understand when it +encounters an "assertion handler". Typically assertions are +implemented with a macro, with the macro performing a check for the assertion +condition and, when the check fails, calling an assertion handler. For +example, consider the following code fragment: + +.. code-block: c + + void foo(int *p) { + assert(p != NULL); + } + +When this code is preprocessed on Mac OS X it expands to the following: + +.. code-block: c + + void foo(int *p) { + (__builtin_expect(!(p != NULL), 0) ? __assert_rtn(__func__, "t.c", 4, "p != NULL") : (void)0); + } + +In this example, the assertion handler is ``__assert_rtn``. When called, +most assertion handlers typically print an error and terminate the program. The +analyzer can exploit such semantics by ending the analysis of a path once it +hits a call to an assertion handler. + +The trick, however, is that the analyzer needs to know that a called function +is an assertion handler; otherwise the analyzer might assume the function call +returns and it will continue analyzing the path where the assertion condition +failed. This can lead to false positives, as the assertion condition usually +implies a safety condition (e.g., a pointer is not null) prior to performing +some action that depends on that condition (e.g., dereferencing a pointer). + +The analyzer knows about several well-known assertion handlers, but can +automatically infer if a function should be treated as an assertion handler if +it is annotated with the 'noreturn' attribute or the (Clang-specific) +'analyzer_noreturn' attribute. Note that, currently, clang does not support +these attributes on Objective-C methods and C++ methods. + +Attribute 'noreturn' +-------------------- + +The 'noreturn' attribute is a GCC attribute that can be placed on the +declarations of functions. It means exactly what its name implies: a function +with a 'noreturn' attribute should never return. + +Specific details of the syntax of using the 'noreturn' attribute can be found +in `GCC's documentation <https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-noreturn-function-attribute>`__. + +Not only does the analyzer exploit this information when pruning false paths, +but the compiler also takes it seriously and will generate different code (and +possibly better optimized) under the assumption that the function does not +return. + +**Example** + +On Mac OS X, the function prototype for ``__assert_rtn`` (declared in +``assert.h``) is specifically annotated with the 'noreturn' attribute: + +.. code-block: c + + void __assert_rtn(const char *, const char *, int, const char *) __attribute__((__noreturn__)); + +Attribute 'analyzer_noreturn' (Clang-specific) +---------------------------------------------- + +The Clang-specific 'analyzer_noreturn' attribute is almost identical to +'noreturn' except that it is ignored by the compiler for the purposes of code +generation. + +This attribute is useful for annotating assertion handlers that actually +*can* return, but for the purpose of using the analyzer we want to +pretend that such functions do not return. + +Because this attribute is Clang-specific, its use should be conditioned with +the use of preprocessor macros. + +**Example** + +.. code-block: c + + #ifndef CLANG_ANALYZER_NORETURN + #if __has_feature(attribute_analyzer_noreturn) + #define CLANG_ANALYZER_NORETURN __attribute__((analyzer_noreturn)) + #else + #define CLANG_ANALYZER_NORETURN + #endif + #endif + + void my_assert_rtn(const char *, const char *, int, const char *) CLANG_ANALYZER_NORETURN; + +Mac OS X API Annotations +________________________ + +Cocoa & Core Foundation Memory Management Annotations +##################################################### + +The analyzer supports the proper management of retain counts for +both Cocoa and Core Foundation objects. This checking is largely based on +enforcing Cocoa and Core Foundation naming conventions for Objective-C methods +(Cocoa) and C functions (Core Foundation). Not strictly following these +conventions can cause the analyzer to miss bugs or flag false positives. + +One can educate the analyzer (and others who read your code) about methods or +functions that deviate from the Cocoa and Core Foundation conventions using the +attributes described here. However, you should consider using proper naming +conventions or the `objc_method_family <https://clang.llvm.org/docs/LanguageExtensions.html#the-objc-method-family-attribute>`_ +attribute, if applicable. + +.. _ns_returns_retained: + +Attribute 'ns_returns_retained' (Clang-specific) +------------------------------------------------ + +The GCC-style (Clang-specific) attribute 'ns_returns_retained' allows one to +annotate an Objective-C method or C function as returning a retained Cocoa +object that the caller is responsible for releasing (via sending a +``release`` message to the object). The Foundation framework defines a +macro ``NS_RETURNS_RETAINED`` that is functionally equivalent to the +one shown below. + +**Placing on Objective-C methods**: For Objective-C methods, this +annotation essentially tells the analyzer to treat the method as if its name +begins with "alloc" or "new" or contains the word +"copy". + +**Placing on C functions**: For C functions returning Cocoa objects, the +analyzer typically does not make any assumptions about whether or not the object +is returned retained. Explicitly adding the 'ns_returns_retained' attribute to C +functions allows the analyzer to perform extra checking. + +**Example** + +.. code-block: objc + + #import <Foundation/Foundation.h>; + + #ifndef __has_feature // Optional. + #define __has_feature(x) 0 // Compatibility with non-clang compilers. + #endif + + #ifndef NS_RETURNS_RETAINED + #if __has_feature(attribute_ns_returns_retained) + #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained)) + #else + #define NS_RETURNS_RETAINED + #endif + #endif + + @interface MyClass : NSObject {} + - (NSString*) returnsRetained NS_RETURNS_RETAINED; + - (NSString*) alsoReturnsRetained; + @end + + @implementation MyClass + - (NSString*) returnsRetained { + return [[NSString alloc] initWithCString:"no leak here"]; + } + - (NSString*) alsoReturnsRetained { + return [[NSString alloc] initWithCString:"flag a leak"]; + } + @end + +Running ``scan-build`` on this source file produces the following output: + +.. image:: ../images/example_ns_returns_retained.png + +.. _ns_returns_not_retained: + +Attribute 'ns_returns_not_retained' (Clang-specific) +---------------------------------------------------- + +The 'ns_returns_not_retained' attribute is the complement of +'`ns_returns_retained`_'. Where a function or method may appear to obey the +Cocoa conventions and return a retained Cocoa object, this attribute can be +used to indicate that the object reference returned should not be considered as +an "owning" reference being returned to the caller. The Foundation +framework defines a macro ``NS_RETURNS_NOT_RETAINED`` that is functionally +equivalent to the one shown below. + +Usage is identical to `ns_returns_retained`_. When using the +attribute, be sure to declare it within the proper macro that checks for +its availability, as it is not available in earlier versions of the analyzer: + +.. code-block:objc + + #ifndef __has_feature // Optional. + #define __has_feature(x) 0 // Compatibility with non-clang compilers. + #endif + + #ifndef NS_RETURNS_NOT_RETAINED + #if __has_feature(attribute_ns_returns_not_retained) + #define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained)) + #else + #define NS_RETURNS_NOT_RETAINED + #endif + #endif + +.. _cf_returns_retained: + +Attribute 'cf_returns_retained' (Clang-specific) +------------------------------------------------ + +The GCC-style (Clang-specific) attribute 'cf_returns_retained' allows one to +annotate an Objective-C method or C function as returning a retained Core +Foundation object that the caller is responsible for releasing. The +CoreFoundation framework defines a macro ``CF_RETURNS_RETAINED`` that is +functionally equivalent to the one shown below. + +**Placing on Objective-C methods**: With respect to Objective-C methods., +this attribute is identical in its behavior and usage to 'ns_returns_retained' +except for the distinction of returning a Core Foundation object instead of a +Cocoa object. + +This distinction is important for the following reason: as Core Foundation is a +C API, the analyzer cannot always tell that a pointer return value refers to a +Core Foundation object. In contrast, it is trivial for the analyzer to +recognize if a pointer refers to a Cocoa object (given the Objective-C type +system). + +**Placing on C functions**: When placing the attribute +'cf_returns_retained' on the declarations of C functions, the analyzer +interprets the function as: + +1. Returning a Core Foundation Object +2. Treating the function as if it its name contained the keywords + "create" or "copy". This means the returned object as a + +1 retain count that must be released by the caller, either by sending a + ``release`` message (via toll-free bridging to an Objective-C object + pointer), or calling ``CFRelease`` or a similar function. + +**Example** + +.. code-block:objc + + #import <Cocoa/Cocoa.h> + + #ifndef __has_feature // Optional. + #define __has_feature(x) 0 // Compatibility with non-clang compilers. + #endif + + #ifndef CF_RETURNS_RETAINED + #if __has_feature(attribute_cf_returns_retained) + #define CF_RETURNS_RETAINED __attribute__((cf_returns_retained)) + #else + #define CF_RETURNS_RETAINED + #endif + #endif + + @interface MyClass : NSObject {} + - (NSDate*) returnsCFRetained CF_RETURNS_RETAINED; + - (NSDate*) alsoReturnsRetained; + - (NSDate*) returnsNSRetained NS_RETURNS_RETAINED; + @end + + CF_RETURNS_RETAINED + CFDateRef returnsRetainedCFDate() { + return CFDateCreate(0, CFAbsoluteTimeGetCurrent()); + } + + @implementation MyClass + - (NSDate*) returnsCFRetained { + return (NSDate*) returnsRetainedCFDate(); // No leak. + } + + - (NSDate*) alsoReturnsRetained { + return (NSDate*) returnsRetainedCFDate(); // Always report a leak. + } + + - (NSDate*) returnsNSRetained { + return (NSDate*) returnsRetainedCFDate(); // Report a leak when using GC. + } + @end + +Running ``scan-build`` on this example produces the following output: + +.. image:: ../images/example_cf_returns_retained.png + +Attribute 'cf_returns_not_retained' (Clang-specific) +---------------------------------------------------- + +The 'cf_returns_not_retained' attribute is the complement of +'`cf_returns_retained`_'. Where a function or method may appear to obey the +Core Foundation or Cocoa conventions and return a retained Core Foundation +object, this attribute can be used to indicate that the object reference +returned should not be considered as an "owning" reference being +returned to the caller. The CoreFoundation framework defines a macro +**``CF_RETURNS_NOT_RETAINED``** that is functionally equivalent to the one +shown below. + +Usage is identical to cf_returns_retained_. When using the attribute, be sure +to declare it within the proper macro that checks for its availability, as it +is not available in earlier versions of the analyzer: + +.. code-block:objc + + #ifndef __has_feature // Optional. + #define __has_feature(x) 0 // Compatibility with non-clang compilers. + #endif + + #ifndef CF_RETURNS_NOT_RETAINED + #if __has_feature(attribute_cf_returns_not_retained) + #define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained)) + #else + #define CF_RETURNS_NOT_RETAINED + #endif + #endif + +.. _ns_consumed: + +Attribute 'ns_consumed' (Clang-specific) +---------------------------------------- + +The 'ns_consumed' attribute can be placed on a specific parameter in either +the declaration of a function or an Objective-C method. It indicates to the +static analyzer that a ``release`` message is implicitly sent to the +parameter upon completion of the call to the given function or method. The +Foundation framework defines a macro ``NS_RELEASES_ARGUMENT`` that +is functionally equivalent to the ``NS_CONSUMED`` macro shown below. + +**Example** + +.. code-block:objc + + #ifndef __has_feature // Optional. + #define __has_feature(x) 0 // Compatibility with non-clang compilers. + #endif + + #ifndef NS_CONSUMED + #if __has_feature(attribute_ns_consumed) + #define NS_CONSUMED __attribute__((ns_consumed)) + #else + #define NS_CONSUMED + #endif + #endif + + void consume_ns(id NS_CONSUMED x); + + void test() { + id x = [[NSObject alloc] init]; + consume_ns(x); // No leak! + } + + @interface Foo : NSObject + + (void) releaseArg:(id) NS_CONSUMED x; + + (void) releaseSecondArg:(id)x second:(id) NS_CONSUMED y; + @end + + void test_method() { + id x = [[NSObject alloc] init]; + [Foo releaseArg:x]; // No leak! + } + + void test_method2() { + id a = [[NSObject alloc] init]; + id b = [[NSObject alloc] init]; + [Foo releaseSecondArg:a second:b]; // 'a' is leaked, but 'b' is released. + } + +Attribute 'cf_consumed' (Clang-specific) +---------------------------------------- + +The 'cf_consumed' attribute is practically identical to ns_consumed_. The +attribute can be placed on a specific parameter in either the declaration of a +function or an Objective-C method. It indicates to the static analyzer that the +object reference is implicitly passed to a call to ``CFRelease`` upon +completion of the call to the given function or method. The CoreFoundation +framework defines a macro ``CF_RELEASES_ARGUMENT`` that is functionally +equivalent to the ``CF_CONSUMED`` macro shown below. + +Operationally this attribute is nearly identical to 'ns_consumed'. + +**Example** + +.. code-block:objc + + #ifndef __has_feature // Optional. + #define __has_feature(x) 0 // Compatibility with non-clang compilers. + #endif + + #ifndef CF_CONSUMED + #if __has_feature(attribute_cf_consumed) + #define CF_CONSUMED __attribute__((cf_consumed)) + #else + #define CF_CONSUMED + #endif + #endif + + void consume_cf(id CF_CONSUMED x); + void consume_CFDate(CFDateRef CF_CONSUMED x); + + void test() { + id x = [[NSObject alloc] init]; + consume_cf(x); // No leak! + } + + void test2() { + CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); + consume_CFDate(date); // No leak, including under GC! + + } + + @interface Foo : NSObject + + (void) releaseArg:(CFDateRef) CF_CONSUMED x; + @end + + void test_method() { + CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); + [Foo releaseArg:date]; // No leak! + } + +.. _ns_consumes_self: + +Attribute 'ns_consumes_self' (Clang-specific) +--------------------------------------------- + +The 'ns_consumes_self' attribute can be placed only on an Objective-C method +declaration. It indicates that the receiver of the message is +"consumed" (a single reference count decremented) after the message +is sent. This matches the semantics of all "init" methods. + +One use of this attribute is declare your own init-like methods that do not +follow the standard Cocoa naming conventions. + +**Example** + +.. code-block:objc + #ifndef __has_feature + #define __has_feature(x) 0 // Compatibility with non-clang compilers. + #endif + + #ifndef NS_CONSUMES_SELF + #if __has_feature((attribute_ns_consumes_self)) + #define NS_CONSUMES_SELF __attribute__((ns_consumes_self)) + #else + #define NS_CONSUMES_SELF + #endif + #endif + + @interface MyClass : NSObject + - initWith:(MyClass *)x; + - nonstandardInitWith:(MyClass *)x NS_CONSUMES_SELF NS_RETURNS_RETAINED; + @end + +In this example, ``-nonstandardInitWith:`` has the same ownership +semantics as the init method ``-initWith:``. The static analyzer will +observe that the method consumes the receiver, and then returns an object with +a +1 retain count. + +The Foundation framework defines a macro ``NS_REPLACES_RECEIVER`` which is +functionally equivalent to the combination of ``NS_CONSUMES_SELF`` and +``NS_RETURNS_RETAINED`` shown above. + +Libkern Memory Management Annotations +##################################### + +`Libkern <https://developer.apple.com/documentation/kernel/osobject?language=objc>`_ +requires developers to inherit all heap allocated objects from ``OSObject`` and +to perform manual reference counting. The reference counting model is very +similar to MRR (manual retain-release) mode in +`Objective-C <https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html>`_ +or to CoreFoundation reference counting. +Freshly-allocated objects start with a reference count of 1, and calls to +``retain`` increment it, while calls to ``release`` decrement it. The object is +deallocated whenever its reference count reaches zero. + +Manually incrementing and decrementing reference counts is error-prone: +over-retains lead to leaks, and over-releases lead to uses-after-free. +The analyzer can help the programmer to check for unbalanced +retain/release calls. + +The reference count checking is based on the principle of *locality*: it should +be possible to establish correctness (lack of leaks/uses after free) by looking +at each function body, and the declarations (not the definitions) of all the +functions it interacts with. + +In order to support such reasoning, it should be possible to *summarize* the +behavior of each function, with respect to reference count of its returned +values and attributes. + +By default, the following summaries are assumed: + +- All functions starting with ``get`` or ``Get``, unless they are returning + subclasses of ``OSIterator``, are assumed to be returning at +0. That is, the + caller has no reference count *obligations* with respect to the reference + count of the returned object and should leave it untouched. + +- All other functions are assumed to return at +1. That is, the caller has an + *obligation* to release such objects. + +- Functions are assumed not to change the reference count of their parameters, + including the implicit ``this`` parameter. + +These summaries can be overriden with the following +`attributes <https://clang.llvm.org/docs/AttributeReference.html#os-returns-not-retained>`_: + +Attribute 'os_returns_retained' +------------------------------- + +The ``os_returns_retained`` attribute (accessed through the macro +``LIBKERN_RETURNS_RETAINED``) plays a role identical to `ns_returns_retained`_ +for functions returning ``OSObject`` subclasses. The attribute indicates that +it is a callers responsibility to release the returned object. + +Attribute 'os_returns_not_retained' +----------------------------------- + +The ``os_returns_not_retained`` attribute (accessed through the macro +``LIBKERN_RETURNS_NOT_RETAINED``) plays a role identical to +`ns_returns_not_retained`_ for functions returning ``OSObject`` subclasses. The +attribute indicates that the caller should not change the retain count of the +returned object. + + +**Example** + +.. code-block:objc + + class MyClass { + OSObject *f; + LIBKERN_RETURNS_NOT_RETAINED OSObject *myFieldGetter(); + } + + + // Note that the annotation only has to be applied to the function declaration. + OSObject * MyClass::myFieldGetter() { + return f; + } + +Attribute 'os_consumed' +----------------------- + +Similarly to `ns_consumed`_ attribute, ``os_consumed`` (accessed through +``LIBKERN_CONSUMED``) attribute, applied to a parameter, indicates that the +call to the function *consumes* the parameter: the callee should either release +it or store it and release it in the destructor, while the caller should assume +one is subtracted from the reference count after the call. + +.. code-block:objc + IOReturn addToList(LIBKERN_CONSUMED IOPMinformee *newInformee); + +Attribute 'os_consumes_this' +---------------------------- + +Similarly to `ns_consumes_self`_, the ``os_consumes_self`` attribute indicates +that the method call *consumes* the implicit ``this`` argument: the caller +should assume one was subtracted from the reference count of the object after +the call, and the callee has on obligation to either release the argument, or +store it and eventually release it in the destructor. + + +.. code-block:objc + void addThisToList(OSArray *givenList) LIBKERN_CONSUMES_THIS; + +Out Parameters +-------------- + +A function can also return an object to a caller by a means of an out parameter +(a pointer-to-OSObject-pointer is passed, and a callee writes a pointer to an +object into an argument). Currently the analyzer does not track unannotated out +parameters by default, but with annotations we distinguish four separate cases: + +**1. Non-retained out parameters**, identified using +``LIBKERN_RETURNS_NOT_RETAINED`` applied to parameters, e.g.: + +.. code-block:objc + void getterViaOutParam(LIBKERN_RETURNS_NOT_RETAINED OSObject **obj) + +Such functions write a non-retained object into an out parameter, and the +caller has no further obligations. + +**2. Retained out parameters**, identified using ``LIBKERN_RETURNS_RETAINED``: + +.. code-block:objc + void getterViaOutParam(LIBKERN_RETURNS_NOT_RETAINED OSObject **obj) + +In such cases a retained object is written into an out parameter, which the caller has then to release in order to avoid a leak. + +These two cases are simple - but in practice a functions returning an +out-parameter usually also return a return code, and then an out parameter may +or may not be written, which conditionally depends on the exit code, e.g.: + +.. code-block:objc + bool maybeCreateObject(LIBKERN_RETURNS_RETAINED OSObject **obj); + +For such functions, the usual semantics is that an object is written into on "success", and not written into on "failure". + +For ``LIBKERN_RETURNS_RETAINED`` we assume the following definition of +success: + +- For functions returning ``OSReturn`` or ``IOReturn`` (any typedef to + ``kern_return_t``) success is defined as having an output of zero + (``kIOReturnSuccess`` is zero). + +- For all others, success is non-zero (e.g. non-nullptr for pointers) + +**3. Retained out parameters on zero return** The annotation +``LIBKERN_RETURNS_RETAINED_ON_ZERO`` states that a retained object is written +into if and only if the function returns a zero value: + +.. code-block:objc + bool OSUnserializeXML(void *data, LIBKERN_RETURNS_RETAINED_ON_ZERO OSString **errString); + +Then the caller has to release an object if the function has returned zero. + +**4. Retained out parameters on non-zero return** Similarly, +``LIBKERN_RETURNS_RETAINED_ON_NONZERO`` specifies that a retained object is +written into the parameter if and only if the function has returned a non-zero +value. + +Note that for non-retained out parameters conditionals do not matter, as the +caller has no obligations regardless of whether an object is written into or +not. diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index b8d702e41aa0bb..d18719e4379b10 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -1461,7 +1461,7 @@ Mind that many more checkers are affected by dynamic memory modeling changes to some extent. Further reading for other annotations: -`Source Annotations in the Clang Static Analyzer <https://clang-analyzer.llvm.org/annotations.html>`_. +`Source Annotations in the Clang Static Analyzer <https://clang.llvm.org/docs/analyzer/user-docs/Annotations.html>`_. }]; } diff --git a/clang/www/analyzer/annotations.html b/clang/www/analyzer/annotations.html index bf0076e5142782..b19d47bce26620 100644 --- a/clang/www/analyzer/annotations.html +++ b/clang/www/analyzer/annotations.html @@ -3,6 +3,8 @@ <html> <head> <title>Source Annotations</title> + <link rel="canonical" href="https://clang.llvm.org/docs/analyzer/user-docs/Annotations.html"/> + <meta http-equiv="refresh" content="0;url=https://clang.llvm.org/docs/analyzer/user-docs/Annotations.html" /> <link type="text/css" rel="stylesheet" href="menu.css"> <link type="text/css" rel="stylesheet" href="content.css"> <script type="text/javascript" src="scripts/menu.js"></script> @@ -15,765 +17,11 @@ <div id="content"> <h1>Source Annotations</h1> +<p style="color:red; font-size:200%">This page is deprecated and will be removed in release 21.0</p> +<p>Its content was migrated to <a href="https://clang.llvm.org/docs/analyzer/user-docs/Annotations.html">the regular LLVM documentation</a>.</p> +<script>window.location='https://clang.llvm.org/docs/analyzer/user-docs/Annotations.html'</script> -<p>The Clang frontend supports several source-level annotations in the form of -<a href="https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html">GCC-style -attributes</a> and pragmas that can help make using the Clang Static Analyzer -more useful. These annotations can both help suppress false positives as well as -enhance the analyzer's ability to find bugs.</p> - -<p>This page gives a practical overview of such annotations. For more technical -specifics regarding Clang-specific annotations please see the Clang's list of <a -href="https://clang.llvm.org/docs/LanguageExtensions.html">language -extensions</a>. Details of "standard" GCC attributes (that Clang also -supports) can be found in the <a href="https://gcc.gnu.org/onlinedocs/gcc/">GCC -manual</a>, with the majority of the relevant attributes being in the section on -<a href="https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html">function -attributes</a>.</p> - -<p>Note that attributes that are labeled <b>Clang-specific</b> are not -recognized by GCC. Their use can be conditioned using preprocessor macros -(examples included on this page).</p> - -<h4>Specific Topics</h4> - -<ul> -<li><a href="#generic">Annotations to Enhance Generic Checks</a> - <ul> - <li><a href="#null_checking"><span>Null Pointer Checking</span></a> - <ul> - <li><a href="#attr_nonnull"><span>Attribute 'nonnull'</span></a></li> - </ul> - </li> - </ul> -</li> -<li><a href="#macosx">Mac OS X API Annotations</a> - <ul> - <li><a href="#cocoa_mem">Cocoa & Core Foundation Memory Management Annotations</a> - <ul> - <li><a href="#attr_ns_returns_retained">Attribute 'ns_returns_retained'</a></li> - <li><a href="#attr_ns_returns_not_retained">Attribute 'ns_returns_not_retained'</a></li> - <li><a href="#attr_cf_returns_retained">Attribute 'cf_returns_retained'</a></li> - <li><a href="#attr_cf_returns_not_retained">Attribute 'cf_returns_not_retained'</a></li> - <li><a href="#attr_ns_consumed">Attribute 'ns_consumed'</a></li> - <li><a href="#attr_cf_consumed">Attribute 'cf_consumed'</a></li> - <li><a href="#attr_ns_consumes_self">Attribute 'ns_consumes_self'</a></li> - </ul> - </li> - <li><a href="#osobject_mem">Libkern Memory Management Annotations</a> - <ul> - <li><a href="#attr_os_returns_retained">Attribute 'os_returns_retained'</a></li> - <li><a href="#attr_os_returns_not_retained">Attribute 'os_returns_not_retained'</a></li> - <li><a href="#attr_os_consumed">Attribute 'os_consumed'</a></li> - <li><a href="#attr_os_consumes_this">Attribute 'os_consumes_this'</a></li> - <li><a href="#os_out_parameters">Out Parameters</a></li> - </ul> - - </li> - </ul> -</li> -<li><a href="#custom_assertions">Custom Assertion Handlers</a> - <ul> - <li><a href="#attr_noreturn">Attribute 'noreturn'</a></li> - <li><a href="#attr_analyzer_noreturn">Attribute 'analyzer_noreturn'</a></li> - </ul> - </li> -</ul> - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> -<h2 id="generic">Annotations to Enhance Generic Checks</h2> -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<h3 id="null_checking">Null Pointer Checking</h3> - -<h4 id="attr_nonnull">Attribute 'nonnull'</h4> - -<p>The analyzer recognizes the GCC attribute 'nonnull', which indicates that a -function expects that a given function parameter is not a null pointer. Specific -details of the syntax of using the 'nonnull' attribute can be found in <a -href="https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-nonnull-function-attribute">GCC's -documentation</a>.</p> - -<p>Both the Clang compiler and GCC will flag warnings for simple cases where a -null pointer is directly being passed to a function with a 'nonnull' parameter -(e.g., as a constant). The analyzer extends this checking by using its deeper -symbolic analysis to track what pointer values are potentially null and then -flag warnings when they are passed in a function call via a 'nonnull' -parameter.</p> - -<p><b>Example</b></p> - -<pre class="code_example"> -<span class="command">$ cat test.m</span> -int bar(int*p, int q, int *r) __attribute__((nonnull(1,3))); - -int foo(int *p, int *q) { - return !p ? bar(q, 2, p) - : bar(p, 2, q); -} -</pre> - -<p>Running <tt>scan-build</tt> over this source produces the following -output:</p> - -<img src="images/example_attribute_nonnull.png" alt="example attribute nonnull"> - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> -<h2 id="macosx">Mac OS X API Annotations</h2> -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<h3 id="cocoa_mem">Cocoa & Core Foundation Memory Management -Annotations</h3> - -<!-- -<p>As described in <a href="/available_checks.html#retain_release">Available -Checks</a>, ---> -<p>The analyzer supports the proper management of retain counts for -both Cocoa and Core Foundation objects. This checking is largely based on -enforcing Cocoa and Core Foundation naming conventions for Objective-C methods -(Cocoa) and C functions (Core Foundation). Not strictly following these -conventions can cause the analyzer to miss bugs or flag false positives.</p> - -<p>One can educate the analyzer (and others who read your code) about methods or -functions that deviate from the Cocoa and Core Foundation conventions using the -attributes described here. However, you should consider using proper naming -conventions or the <a -href="https://clang.llvm.org/docs/LanguageExtensions.html#the-objc-method-family-attribute"><tt>objc_method_family</tt></a> -attribute, if applicable.</p> - -<h4 id="attr_ns_returns_retained">Attribute 'ns_returns_retained' -(Clang-specific)</h4> - -<p>The GCC-style (Clang-specific) attribute 'ns_returns_retained' allows one to -annotate an Objective-C method or C function as returning a retained Cocoa -object that the caller is responsible for releasing (via sending a -<tt>release</tt> message to the object). The Foundation framework defines a -macro <b><tt>NS_RETURNS_RETAINED</tt></b> that is functionally equivalent to the -one shown below.</p> - -<p><b>Placing on Objective-C methods</b>: For Objective-C methods, this -annotation essentially tells the analyzer to treat the method as if its name -begins with "alloc" or "new" or contains the word -"copy".</p> - -<p><b>Placing on C functions</b>: For C functions returning Cocoa objects, the -analyzer typically does not make any assumptions about whether or not the object -is returned retained. Explicitly adding the 'ns_returns_retained' attribute to C -functions allows the analyzer to perform extra checking.</p> - -<p><b>Example</b></p> - -<pre class="code_example"> -<span class="command">$ cat test.m</span> -#import <Foundation/Foundation.h> - -#ifndef __has_feature // Optional. -#define __has_feature(x) 0 // Compatibility with non-clang compilers. -#endif - -#ifndef NS_RETURNS_RETAINED -#if __has_feature(attribute_ns_returns_retained) -<span class="code_highlight">#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))</span> -#else -#define NS_RETURNS_RETAINED -#endif -#endif - -@interface MyClass : NSObject {} -- (NSString*) returnsRetained <span class="code_highlight">NS_RETURNS_RETAINED</span>; -- (NSString*) alsoReturnsRetained; -@end - -@implementation MyClass -- (NSString*) returnsRetained { - return [[NSString alloc] initWithCString:"no leak here"]; -} -- (NSString*) alsoReturnsRetained { - return [[NSString alloc] initWithCString:"flag a leak"]; -} -@end -</pre> - -<p>Running <tt>scan-build</tt> on this source file produces the following output:</p> - -<img src="images/example_ns_returns_retained.png" alt="example returns retained"> - -<h4 id="attr_ns_returns_not_retained">Attribute 'ns_returns_not_retained' -(Clang-specific)</h4> - -<p>The 'ns_returns_not_retained' attribute is the complement of '<a -href="#attr_ns_returns_retained">ns_returns_retained</a>'. Where a function or -method may appear to obey the Cocoa conventions and return a retained Cocoa -object, this attribute can be used to indicate that the object reference -returned should not be considered as an "owning" reference being -returned to the caller. The Foundation framework defines a -macro <b><tt>NS_RETURNS_NOT_RETAINED</tt></b> that is functionally equivalent to -the one shown below.</p> - -<p>Usage is identical to <a -href="#attr_ns_returns_retained">ns_returns_retained</a>. When using the -attribute, be sure to declare it within the proper macro that checks for -its availability, as it is not available in earlier versions of the analyzer:</p> - -<pre class="code_example"> -<span class="command">$ cat test.m</span> -#ifndef __has_feature // Optional. -#define __has_feature(x) 0 // Compatibility with non-clang compilers. -#endif - -#ifndef NS_RETURNS_NOT_RETAINED -#if __has_feature(attribute_ns_returns_not_retained) -<span class="code_highlight">#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))</span> -#else -#define NS_RETURNS_NOT_RETAINED -#endif -#endif -</pre> - -<h4 id="attr_cf_returns_retained">Attribute 'cf_returns_retained' -(Clang-specific)</h4> - -<p>The GCC-style (Clang-specific) attribute 'cf_returns_retained' allows one to -annotate an Objective-C method or C function as returning a retained Core -Foundation object that the caller is responsible for releasing. The -CoreFoundation framework defines a macro <b><tt>CF_RETURNS_RETAINED</tt></b> -that is functionally equivalent to the one shown below.</p> - -<p><b>Placing on Objective-C methods</b>: With respect to Objective-C methods., -this attribute is identical in its behavior and usage to 'ns_returns_retained' -except for the distinction of returning a Core Foundation object instead of a -Cocoa object. - -This distinction is important for the following reason: -as Core Foundation is a C API, -the analyzer cannot always tell that a pointer return value refers to a -Core Foundation object. -In contrast, it is -trivial for the analyzer to recognize if a pointer refers to a Cocoa object -(given the Objective-C type system). - -<p><b>Placing on C functions</b>: When placing the attribute -'cf_returns_retained' on the declarations of C functions, the analyzer -interprets the function as:</p> - -<ol> - <li>Returning a Core Foundation Object</li> - <li>Treating the function as if it its name -contained the keywords "create" or "copy". This means the -returned object as a +1 retain count that must be released by the caller, either -by sending a <tt>release</tt> message (via toll-free bridging to an Objective-C -object pointer), or calling <tt>CFRelease</tt> or a similar function.</li> -</ol> - -<p><b>Example</b></p> - -<pre class="code_example"> -<span class="command">$ cat test.m</span> -$ cat test.m -#import <Cocoa/Cocoa.h> - -#ifndef __has_feature // Optional. -#define __has_feature(x) 0 // Compatibility with non-clang compilers. -#endif - -#ifndef CF_RETURNS_RETAINED -#if __has_feature(attribute_cf_returns_retained) -<span class="code_highlight">#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))</span> -#else -#define CF_RETURNS_RETAINED -#endif -#endif - -@interface MyClass : NSObject {} -- (NSDate*) returnsCFRetained <span class="code_highlight">CF_RETURNS_RETAINED</span>; -- (NSDate*) alsoReturnsRetained; -- (NSDate*) returnsNSRetained <span class="code_highlight">NS_RETURNS_RETAINED</span>; -@end - -<span class="code_highlight">CF_RETURNS_RETAINED</span> -CFDateRef returnsRetainedCFDate() { - return CFDateCreate(0, CFAbsoluteTimeGetCurrent()); -} - -@implementation MyClass -- (NSDate*) returnsCFRetained { - return (NSDate*) returnsRetainedCFDate(); <b><i>// No leak.</i></b> -} - -- (NSDate*) alsoReturnsRetained { - return (NSDate*) returnsRetainedCFDate(); <b><i>// Always report a leak.</i></b> -} - -- (NSDate*) returnsNSRetained { - return (NSDate*) returnsRetainedCFDate(); <b><i>// Report a leak when using GC.</i></b> -} -@end -</pre> - -<p>Running <tt>scan-build</tt> on this example produces the following output:</p> - -<img src="images/example_cf_returns_retained.png" alt="example returns retained"> - -<h4 id="attr_cf_returns_not_retained">Attribute 'cf_returns_not_retained' -(Clang-specific)</h4> - -<p>The 'cf_returns_not_retained' attribute is the complement of '<a -href="#attr_cf_returns_retained">cf_returns_retained</a>'. Where a function or -method may appear to obey the Core Foundation or Cocoa conventions and return -a retained Core Foundation object, this attribute can be used to indicate that -the object reference returned should not be considered as an -"owning" reference being returned to the caller. The -CoreFoundation framework defines a macro <b><tt>CF_RETURNS_NOT_RETAINED</tt></b> -that is functionally equivalent to the one shown below.</p> - -<p>Usage is identical to <a -href="#attr_cf_returns_retained">cf_returns_retained</a>. When using the -attribute, be sure to declare it within the proper macro that checks for -its availability, as it is not available in earlier versions of the analyzer:</p> - -<pre class="code_example"> -<span class="command">$ cat test.m</span> -#ifndef __has_feature // Optional. -#define __has_feature(x) 0 // Compatibility with non-clang compilers. -#endif - -#ifndef CF_RETURNS_NOT_RETAINED -#if __has_feature(attribute_cf_returns_not_retained) -<span class="code_highlight">#define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))</span> -#else -#define CF_RETURNS_NOT_RETAINED -#endif -#endif -</pre> - -<h4 id="attr_ns_consumed">Attribute 'ns_consumed' -(Clang-specific)</h4> - -<p>The 'ns_consumed' attribute can be placed on a specific parameter in either -the declaration of a function or an Objective-C method. It indicates to the -static analyzer that a <tt>release</tt> message is implicitly sent to the -parameter upon completion of the call to the given function or method. The -Foundation framework defines a macro <b><tt>NS_RELEASES_ARGUMENT</tt></b> that -is functionally equivalent to the <tt>NS_CONSUMED</tt> macro shown below.</p> - -<p><b>Example</b></p> - -<pre class="code_example"> -<span class="command">$ cat test.m</span> -#ifndef __has_feature // Optional. -#define __has_feature(x) 0 // Compatibility with non-clang compilers. -#endif - -#ifndef NS_CONSUMED -#if __has_feature(attribute_ns_consumed) -<span class="code_highlight">#define NS_CONSUMED __attribute__((ns_consumed))</span> -#else -#define NS_CONSUMED -#endif -#endif - -void consume_ns(id <span class="code_highlight">NS_CONSUMED</span> x); - -void test() { - id x = [[NSObject alloc] init]; - consume_ns(x); <b><i>// No leak!</i></b> -} - -@interface Foo : NSObject -+ (void) releaseArg:(id) <span class="code_highlight">NS_CONSUMED</span> x; -+ (void) releaseSecondArg:(id)x second:(id) <span class="code_highlight">NS_CONSUMED</span> y; -@end - -void test_method() { - id x = [[NSObject alloc] init]; - [Foo releaseArg:x]; <b><i>// No leak!</i></b> -} - -void test_method2() { - id a = [[NSObject alloc] init]; - id b = [[NSObject alloc] init]; - [Foo releaseSecondArg:a second:b]; <b><i>// 'a' is leaked, but 'b' is released.</i></b> -} -</pre> - -<h4 id="attr_cf_consumed">Attribute 'cf_consumed' -(Clang-specific)</h4> - -<p>The 'cf_consumed' attribute is practically identical to <a -href="#attr_ns_consumed">ns_consumed</a>. The attribute can be placed on a -specific parameter in either the declaration of a function or an Objective-C -method. It indicates to the static analyzer that the object reference is -implicitly passed to a call to <tt>CFRelease</tt> upon completion of the call -to the given function or method. The CoreFoundation framework defines a macro -<b><tt>CF_RELEASES_ARGUMENT</tt></b> that is functionally equivalent to the -<tt>CF_CONSUMED</tt> macro shown below.</p> - -<p>Operationally this attribute is nearly identical to 'ns_consumed'.</p> - -<p><b>Example</b></p> - -<pre class="code_example"> -<span class="command">$ cat test.m</span> -#ifndef __has_feature // Optional. -#define __has_feature(x) 0 // Compatibility with non-clang compilers. -#endif - -#ifndef CF_CONSUMED -#if __has_feature(attribute_cf_consumed) -<span class="code_highlight">#define CF_CONSUMED __attribute__((cf_consumed))</span> -#else -#define CF_CONSUMED -#endif -#endif - -void consume_cf(id <span class="code_highlight">CF_CONSUMED</span> x); -void consume_CFDate(CFDateRef <span class="code_highlight">CF_CONSUMED</span> x); - -void test() { - id x = [[NSObject alloc] init]; - consume_cf(x); <b><i>// No leak!</i></b> -} - -void test2() { - CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); - consume_CFDate(date); <b><i>// No leak, including under GC!</i></b> - -} - -@interface Foo : NSObject -+ (void) releaseArg:(CFDateRef) <span class="code_highlight">CF_CONSUMED</span> x; -@end - -void test_method() { - CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); - [Foo releaseArg:date]; <b><i>// No leak!</i></b> -} -</pre> - -<h4 id="attr_ns_consumes_self">Attribute 'ns_consumes_self' -(Clang-specific)</h4> - -<p>The 'ns_consumes_self' attribute can be placed only on an Objective-C method -declaration. It indicates that the receiver of the message is -"consumed" (a single reference count decremented) after the message -is sent. This matches the semantics of all "init" methods.</p> - -<p>One use of this attribute is declare your own init-like methods that do not -follow the standard Cocoa naming conventions.</p> - -<p><b>Example</b></p> - -<pre class="code_example"> -#ifndef __has_feature -#define __has_feature(x) 0 // Compatibility with non-clang compilers. -#endif - -#ifndef NS_CONSUMES_SELF -#if __has_feature((attribute_ns_consumes_self)) -<span class="code_highlight">#define NS_CONSUMES_SELF __attribute__((ns_consumes_self))</span> -#else -#define NS_CONSUMES_SELF -#endif -#endif - -@interface MyClass : NSObject -- initWith:(MyClass *)x; -- nonstandardInitWith:(MyClass *)x <span class="code_highlight">NS_CONSUMES_SELF</span> NS_RETURNS_RETAINED; -@end -</pre> - -<p>In this example, <tt>-nonstandardInitWith:</tt> has the same ownership -semantics as the init method <tt>-initWith:</tt>. The static analyzer will -observe that the method consumes the receiver, and then returns an object with -a +1 retain count.</p> - -<p>The Foundation framework defines a macro <b><tt>NS_REPLACES_RECEIVER</tt></b> -which is functionally equivalent to the combination of <tt>NS_CONSUMES_SELF</tt> -and <tt>NS_RETURNS_RETAINED</tt> shown above.</p> - -<h3 id="osobject_mem">Libkern Memory Management Annotations</h3> - -<p><a - href="https://developer.apple.com/documentation/kernel/osobject?language=objc">Libkern</a> -requires developers to inherit all heap allocated objects from <tt>OSObject</tt> -and to perform manual reference counting. -The reference counting model is very similar to MRR (manual retain-release) mode in -<a href="https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html">Objective-C</a> -or to CoreFoundation reference counting. -Freshly-allocated objects start with a reference count of 1, -and calls to <tt>retain</tt> increment it, -while calls to <tt>release</tt> decrement it. -The object is deallocated whenever its reference count reaches zero.</p> - -<p>Manually incrementing and decrementing reference counts is error-prone: -over-retains lead to leaks, and over-releases lead to uses-after-free. -The analyzer can help the programmer to check for unbalanced -retain/release calls.</p> - -<p>The reference count checking is based on the principle of -<em>locality</em>: it should be possible to establish correctness -(lack of leaks/uses after free) by looking at each function body, -and the declarations (not the definitions) of all the functions it interacts -with.</p> - -<p>In order to support such reasoning, it should be possible to <em>summarize</em> -the behavior of each function, with respect to reference count -of its returned values and attributes.</p> - -<p>By default, the following summaries are assumed:</p> -<ul> - <li>All functions starting with <tt>get</tt> or <tt>Get</tt>, - unless they are returning subclasses of <tt>OSIterator</tt>, - are assumed to be returning at +0. - That is, the caller has no reference - count <em>obligations</em> with respect to the reference count of the returned object - and should leave it untouched. - </li> - - <li> - All other functions are assumed to return at +1. - That is, the caller has an <em>obligation</em> to release such objects. - </li> - - <li> - Functions are assumed not to change the reference count of their parameters, - including the implicit <tt>this</tt> parameter. - </li> -</ul> - -<p>These summaries can be overriden with the following -<a href="https://clang.llvm.org/docs/AttributeReference.html#os-returns-not-retained">attributes</a>:</p> - -<h4 id="attr_os_returns_retained">Attribute 'os_returns_retained'</h4> - -<p>The <tt>os_returns_retained</tt> attribute (accessed through the macro <tt> -LIBKERN_RETURNS_RETAINED</tt>) plays a role identical to <a -href="#attr_ns_returns_retained">ns_returns_retained</a> for functions -returning <tt>OSObject</tt> subclasses. -The attribute indicates that it is a callers responsibility to release the -returned object. -</p> - - -<h4 id="attr_os_returns_not_retained">Attribute 'os_returns_not_retained'</h4> - -<p>The <tt>os_returns_not_retained</tt> attribute (accessed through the macro <tt> -LIBKERN_RETURNS_NOT_RETAINED</tt>) plays a role identical to <a -href="#attr_ns_returns_not_retained">ns_returns_not_retained</a> for functions -returning <tt>OSObject</tt> subclasses. -The attribute indicates that the caller should not change the retain -count of the returned object. -</p> - -<h5>Example</h5> - -<pre class="code_example"> -class MyClass { - OSObject *f; - LIBKERN_RETURNS_NOT_RETAINED OSObject *myFieldGetter(); -} - - -// Note that the annotation only has to be applied to the function declaration. -OSObject * MyClass::myFieldGetter() { - return f; -} -</pre> - -<h4 id="attr_os_consumed">Attribute 'os_consumed'</h4> - -<p>Similarly to <a href="#attr_ns_consumed">ns_consumed</a> attribute, -<tt>os_consumed</tt> (accessed through <tt>LIBKERN_CONSUMED</tt>) attribute, -applied to a parameter, -indicates that the call to the function <em>consumes</em> the parameter: -the callee should either release it or store it and release it in the destructor, -while the caller should assume one is subtracted from the reference count -after the call.</p> - -<pre class="code_example"> -IOReturn addToList(LIBKERN_CONSUMED IOPMinformee *newInformee); -</pre> - -<h4 id="attr_os_consumes_this">Attribute 'os_consumes_this'</h4> - -<p>Similarly to <a href="#attr_ns_consumes_self">ns_consumes_self</a>, -the <tt>os_consumes_self</tt> attribute indicates that the method call -<em>consumes</em> the implicit <tt>this</tt> argument: the caller -should assume one was subtracted from the reference count of the object -after the call, and the callee has on obligation to either -release the argument, or store it and eventually release it in the -destructor.</p> - -<pre class="code_example"> -void addThisToList(OSArray *givenList) LIBKERN_CONSUMES_THIS; -</pre> - -<h4 id="os_out_parameters">Out Parameters</h4> - -A function can also return an object to a caller by a means of an out parameter -(a pointer-to-OSObject-pointer is passed, and a callee writes a pointer to an -object into an argument). -Currently the analyzer does not track unannotated out -parameters by default, but with annotations we distinguish four separate cases: - -<p><b>1. Non-retained out parameters</b>, identified using - <tt>LIBKERN_RETURNS_NOT_RETAINED</tt> applied to parameters, e.g.:</p> - -<pre class="code_example"> -void getterViaOutParam(LIBKERN_RETURNS_NOT_RETAINED OSObject **obj) -</pre> - -<p>Such functions write a non-retained object into an out parameter, and the -caller has no further obligations.</p> - -<p><b>2. Retained out parameters</b>, -identified using <tt>LIBKERN_RETURNS_RETAINED</tt>:</p> -<pre class="code_example"> -void getterViaOutParam(LIBKERN_RETURNS_NOT_RETAINED OSObject **obj) -</pre> -<p> -In such cases a retained object is written into an out parameter, which the caller has then to release in order to avoid a leak. -</p> - -<p>These two cases are simple - but in practice a functions returning an out-parameter usually also return a return code, and then an out parameter may or may not be written, which conditionally depends on the exit code, e.g.:</p> - -<pre class="code_example"> -bool maybeCreateObject(LIBKERN_RETURNS_RETAINED OSObject **obj); -</pre> - -<p>For such functions, the usual semantics is that an object is written into on "success", and not written into on "failure".<p> - -<p>For <tt>LIBKERN_RETURNS_RETAINED</tt> we assume the following definition of -success:</p> - -<p>For functions returning <tt>OSReturn</tt> or <tt>IOReturn</tt> -(any typedef to <tt>kern_return_t</tt>) success is defined as having an output of zero (<tt>kIOReturnSuccess</tt> is zero). -For all others, success is non-zero (e.g. non-nullptr for pointers)</p> - -<p><b>3. Retained out parameters on zero return</b> -The annotation <tt>LIBKERN_RETURNS_RETAINED_ON_ZERO</tt> states -that a retained object is written into if and only if the function returns a zero value:</p> - -<pre class="code_example"> -bool OSUnserializeXML(void *data, LIBKERN_RETURNS_RETAINED_ON_ZERO OSString **errString); -</pre> - -<p>Then the caller has to release an object if the function has returned zero.</p> - -<p><b>4. Retained out parameters on non-zero return</b> -Similarly, <tt>LIBKERN_RETURNS_RETAINED_ON_NONZERO</tt> specifies that a -retained object is written into the parameter if and only if the function has -returned a non-zero value.</p> - -<p>Note that for non-retained out parameters conditionals do not matter, as the -caller has no obligations regardless of whether an object is written into or -not.</p> - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> -<h2 id="custom_assertions">Custom Assertion Handlers</h2> -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<p>The analyzer exploits code assertions by pruning off paths where the -assertion condition is false. The idea is capture any program invariants -specified in the assertion that the developer may know but is not immediately -apparent in the code itself. In this way assertions make implicit assumptions -explicit in the code, which not only makes the analyzer more accurate when -finding bugs, but can help others better able to understand your code as well. -It can also help remove certain kinds of analyzer false positives by pruning off -false paths.</p> - -<p>In order to exploit assertions, however, the analyzer must understand when it -encounters an "assertion handler." Typically assertions are -implemented with a macro, with the macro performing a check for the assertion -condition and, when the check fails, calling an assertion handler. For example, consider the following code -fragment:</p> - -<pre class="code_example"> -void foo(int *p) { - assert(p != NULL); -} -</pre> - -<p>When this code is preprocessed on Mac OS X it expands to the following:</p> - -<pre class="code_example"> -void foo(int *p) { - (__builtin_expect(!(p != NULL), 0) ? __assert_rtn(__func__, "t.c", 4, "p != NULL") : (void)0); -} -</pre> - -<p>In this example, the assertion handler is <tt>__assert_rtn</tt>. When called, -most assertion handlers typically print an error and terminate the program. The -analyzer can exploit such semantics by ending the analysis of a path once it -hits a call to an assertion handler.</p> - -<p>The trick, however, is that the analyzer needs to know that a called function -is an assertion handler; otherwise the analyzer might assume the function call -returns and it will continue analyzing the path where the assertion condition -failed. This can lead to false positives, as the assertion condition usually -implies a safety condition (e.g., a pointer is not null) prior to performing -some action that depends on that condition (e.g., dereferencing a pointer).</p> - -<p>The analyzer knows about several well-known assertion handlers, but can -automatically infer if a function should be treated as an assertion handler if -it is annotated with the 'noreturn' attribute or the (Clang-specific) -'analyzer_noreturn' attribute. Note that, currently, clang does not support -these attributes on Objective-C methods and C++ methods.</p> - -<h4 id="attr_noreturn">Attribute 'noreturn'</h4> - -<p>The 'noreturn' attribute is a GCC-attribute that can be placed on the -declarations of functions. It means exactly what its name implies: a function -with a 'noreturn' attribute should never return.</p> - -<p>Specific details of the syntax of using the 'noreturn' attribute can be found -in <a -href="https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-noreturn-function-attribute">GCC's -documentation</a>.</p> - -<p>Not only does the analyzer exploit this information when pruning false paths, -but the compiler also takes it seriously and will generate different code (and -possibly better optimized) under the assumption that the function does not -return.</p> - -<p><b>Example</b></p> - -<p>On Mac OS X, the function prototype for <tt>__assert_rtn</tt> (declared in -<tt>assert.h</tt>) is specifically annotated with the 'noreturn' attribute:</p> - -<pre class="code_example"> -void __assert_rtn(const char *, const char *, int, const char *) <span class="code_highlight">__attribute__((__noreturn__))</span>; -</pre> - -<h4 id="attr_analyzer_noreturn">Attribute 'analyzer_noreturn' (Clang-specific)</h4> - -<p>The Clang-specific 'analyzer_noreturn' attribute is almost identical to -'noreturn' except that it is ignored by the compiler for the purposes of code -generation.</p> - -<p>This attribute is useful for annotating assertion handlers that actually -<em>can</em> return, but for the purpose of using the analyzer we want to -pretend that such functions do not return.</p> - -<p>Because this attribute is Clang-specific, its use should be conditioned with -the use of preprocessor macros.</p> - -<p><b>Example</b> - -<pre class="code_example"> -#ifndef CLANG_ANALYZER_NORETURN -#if __has_feature(attribute_analyzer_noreturn) -<span class="code_highlight">#define CLANG_ANALYZER_NORETURN __attribute__((analyzer_noreturn))</span> -#else -#define CLANG_ANALYZER_NORETURN -#endif -#endif - -void my_assert_rtn(const char *, const char *, int, const char *) <span class="code_highlight">CLANG_ANALYZER_NORETURN</span>; -</pre> - -</div> -</div> +</div> <!-- content --> +</div> <!-- page --> </body> </html> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits