diff options
author | Carlo Zancanaro <carlo@pc-4w14-0.cs.usyd.edu.au> | 2012-10-15 17:10:06 +1100 |
---|---|---|
committer | Carlo Zancanaro <carlo@pc-4w14-0.cs.usyd.edu.au> | 2012-10-15 17:10:06 +1100 |
commit | be1de4be954c80875ad4108e0a33e8e131b2f2c0 (patch) | |
tree | 1fbbecf276bf7c7bdcbb4dd446099d6d90eaa516 /clang/www/analyzer/annotations.html | |
parent | c4626a62754862d20b41e8a46a3574264ea80e6d (diff) | |
parent | f1bd2e48c5324d3f7cda4090c87f8a5b6f463ce2 (diff) |
Merge branch 'master' of ssh://bitbucket.org/czan/honours
Diffstat (limited to 'clang/www/analyzer/annotations.html')
-rw-r--r-- | clang/www/analyzer/annotations.html | 602 |
1 files changed, 602 insertions, 0 deletions
diff --git a/clang/www/analyzer/annotations.html b/clang/www/analyzer/annotations.html new file mode 100644 index 0000000..9e3583d --- /dev/null +++ b/clang/www/analyzer/annotations.html @@ -0,0 +1,602 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" + "http://www.w3.org/TR/html4/strict.dtd"> +<html> +<head> + <title>Source Annotations</title> + <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> +</head> +<body> + +<div id="page"> +<!--#include virtual="menu.html.incl"--> + +<div id="content"> + +<h1>Source Annotations</h1> + +<p>The Clang frontend supports several source-level annotations in the form of +<a href="http://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="http://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="http://gcc.gnu.org/onlinedocs/gcc/">GCC +manual</a>, with the majority of the relevant attributes being in the section on +<a href="http://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> + </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="http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html#index-g_t_0040code_007bnonnull_007d-function-attribute-2263">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.</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).</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>Important note when using Garbage Collection</b>: Note that the analyzer +interprets this attribute slightly differently when using Objective-C garbage +collection (available on Mac OS 10.5+). When analyzing Cocoa code that uses +garbage collection, "alloc" methods are assumed to return an object +that is managed by the garbage collector (and thus doesn't have a retain count +the caller must balance). These same assumptions are applied to methods or +functions annotated with 'ns_returns_retained'. If you are returning a Core +Foundation object (which may not be managed by the garbage collector) you should +use 'cf_returns_retained'.</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.</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. + +<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 two reasons:</p> + +<ul> + <li>Core Foundation objects are not automatically managed by the Objective-C + garbage collector.</li> + <li>Because 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). +</ul> + +<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), calling <tt>CFRelease</tt> (or similar function), or using +<tt>CFMakeCollectable</tt> to register the object with the Objective-C garbage +collector.</li> +</ol> + +<p><b>Example</b></p> + +<p>In this example, observe the difference in output when the code is compiled +to not use garbage collection versus when it is compiled to only use garbage +collection (<tt>-fobjc-gc-only</tt>).</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"> + +<p>When the above code is compiled using Objective-C garbage collection (i.e., +code is compiled with the flag <tt>-fobjc-gc</tt> or <tt>-fobjc-gc-only</tt>), +<tt>scan-build</tt> produces both the above error (with slightly different text +to indicate the code uses garbage collection) as well as the following warning, +which indicates a leak that occurs <em>only</em> when using garbage +collection:</p> + +<img src="images/example_cf_returns_retained_gc.png" alt="example returns retained gc"> + +<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.</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. + +<p><b>Important note when using Garbage Collection</b>: Note that the analyzer +essentially ignores this attribute when code is compiled to use Objective-C +garbage collection. This is because the <tt>release</tt> message does nothing +when using GC. If the underlying function/method uses something like +<tt>CFRelease</tt> to decrement the reference count, consider using +the <a href="#attr_cf_consumed">cf_consumed</a> attribute instead.</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.</p> + +<p>Operationally this attribute is nearly identical to ns_consumed +with the main difference that the reference count decrement still occurs when using Objective-C garbage +collection (which is import for Core Foundation types, which are not automatically garbage collected).</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> + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> +<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.</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="http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html#index-g_t_0040code_007bnoreturn_007d-function-attribute-2264">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> +</body> +</html> + |