/* If configuration machinery hasn't determined a flavour, then we'll take a
* rough guess based on compiler versions.
*/
-#if !defined(FINALLY_CONFIG_FLAVOUR) && \
- !defined(__clang__) && FINALLY__GCC_P(3, 3)
+#if !defined(FINALLY_CONFIG_FLAVOUR) && defined(__clang__)
+# if FINALLY__CLANG_P(2, 5)
+# ifndef __BLOCKS__
+# error "Clang detected, but blocks support is not available. \
+This isn't going to work. Try setting the `-fblocks' compiler option."
+# endif
+# define FINALLY_CONFIG_FLAVOUR CLANG_BLOCKS
+# else
+# define FINALLY_CONFIG_FLAVOUR NIL
+# endif
+#endif
+
+#if !defined(FINALLY_CONFIG_FLAVOUR) && FINALLY__GCC_P(3, 3)
# define FINALLY_CONFIG_FLAVOUR GCC_NESTED_FUNCTIONS
#endif
/* Before we start, a note about compatibility. We're using pretty esoteric
* compiler features here, and not all compilers support them. I'm most
- * interested in GCC, which will work fine. This isn't going to work for
- * other compilers, but lots of them try to impersonate GCC, and it's just
- * not worth the effort to try to see through their lies.
+ * interested in GCC, which will work fine, and I'm just a tiny bit
+ * interested in Clang, so there's support for that too. This isn't going to
+ * work for other compilers, but lots of them try to impersonate GCC, and
+ * it's just not worth the effort to try to see through their lies.
*
* So the rules are: if you include this header file, you've either already
* made an effort to check that it's likely to work (e.g., by using the
/* Flavour selection machinery. */
#define FINALLY__FLAVOUR_NIL -1
#define FINALLY__FLAVOUR_GCC_NESTED_FUNCTIONS 1
+#define FINALLY__FLAVOUR_CLANG_BLOCKS 2
#define FINALLY__SELECTED_FLAVOUR \
FINALLY__GLUE(FINALLY__FLAVOUR_, FINALLY_CONFIG_FLAVOUR)
__attribute__((__unused__, __cleanup__(FINALLY__TMP(tag##__fn)))) \
int FINALLY__TMP(tag##__var)
+#elif FINALLY__GLUE(FINALLY__FLAVOUR_, FINALLY_CONFIG_FLAVOUR) == \
+ FINALLY__FLAVOUR_CLANG_BLOCKS
+ /* We're being compiled by Clang, so we're messing with the ugly `blocks'
+ * syntax. Unfortunately, blocks capture names from their outer
+ * environment by copying rather than by reference, so a `FINALLY' block
+ * is insensitive to changes to variables since its establishment. As a
+ * result of this, we declare a bug.
+ */
+
+# define FINALLY_BUG_CAPTURE_COPIES 1
+
+ /* We'll need a separate cleanup handler, because we're not allowed to
+ * define a local function to do this. We'll attach this as the cleanup
+ * handler for the block containing the code that we want to run.
+ */
+ static __inline__ void _finally__runblk(void (^*_blk)(void))
+ { (*_blk)(); }
+
+ /* Now we're ready for the actual macro definition. */
+# define FINALLY_TAGGED(tag, body) \
+ __attribute__((__unused__, __cleanup__(_finally__runblk))) \
+ void (^FINALLY__TMP(tag##__blk))(void) = ^{ body }
+
#elif FINALLY__GLUE(FINALLY__FLAVOUR_, FINALLY_CONFIG_FLAVOUR) == \
FINALLY__GLUE(FINALLY__FLAVOUR_, NIL)
/* We don't have a flavour to support this environment. */
# error "Internal error: `FINALLY_CONFIG_FLAVOUR' bungled."
#endif
+/* Check for bugs. */
+#if defined(FINALLY_BUG_CAPTURE_COPIES) && \
+ (!defined(FINALLY_TOLERATE_BUG_CAPTURE_COPIES) || \
+ !FINALLY_TOLERATE_BUG_CAPTURE_COPIES)
+# error "Implementation captures variables by copying rather than by \
+reference. Define `FINALLY_BUG_CAPTURE_COPIES' if you don't mind."
+#endif
+
/* We now have `FINALLY_TAGGED'; defining `FINALLY' is easy. The TAG here is
* guaranteed not conflict with any call on `FINALLY_TAGGED', since TAGs are
* required to be identifiers.