Check for __attribute__((fallthrough)) support is sometimes incorrect
Description
Clang added support for the gcc-style fallthrough attribute (i.e. __attribute__((fallthrough))
) in version 10. However, __has_attribute(fallthrough)
will return 1 in C mode in older versions, even though they only support the C++11 fallthrough attribute. At best, the unsupported attribute is simply ignored; at worst, it causes errors like this:
In file included from rdata.c:604:
In file included from ./code.h:66:
./rdata/generic/opt_41.c:236:4: error: expected expression
FALLTHROUGH;
^
../../lib/isc/include/isc/util.h:65:21: note: expanded from macro 'FALLTHROUGH'
#define FALLTHROUGH __attribute__((fallthrough))
^
Request
The C2x fallthrough attribute has the advantages of being supported in the broadest range of clang versions (added in version 9) and being easy to check for support. Therefore, I think it would be best to use it if possible, and fall back to not using an attribute for clang versions that don't have it. This patch implements that:
--- lib/isc/include/isc/util.h.orig 2022-05-09 19:32:19.000000000 +1000
+++ lib/isc/include/isc/util.h 2022-05-20 02:36:59.000000000 +1000
@@ -35,6 +35,10 @@
#define __has_attribute(x) 0
#endif /* if !defined(__has_attribute) */
+#if !defined(__has_c_attribute)
+#define __has_c_attribute(x) 0
+#endif /* if !defined(__has_c_attribute) */
+
#if !defined(__has_feature)
#define __has_feature(x) 0
#endif /* if !defined(__has_feature) */
@@ -61,7 +65,9 @@
#define ISC_NONSTRING
#endif /* __GNUC__ */
-#if __GNUC__ >= 7 || __has_attribute(fallthrough)
+#if __has_c_attribute(fallthrough)
+#define FALLTHROUGH [[fallthrough]]
+#elif !defined(__clang__) && (__GNUC__ >= 7 || __has_attribute(fallthrough))
#define FALLTHROUGH __attribute__((fallthrough))
#else
/* clang-format off */
Links / references
https://github.com/llvm/llvm-project/commit/1e0affb6e564b7361b0aadb38805f26deff4ecfc