Rework the __block jump-checking section, including a justification of
why this bug can go uncaught.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124790 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/www/compatibility.html b/www/compatibility.html
index b273487..ddfddc7 100644
--- a/www/compatibility.html
+++ b/www/compatibility.html
@@ -199,50 +199,51 @@
 <h3 id="blocks-in-protected-scope">Jumps to within <tt>__block</tt> variable scope</h3>
 <!-- ======================================================================= -->
 
-<p>Clang disallows jumps into the scope of a <tt>__block</tt> variable, similar
-to the manner in which both GCC and Clang disallow jumps into the scope of
-variables which have user defined constructors (in C++).</p>
-
-<p>Variables marked with <tt>__block</tt> require special runtime initialization
-before they can be used. A jump into the scope of a <tt>__block</tt> variable
-would bypass this initialization and therefore the variable cannot safely be
-used.</p>
-
-<p>For example, consider the following code fragment:</p>
+<p>Clang disallows jumps into the scope of a <tt>__block</tt>
+variable.  Variables marked with <tt>__block</tt> require special
+runtime initialization. A jump into the scope of a <tt>__block</tt>
+variable bypasses this initialization, leaving the variable's metadata
+in an invalid state.  Consider the following code fragment:</p>
 
 <pre>
-int f0(int c) {
-  if (c)
-    goto error;
+int fetch_object_state(struct MyObject *c) {
+  if (!c->active) goto error;
 
-  __block int x;
-  x = 1;
-  return x;
+  __block int result;
+  run_specially_somehow(^{ result = c->state; });
+  return result;
 
  error:
-  x = 0;
-  return x;
+  fprintf(stderr, "error while fetching object state");
+  return -1;
 }
 </pre>
 
-<p>GCC accepts this code, but it will crash at runtime along the error path,
-because the runtime setup for the storage backing the <tt>x</tt> variable will
-not have been initialized. Clang rejects this code with a hard error:</p>
+<p>GCC accepts this code, but it produces code that will usually crash
+when <code>result</code> goes out of scope if the jump is taken.  (It's
+possible for this bug to go undetected because it often won't crash if
+the stack is fresh, i.e. still zeroed.)  Therefore, Clang rejects this
+code with a hard error:</p>
 
 <pre>
 t.c:3:5: error: goto into protected scope
     goto error;
     ^
 t.c:5:15: note: jump bypasses setup of __block variable
-  __block int x;
+  __block int result;
               ^
 </pre>
 
-<p>Some instances of this construct may be safe if the variable is never used
-after the jump target, however the protected scope checker does not check the
-uses of the variable, only the scopes in which it is visible. You should rewrite
-your code to put the <tt>__block</tt> variables in a scope which is only visible
-where they are used.</p>
+<p>The fix is to rewrite the code to not require jumping into a
+<tt>__block</tt> variable's scope, e.g. by limiting that scope:</p>
+
+<pre>
+  {
+    __block int result;
+    run_specially_somehow(^{ result = c->state; });
+    return result;
+  }
+</pre>
 
 <!-- ======================================================================= -->
 <h3 id="block-variable-initialization">Non-initialization of <tt>__block</tt>