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 &lt;stdarg.h&gt;
+
+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 &lt;stdarg.h&gt;
+
+void test(int x, ...) {
+  va_list args;
+  int y = va_arg(args, int); // warn
+}
+</pre></div>
+<div class="example"><pre>
+#include &lt;stdarg.h&gt;
+
+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 &lt;stdarg.h&gt;
+
+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

Reply via email to