diff --git a/p99/p99_block.h b/p99/p99_block.h
index 523c432be958e88af592bafe3139ec301e00e4c8..ab1dad2fb37abd6477d71e03fe310d23f92fb397 100644
--- a/p99/p99_block.h
+++ b/p99/p99_block.h
@@ -37,7 +37,6 @@
 #define P00 P99_FILEID(blk)
 
 #define P00_BLK_GEN(BEFORE, COND, ...) for (P00_ROBUST(BEFORE); (COND) && P00; (__VA_ARGS__), P00 = 0)
-#define P00_BLK_BEFAFT(BEFORE, ...) P00_BLK_GEN(P00_ROBUST(BEFORE), true, __VA_ARGS__)
 #define P00_BLK_BEFORE(...) for (__VA_ARGS__; P00; P00 = 0)
 #define P00_BLK_AFTER(...) P00_BLK_BEFAFT(, (__VA_ARGS__))
 #define P00_BLK_CONDITIONAL(...) for (; (__VA_ARGS__) && P00; P00 = 0)
@@ -73,6 +72,81 @@ P99_PREFER(                                                            \
   goto P99_FILEID(p00_label_, NAME); ) P99_FILEID(p00_label_, NAME):
 
 
+/**
+ ** @addtogroup validity Checking code validity
+ ** @{
+ **/
+
+#define P00_INHIBIT(NAME, EXT) P99_PASTE3(p00_inhibit_, NAME, EXT)
+
+
+/**
+ ** @brief Declare a feature @a NAME that can be compile time
+ ** inhibited or allowed in certain parts of code.
+ **
+ ** @see P99_INHIBIT
+ ** @see P99_ALLOW
+ ** @see P99_INHIBIT_CHECK
+ ** @see P99_CHECK_RETURN for an example
+ **/
+#define P99_DECLARE_INHIBIT(NAME) enum { P00_INHIBIT(NAME,) = 0 }
+
+/**
+ ** @brief Error out at compile time if @a NAME is inhibited.
+ **
+ ** @see P99_DECLARE_INHIBIT
+ **/
+#define P99_INHIBIT_CHECK(NAME)                                         \
+switch (P99_STRINGIFY(P00_INHIBIT(NAME,))[P00_INHIBIT(NAME,)]) default:
+
+
+/**
+ ** @brief Inhibit the use of feature @a NAME inside the dependent code.
+ **
+ ** @see P99_DECLARE_INHIBIT
+ ** @see P99_ALLOW
+ **/
+#define P99_INHIBIT(NAME)                                               \
+P00_BLK_START                                                           \
+for (unsigned const*const P00_INHIBIT(NAME,) = 0; !P00_INHIBIT(NAME,) && P00; P00 = 0)
+
+
+/**
+ ** @brief Allow the use of feature @a NAME inside the dependent code.
+ **
+ ** @see P99_DECLARE_INHIBIT
+ ** @see P99_INHIBIT
+ **/
+#define P99_ALLOW(NAME)                                                 \
+P00_BLK_START                                                           \
+P00_BLK_DECL(unsigned const, P00_INHIBIT(NAME,), 0)
+
+
+P99_DECLARE_INHIBIT(RETURN);
+
+#ifdef P99_CHECK_RETURN
+#define return P99_INHIBIT_CHECK(RETURN) return
+#endif
+
+#ifdef P00_DOXYGEN
+/**
+ ** @brief Insert code checks for bare @c return statements inside
+ ** ::P99_UNWIND_PROTECT
+ **
+ ** This check is not on by default, you should only enable it during
+ ** development via, e.g, a <code>-DP99_CHECK_RETURN</code> compiler
+ ** option.
+ **/
+#define P99_CHECK_RETURN
+#endif
+
+/** @}
+ **/
+
+
+#define P00_BLK_BEFAFT(BEFORE, ...)                     \
+P99_INHIBIT(RETURN)                                     \
+P00_BLK_GEN(P00_ROBUST(BEFORE), true, __VA_ARGS__)
 
 #ifdef P00_DOXYGEN
 /**
@@ -412,11 +486,15 @@ struct p00_inhibitor {
  ** ::P99_UNWIND are only guaranteed to have their new value in the
  ** protected part if they are declared @c volatile.
  **
+ ** @warning There should be no plain @c return statement in the
+ ** depending block before the ::P99_PROTECT label.
+ **
  ** @see "test-p99-block.c" for a more sophisticated example of nested
  ** ::P99_UNWIND_PROTECT.
  ** @see ::P99_UNWIND
  ** @see ::P99_UNWIND_RETURN for a replacement of @c return that
  **      respects the protected parts
+ ** @see ::P99_CHECK_RETURN to check for suspicious bare @c return statements
  ** @see ::p99_unwind_code
  ** @see ::p99_unwind_level
  **/
@@ -426,7 +504,7 @@ P00_BLK_START
    inside this construct. Only the lowest level variable will be                          \
    needed but since we don't know our level yet, we have to declare                       \
    this at every level. */                                                                \
- P00_BLK_BEFAFT(auto p00_jmp_buf p00_unwind_return = P00_ROBUST(P00_JMP_BUF_INITIALIZER), \
+P00_BLK_BEFAFT(auto p00_jmp_buf p00_unwind_return = P00_ROBUST(P00_JMP_BUF_INITIALIZER),  \
                /* returning can only be on because it was set by                          \
                   P99_UNWIND_RETURN and we fell of the edge after all                     \
                   P99_PROTECT clauses */                                                  \
@@ -529,13 +607,17 @@ P00_BLK_START                                                       \
     /* assign before we unwind all the way down */                  \
     p00_unwind_bottom->returning = 1;                               \
     P99_UNWIND(-p99_unwind_return);                                 \
-  } else return
+  } else P99_ALLOW(RETURN) return
 
 /**
  ** @brief The pseudo label to which we jump when we unwind the stack
  ** with ::P99_UNWIND.
  **
- ** Each ::P99_UNWIND_PROTECT may contain at most one such label.
+ ** @warning ::P99_UNWIND_PROTECT may contain at most one such label.
+ **
+ ** @warning Other than a normal C label, ::P99_PROTECT must be at a
+ ** location where several statements can be placed. In particular, it
+ ** should not be the direct dependent of a conditional.
  **
  ** @see P99_UNWIND_PROTECT
  ** @see P99_UNWIND_RETURN
@@ -544,6 +626,7 @@ P00_BLK_START                                                       \
  ** @see p99_unwind_level
  **/
 #define P99_PROTECT                                                     \
+P99_DECLARE_INHIBIT(RETURN);                                            \
 if (0) {                                                                \
   /* The switch expression of the surrounding switch from               \
      P99_UNWIND_PROTECT should only have values true and false. So      \
@@ -576,6 +659,7 @@ P99_PROTECTED_BLOCK(assert((EXPR) && "failed on entry"), assert((EXPR) && "faile
 /** @}
  **/
 
+
 /* Disable bogus warnings that are provoked by the code in this file. */
 
 P99_IF_COMPILER(INTEL, warning(disable: 589)) /* transfer of control bypasses initialization of... */