C23 attribute specifiers

C23 specification added C++-like attribute specifiers to C. C attribute specifiers add metadata to declarations and definitions. The metadata can be used by the compiler and by the developer to help understand the code intent.

Commonly used attributes such as [[maybe_unused]] and [[fallthrough]] suppress compiler warnings.

Compilers including GCC ≥ 11 have __has_c_attribute() to check if an attribute is supported by the compiler–even if the command line specified standard is older.

maybe_unused attribute

To enable code to fallback to no attribute with older compilers, use logic in header file like:

#if !defined(__has_c_attribute)
#  define __has_c_attribute(x) 0
#endif

#if __has_c_attribute(maybe_unused)
#  define MAYBE_UNUSED [[maybe_unused]]
#else
#  define MAYBE_UNUSED
#endif

then in the definition:

int windows_fun(int x, MAYBE_UNUSED int y) {

#ifdef _WIN32
  return y;
#else
  return x;
#endif
}

On non-Windows systems, the compiler would have issued a warning about y being an unused argument. The [[maybe_unused]] attribute suppresses that warning.

fallthrough attribute

The [[fallthrough]] attribute is used to indicate that a fall-through in a switch statement is intentional. This attribute can be used to suppress warnings about missing break statements in a switch block.

In declaration (header) file do like:

#ifndef __has_c_attribute
#define __has_c_attribute(x) 0
#endif
#if __has_c_attribute(fallthrough)
// GCC >= 11
#define FALLTHROUGH [[fallthrough]]
#elif defined(__GNUC__) && __GNUC__ >= 7 || defined(__clang__) && __clang_major__ >= 12
#define FALLTHROUGH __attribute__((fallthrough))
#else
#define FALLTHROUGH
#endif

then in the definition:

switch (x) {
  case 1:
    x++;
    FALLTHROUGH;
  case 2:
    x--;
}