diff options
author | John McCall <rjmccall@apple.com> | 2011-02-03 10:56:31 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-02-03 10:56:31 +0000 |
commit | 504b369f8de741241e0304f7801c84aca3ed922e (patch) | |
tree | 73dcda0561712c6d50df3a0cfa842f3d2ddfcc9e /www | |
parent | 5ae84f274c4e1e9400fbd5d4aaa1d0328644a23e (diff) | |
download | clang-504b369f8de741241e0304f7801c84aca3ed922e.tar.gz |
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
Diffstat (limited to 'www')
-rw-r--r-- | www/compatibility.html | 55 |
1 files changed, 28 insertions, 27 deletions
diff --git a/www/compatibility.html b/www/compatibility.html index b273487452..ddfddc7fa9 100644 --- a/www/compatibility.html +++ b/www/compatibility.html @@ -199,50 +199,51 @@ example, one could use:</p> <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> |