Tweak the WUFFS_BASE__FALLTHROUGH macro

When compiling with "-Werror,-Wimplicit-fallthrough", commit c90cc7b6
tweaked WUFFS_BASE__FALLTHROUGH to work with newer clang compilers, when
defined(__cplusplus) is false, but inadvertently broke older clang
compilers, when __has_attribute(fallthrough) is false.

This commit reverts some of c90cc7b6 to handle more cases. The next two
commits will delete the WUFFS_BASE__FALLTHROUGH macro entirely and
render this commit redundant, as the whole business is proving more
trouble than it's worth. But it's checked into the commit history in
case somebody in the future wants to revive WUFFS_BASE__FALLTHROUGH.
diff --git a/internal/cgen/base/fundamental-private.h b/internal/cgen/base/fundamental-private.h
index 8247011..78ccca0 100644
--- a/internal/cgen/base/fundamental-private.h
+++ b/internal/cgen/base/fundamental-private.h
@@ -31,17 +31,24 @@
 
 // Denote intentional fallthroughs for -Wimplicit-fallthrough.
 //
-// The two #if lines are deliberately separate. Combining the two conditions
-// into a single "#if foo && bar" line would not be portable. See
+// The next two #if lines are deliberately separate. Combining the two
+// conditions into a single "#if foo && bar" line would not be portable. See
 // https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fattribute.html
 #if defined(__has_attribute)
 #if __has_attribute(fallthrough)
 #define WUFFS_BASE__FALLTHROUGH __attribute__((fallthrough))
+#endif
+#endif
+// Newer C/C++ compilers are handled above. Other compilers are handled below.
+#if !defined(WUFFS_BASE__FALLTHROUGH)
+// Chromium's clang-based PNaCl compiler does define __has_attribute, but
+// "__has_attribute(fallthrough)" is false and "__attribute__((fallthrough))"
+// has no effect. Use the C++ style "[[clang::fallthrough]]" instead.
+#if defined(__clang__) && defined(__cplusplus) && (__cplusplus >= 201103L)
+#define WUFFS_BASE__FALLTHROUGH [[clang::fallthrough]]
 #else
 #define WUFFS_BASE__FALLTHROUGH
 #endif
-#else
-#define WUFFS_BASE__FALLTHROUGH
 #endif
 
 // Use switch cases for coroutine suspension points, similar to the technique
diff --git a/internal/cgen/data/data.go b/internal/cgen/data/data.go
index 162eb44..236f299 100644
--- a/internal/cgen/data/data.go
+++ b/internal/cgen/data/data.go
@@ -29,9 +29,9 @@
 	""
 
 const BaseFundamentalPrivateH = "" +
