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>