[cfe-commits] r124790 - /cfe/trunk/www/compatibility.html
John McCall
rjmccall at apple.com
Thu Feb 3 02:56:31 PST 2011
Author: rjmccall
Date: Thu Feb 3 04:56:31 2011
New Revision: 124790
URL: http://llvm.org/viewvc/llvm-project?rev=124790&view=rev
Log:
Rework the __block jump-checking section, including a justification of
why this bug can go uncaught.
Modified:
cfe/trunk/www/compatibility.html
Modified: cfe/trunk/www/compatibility.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/compatibility.html?rev=124790&r1=124789&r2=124790&view=diff
==============================================================================
--- cfe/trunk/www/compatibility.html (original)
+++ cfe/trunk/www/compatibility.html Thu Feb 3 04:56:31 2011
@@ -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;
-
- __block int x;
- x = 1;
- return x;
+int fetch_object_state(struct MyObject *c) {
+ if (!c->active) goto error;
+
+ __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>
More information about the cfe-commits
mailing list