[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
Rework the __block jump-checking section, including a justification of
why this bug can go uncaught.


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
-<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>
-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;
-  x = 0;
-  return x;
+  fprintf(stderr, "error while fetching object state");
+  return -1;
-<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>
 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;
-<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>
+  {
+    __block int result;
+    run_specially_somehow(^{ result = c->state; });
+    return result;
+  }
 <!-- ======================================================================= -->
 <h3 id="block-variable-initialization">Non-initialization of <tt>__block</tt>

More information about the cfe-commits mailing list