-	"// ---------------- Fundamentals\n\n// WUFFS_BASE__MAGIC is a magic number to check that initializers are called.\n// It's not foolproof, given C doesn't automatically zero memory before use,\n// but it should catch 99.99% of cases.\n//\n// Its (non-zero) value is arbitrary, based on md5sum(\"wuffs\").\n#define WUFFS_BASE__MAGIC ((uint32_t)0x3CCB6C71)\n\n// WUFFS_BASE__DISABLED is a magic number to indicate that a non-recoverable\n// error was previously encountered.\n//\n// Its (non-zero) value is arbitrary, based on md5sum(\"disabled\").\n#define WUFFS_BASE__DISABLED ((uint32_t)0x075AE3D2)\n\n// Denote intentional fallthroughs for -Wimplicit-fallthrough.\n//\n// The two #if lines are deliberately separate. Combining the two conditions\n// into a single \"#if foo && bar\" line would not be portable. See\n// https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fattribute.html\n#if defined(__has_attribute)\n#if __has_attribute(fallthrough)\n#define WUFFS_BASE__FALLTHROUGH __attribute__((fallthrough))\n#else\n#define WUFFS_BASE__FALLTHROUGH\n" +
-	"#endif\n#else\n#define WUFFS_BASE__FALLTHROUGH\n#endif\n\n// Use switch cases for coroutine suspension points, similar to the technique\n// in https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html\n//\n// We use trivial macros instead of an explicit assignment and case statement\n// so that clang-format doesn't get confused by the unusual \"case\"s.\n#define WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0 case 0:;\n#define WUFFS_BASE__COROUTINE_SUSPENSION_POINT(n) \\\n  coro_susp_point = n;                            \\\n  WUFFS_BASE__FALLTHROUGH;                        \\\n  case n:;\n\n#define WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(n) \\\n  if (!status.repr) {                                           \\\n    goto ok;                                                    \\\n  } else if (*status.repr != '$') {                             \\\n    goto exit;                                                  \\\n  }                                                             \\\n  coro_susp_point = n;                                " +
-	"          \\\n  goto suspend;                                                 \\\n  case n:;\n\n// Clang also defines \"__GNUC__\".\n#if defined(__GNUC__)\n#define WUFFS_BASE__LIKELY(expr) (__builtin_expect(!!(expr), 1))\n#define WUFFS_BASE__UNLIKELY(expr) (__builtin_expect(!!(expr), 0))\n#else\n#define WUFFS_BASE__LIKELY(expr) (expr)\n#define WUFFS_BASE__UNLIKELY(expr) (expr)\n#endif\n\n" +
+	"// ---------------- Fundamentals\n\n// WUFFS_BASE__MAGIC is a magic number to check that initializers are called.\n// It's not foolproof, given C doesn't automatically zero memory before use,\n// but it should catch 99.99% of cases.\n//\n// Its (non-zero) value is arbitrary, based on md5sum(\"wuffs\").\n#define WUFFS_BASE__MAGIC ((uint32_t)0x3CCB6C71)\n\n// WUFFS_BASE__DISABLED is a magic number to indicate that a non-recoverable\n// error was previously encountered.\n//\n// Its (non-zero) value is arbitrary, based on md5sum(\"disabled\").\n#define WUFFS_BASE__DISABLED ((uint32_t)0x075AE3D2)\n\n// Denote intentional fallthroughs for -Wimplicit-fallthrough.\n//\n// The next two #if lines are deliberately separate. Combining the two\n// conditions into a single \"#if foo && bar\" line would not be portable. See\n// https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fattribute.html\n#if defined(__has_attribute)\n#if __has_attribute(fallthrough)\n#define WUFFS_BASE__FALLTHROUGH __attribute__((fallthrough))\n#endif\n#endif\n// Newer C/C++ comp" +
+	"ilers are handled above. Other compilers are handled below.\n#if !defined(WUFFS_BASE__FALLTHROUGH)\n// Chromium's clang-based PNaCl compiler does define __has_attribute, but\n// \"__has_attribute(fallthrough)\" is false and \"__attribute__((fallthrough))\"\n// has no effect. Use the C++ style \"[[clang::fallthrough]]\" instead.\n#if defined(__clang__) && defined(__cplusplus) && (__cplusplus >= 201103L)\n#define WUFFS_BASE__FALLTHROUGH [[clang::fallthrough]]\n#else\n#define WUFFS_BASE__FALLTHROUGH\n#endif\n#endif\n\n// Use switch cases for coroutine suspension points, similar to the technique\n// in https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html\n//\n// We use trivial macros instead of an explicit assignment and case statement\n// so that clang-format doesn't get confused by the unusual \"case\"s.\n#define WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0 case 0:;\n#define WUFFS_BASE__COROUTINE_SUSPENSION_POINT(n) \\\n  coro_susp_point = n;                            \\\n  WUFFS_BASE__FALLTHROUGH;                        \\\n  case n:;\n\n" +
+	"#define WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(n) \\\n  if (!status.repr) {                                           \\\n    goto ok;                                                    \\\n  } else if (*status.repr != '$') {                             \\\n    goto exit;                                                  \\\n  }                                                             \\\n  coro_susp_point = n;                                          \\\n  goto suspend;                                                 \\\n  case n:;\n\n// Clang also defines \"__GNUC__\".\n#if defined(__GNUC__)\n#define WUFFS_BASE__LIKELY(expr) (__builtin_expect(!!(expr), 1))\n#define WUFFS_BASE__UNLIKELY(expr) (__builtin_expect(!!(expr), 0))\n#else\n#define WUFFS_BASE__LIKELY(expr) (expr)\n#define WUFFS_BASE__UNLIKELY(expr) (expr)\n#endif\n\n" +
 	"" +
 	"// --------\n\nstatic inline wuffs_base__empty_struct  //\nwuffs_base__ignore_status(wuffs_base__status z) {\n  return wuffs_base__make_empty_struct();\n}\n\nstatic inline wuffs_base__status  //\nwuffs_base__status__ensure_not_a_suspension(wuffs_base__status z) {\n  if (z.repr && (*z.repr == '$')) {\n    z.repr = wuffs_base__error__cannot_return_a_suspension;\n  }\n  return z;\n}\n\n" +
 	"" +
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index aeb4379..334d9fd 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -10111,17 +10111,24 @@
 
 // Denote intentional fallthroughs for -Wimplicit-fallthrough.
 //
-// The two #if lines are deliberately separate. Combining the two conditions
-// into a single "#if foo && bar" line would not be portable. See
+// The next two #if lines are deliberately separate. Combining the two
+// conditions into a single "#if foo && bar" line would not be portable. See
 // https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fattribute.html
 #if defined(__has_attribute)
 #if __has_attribute(fallthrough)
 #define WUFFS_BASE__FALLTHROUGH __attribute__((fallthrough))
+#endif
+#endif
+// Newer C/C++ compilers are handled above. Other compilers are handled below.
+#if !defined(WUFFS_BASE__FALLTHROUGH)
+// Chromium's clang-based PNaCl compiler does define __has_attribute, but
+// "__has_attribute(fallthrough)" is false and "__attribute__((fallthrough))"
+// has no effect. Use the C++ style "[[clang::fallthrough]]" instead.
+#if defined(__clang__) && defined(__cplusplus) && (__cplusplus >= 201103L)
+#define WUFFS_BASE__FALLTHROUGH [[clang::fallthrough]]
 #else
 #define WUFFS_BASE__FALLTHROUGH
 #endif
-#else
-#define WUFFS_BASE__FALLTHROUGH
 #endif
 
 // Use switch cases for coroutine suspension points, similar to the technique