Szelethus updated this revision to Diff 170920. Szelethus edited the summary of this revision.
https://reviews.llvm.org/D53069 Files: www/analyzer/available_checks.html
Index: www/analyzer/available_checks.html =================================================================== --- www/analyzer/available_checks.html +++ www/analyzer/available_checks.html @@ -38,11 +38,13 @@ <li><a href="#core_checkers">Core Checkers</a> model core language features and perform general-purpose checks such as division by zero, null pointer dereference, usage of uninitialized values, etc.</li> <li><a href="#cplusplus_checkers">C++ Checkers</a> perform C++-specific checks</li> <li><a href="#deadcode_checkers">Dead Code Checkers</a> check for unused code</li> +<li><a href="#llvm_checkers">LLVM Checkers</a> for LLVM developers</li> <li><a href="#nullability_checkers">Nullability Checkers</a> </li> <li><a href="#optin_checkers">Optin Checkers</a> </li> <li><a href="#osx_checkers">OS X Checkers</a> perform Objective-C-specific checks and check the use of Apple's SDKs (OS X and iOS)</li> <li><a href="#security_checkers">Security Checkers</a> check for insecure API usage and perform checks based on the CERT Secure Coding Standards</li> <li><a href="#unix_checkers">Unix Checkers</a> check the use of Unix and POSIX APIs</li> +<li><a href="#valist_checkers">Variable Argument Checkers</a></li> </ul> <!-- =========================== core =========================== --> @@ -369,6 +371,25 @@ <thead><tr><td>Name, Description</td><td>Example</td></tr></thead> <tbody> + + +<tr><td><div class="namedescr expandable"><span class="name"> +cplusplus.InnerPointer</span><span class="lang"> +(C++)</span><div class="descr"> +Check for inner pointers of C++ containers used after re/deallocation. +</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void log(const char *str); + +void test(int value) { + const char *msg = std::to_string(value).c_str(); + // msg points to the buffer of a temporary that is now destroyed + log(msg); // warn: inner pointer of container used after re/deallocation +} +</pre></div></div></td></tr> + + <tr><td><div class="namedescr expandable"><span class="name"> cplusplus.NewDelete</span><span class="lang"> (C++)</span><div class="descr"> @@ -435,6 +456,7 @@ } // warn </pre></div></div></td></tr> + </tbody></table> <!-- =========================== dead code =========================== --> @@ -458,6 +480,31 @@ </tbody></table> +<!-- =========================== llvm =========================== --> +<h3 id="llvm_checkers">LLVM Checkers</h3> +<table class="checkers"> +<colgroup><col class="namedescr"><col class="example"></colgroup> +<thead><tr><td>Name, Description</td><td>Example</td></tr></thead> + +<tbody> +<tr><td><div class="namedescr expandable"><span class="name"> +llvm.Conventions</span><span class="lang"> +(C)</span><div class="descr"> +Check code for LLVM codebase conventions: +<ul> + <li>A <code>StringRef</code> should not be bound to a temporary std::string + whose lifetime is shorter than the <code>StringRef</code>'s.</li> + <li>Clang AST nodes should not have fields that can allocate memory.</li> +</ul> +</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +<!-- TODO: Add examples. And also test files for this checker. --> +</pre></div></div></td></tr> + +</tbody></table> + + <!-- =========================== nullability =========================== --> <h3 id="nullability_checkers">Nullability Checkers</h3> <table class="checkers"> @@ -535,6 +582,21 @@ } </pre></div></div></td></tr> + +<tr><td><div class="namedescr expandable"><span class="name"> +nullability.NullableReturnedFromNonnull</span><span class="lang"> +(ObjC)</span><div class="descr"> +Warns when a nullable pointer is returned from a function that has _Nonnull return type.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +typedef struct Dummy { int val; } Dummy; + +Dummy *_Nonnull test(Dummy *_Nullable a) { + Dummy *p = a; + return p; // warn +} +</pre></div></div></td></tr> + </tbody></table> <!-- =========================== optin =========================== --> @@ -610,6 +672,95 @@ [alarmStateLabel setText:alarmText]; </pre></div></div></td></tr> + +<tr><td><div class="namedescr expandable"><span class="name"> +optin.performance.GCDAntipattern</span><span class="lang"> +(ObjC)</span><div class="descr"> +This checker finds a common performance anti-pattern in a code that uses Grand +Central dispatch. The anti-pattern involves emulating a synchronous call from an +asynchronous API using semaphores, as in the snippet below, where the +<code>requestCurrentTaskName</code> function makes an XPC call and then uses the +semaphore to block until the XPC call returns (example 1.).<br> +Usage of such a pattern in production code running on the main thread is +discouraged, as the main queue gets blocked waiting for the background queue, +which could be running at a lower priority, and unnecessary threads are spawned +in the process.<br> +In order to avoid the anti-pattern, the available alternatives are: +<ul> + <li>Use the synchronous version of the API, if available (as seen on example + 2.)</li> + <li>Alternatively, the API can be used in the asynchronous way.</li> +</ul> +</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +// Example 1. ++ (NSString *)requestCurrentTaskName { + __block NSString *taskName = nil; + dispatch_semaphore_t sema = dispatch_semaphore_create(0); + NSXPCConnection *connection = [[NSXPCConnection alloc] initWithServiceName:@"MyConnection"]; + id remoteObjectProxy = connection.remoteObjectProxy; + [remoteObjectProxy requestCurrentTaskName:^(NSString *task) { + taskName = task; + dispatch_semaphore_signal(sema); + }]; + dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); + return taskName; +} +</pre></div><div class="separator"></div> +<div class="example"><pre> +// Example 2. ++ (NSString *)requestCurrentTaskName { + __block NSString *taskName = nil; + NSXPCConnection *connection = [[NSXPCConnection alloc] initWithServiceName:@"MyConnection"]; + id remoteObjectProxy = [connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) { + NSLog(@"Error = %@", error); + + }]; + [remoteObjectProxy requestCurrentTaskName:^(NSString *task) { + taskName = task; + }]; + return taskName; +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +optin.performance.Padding</span><span class="lang"> +(C)</span><div class="descr"> +Check for excessively padded structs. +</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +class PaddedA { // warn: excessive padding + char c1; + int i; + char c2; +}; +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +optin.portability.UnixAPI</span><span class="lang"> +(C)</span><div class="descr"> +Finds implementation-defined behavior in UNIX/Posix functions. +<div class=functions> +calloc<br> +malloc<br> +realloc<br> +reallocf<br> +alloca, __builtin_alloca<br> +__builtin_alloca_with_align<br> +valloc</div> +</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void *f(int n) { + return malloc(n * 0 * sizeof(int)); // warn: Call to 'malloc' has an + // allocation size of 0 bytes +} +</pre></div></div></td></tr> + </tbody></table> <!-- =========================== OS X =========================== --> @@ -649,6 +800,9 @@ </pre></div></div></td></tr> +<!-- Describe osx.ObjCProperty. --> + + <tr><td><div class="namedescr expandable"><span class="name"> osx.SecKeychainAPI</span><span class="lang"> (C)</span><div class="descr"> @@ -732,7 +886,8 @@ <tr><td><div class="namedescr expandable"><span class="name"> osx.cocoa.AtSync</span><span class="lang"> (ObjC)</span><div class="descr"> -Check for nil pointers used as mutexes for <code>@synchronized</code>.</div></div></td> +Check for nil pointers used as mutexes for <code>@synchronized</code>. +</div></div></td> <td><div class="exampleContainer expandable"> <div class="example"><pre> void test(id x) { @@ -749,6 +904,38 @@ <tr><td><div class="namedescr expandable"><span class="name"> +osx.cocoa.AutoreleaseWrite</span><span class="lang"> +(ObjC)</span><div class="descr"> +Under ARC, function parameters which are pointers to pointers (e.g. +<code>NSError **</code>) are <code>__autoreleasing</code>. Writing to such +parameters inside autoreleasing pools might crash whenever the parameter +outlives the pool. Detecting such crashes may be difficult, as usage of +autorelease pool is usually hidden inside the called functions implementation. +</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +BOOL writeToErrorWithIterator(NSError *__autoreleasing* error, NSArray *a) { [a enumerateObjectsUsingBlock:^{ + *error = [NSError errorWithDomain:1]; + }]; +} +</pre></div><div class="separator"></div> +<div class="example"><pre> +BOOL writeToErrorInBlockFromCFunc(NSError *__autoreleasing* error) { + dispatch_semaphore_t sem = dispatch_semaphore_create(0l); + dispatch_async(queue, ^{ + if (error) { + *error = [NSError errorWithDomain:1]; + } + dispatch_semaphore_signal(sem); + }); + + dispatch_semaphore_wait(sem, 100); + return 0; +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> osx.cocoa.ClassRelease</span><span class="lang"> (ObjC)</span><div class="descr"> Check for sending <code>retain</code>, <code>release</code>, or <code> @@ -965,6 +1152,29 @@ <tr><td><div class="namedescr expandable"><span class="name"> +osx.cocoa.RunLoopAutoreleaseLeak</span><span class="lang"> +(ObjC)</span><div class="descr"> +Detects leaks resulting from allocating temporary autoreleased objects before +starting the main run loop. + +Checks for two antipatterns: +<ul> + <li>ObjCMessageExpr followed by <code>[[NSRunLoop mainRunLoop] run]</code> in + the same autorelease pool.</li> + <li>ObjCMessageExpr followed by <code>[[NSRunLoop mainRunLoop] run]</code> in + no autorelease pool.</li> +</ul> + +Any temporary objects autoreleased in code called in those expressions will not +be deallocated until the program exits, and are effectively leaks. +</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +<!-- TODO: Add examples. --> +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> osx.cocoa.SelfInit</span><span class="lang"> (ObjC)</span><div class="descr"> Check that <code>self</code> is properly initialized inside an initializer @@ -1571,6 +1781,74 @@ </tbody></table> + +<!-- =============================== va_list =============================== --> +<h3 id="valist_checkers">Variable Argument Checkers</h3> +<table class="checkers"> +<colgroup><col class="namedescr"><col class="example"></colgroup> +<thead><tr><td>Name, Description</td><td>Example</td></tr></thead> + +<tbody> +<tr><td><div class="namedescr expandable"><span class="name"> +valist.CopyToSelf</span><span class="lang"> +(C)</span><div class="descr"> +Calls to the <code>va_copy</code> macro should not copy onto itself.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +#include <stdarg.h> + +void test(int x, ...) { + va_list args; + va_start(args, x); + va_copy(args, args); // warn + va_end(args); +} +</pre></div></div></td></tr> + +<tr><td><div class="namedescr expandable"><span class="name"> +valist.Uninitialized</span><span class="lang"> +(C)</span><div class="descr"> +Calls to the <code>va_arg</code>, <code>va_copy</code>, or +<code>va_end</code> macro must happen after calling <code>va_start</code> and +before calling <code>va_end</code>.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +#include <stdarg.h> + +void test(int x, ...) { + va_list args; + int y = va_arg(args, int); // warn +} +</pre></div> +<div class="example"><pre> +#include <stdarg.h> + +void test(int x, ...) { + va_list args; + va_start(args, x); + va_end(args); + int z = va_arg(args, int); // warn +} +</pre></div></div></td></tr> + +<tr><td><div class="namedescr expandable"><span class="name"> +valist.Unterminated</span><span class="lang"> +(C)</span><div class="descr"> +Every <code>va_start</code> must be matched by a <code>va_end</code>. A va_list +can only be ended once.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +#include <stdarg.h> + +void test(int x, ...) { + va_list args; + va_start(args, x); + int y = x + va_arg(args, int); +} // warn: missing va_end +</pre></div></div></td></tr> + +</tbody></table> + </div> <!-- page --> </div> <!-- content --> </body>
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits