Browse Source

Add `compiler_support.h` (#25274)

Pablo Martínez 1 year ago
parent
commit
955809bd5a
36 changed files with 142 additions and 81 deletions
  1. 2 2
      docs/quantum_painter_qff.md
  2. 4 4
      docs/quantum_painter_qgf.md
  3. 2 1
      drivers/lcd/st7565.c
  4. 3 1
      drivers/oled/oled_driver.c
  5. 4 3
      drivers/sensors/azoteq_iqs5xx.h
  6. 3 2
      drivers/sensors/pmw33xx_common.h
  7. 5 4
      lib/fnv/qmk_fnv_type_validation.c
  8. 4 2
      lib/python/qmk/cli/generate/community_modules.py
  9. 7 5
      platforms/atomic_util.h
  10. 3 1
      platforms/avr/drivers/i2c_slave.h
  11. 4 2
      platforms/avr/gpio.h
  12. 3 1
      platforms/chibios/chibios_config.h
  13. 4 2
      platforms/chibios/drivers/wear_leveling/wear_leveling_rp2040_flash.c
  14. 3 1
      quantum/audio/audio.h
  15. 3 1
      quantum/backlight/backlight.h
  16. 15 0
      quantum/compiler_support.h
  17. 3 1
      quantum/connection/connection.h
  18. 3 1
      quantum/haptic.h
  19. 2 4
      quantum/keycode_config.h
  20. 7 6
      quantum/keymap_introspection.c
  21. 3 1
      quantum/led_matrix/led_matrix_types.h
  22. 4 3
      quantum/nvm/eeprom/nvm_dynamic_keymap.c
  23. 3 1
      quantum/nvm/eeprom/nvm_eeprom_eeconfig_internal.h
  24. 5 4
      quantum/painter/qff.h
  25. 9 8
      quantum/painter/qgf.h
  26. 2 1
      quantum/painter/qp_draw_core.c
  27. 3 1
      quantum/painter/qp_internal.c
  28. 2 1
      quantum/painter/qp_internal_formats.h
  29. 3 1
      quantum/rgb_matrix/rgb_matrix_types.h
  30. 3 1
      quantum/rgblight/rgblight.h
  31. 5 3
      quantum/split_common/split_util.c
  32. 3 1
      quantum/split_common/transaction_id_define.h
  33. 2 1
      quantum/split_common/transport.c
  34. 3 1
      quantum/unicode/unicode.h
  35. 6 8
      quantum/wear_leveling/wear_leveling_internal.h
  36. 2 1
      tmk_core/protocol/vusb/vusb.c

+ 2 - 2
docs/quantum_painter_qff.md

@@ -44,7 +44,7 @@ typedef struct __attribute__((packed)) qff_font_descriptor_v1_t {
     uint8_t               compression_scheme;   // compression scheme, see below.
     uint8_t               transparency_index;   // palette index used for transparent pixels (not yet implemented)
 } qff_font_descriptor_v1_t;
-// _Static_assert(sizeof(qff_font_descriptor_v1_t) == (sizeof(qgf_block_header_v1_t) + 20), "qff_font_descriptor_v1_t must be 25 bytes in v1 of QFF");
+// STATIC_ASSERT(sizeof(qff_font_descriptor_v1_t) == (sizeof(qgf_block_header_v1_t) + 20), "qff_font_descriptor_v1_t must be 25 bytes in v1 of QFF");
 ```
 
 The values for `format`, `flags`, `compression_scheme`, and `transparency_index` match [QGF's frame descriptor block](quantum_painter_qgf#qgf-frame-descriptor), with the exception that the `delta` flag is ignored by QFF.
@@ -66,7 +66,7 @@ typedef struct __attribute__((packed)) qff_ascii_glyph_table_v1_t {
     qgf_block_header_v1_t header;  // = { .type_id = 0x01, .neg_type_id = (~0x01), .length = 285 }
     uint24_t glyph[95];            // 95 glyphs, 0x20..0x7E, see bits/masks above for values
 } qff_ascii_glyph_table_v1_t;
-// _Static_assert(sizeof(qff_ascii_glyph_table_v1_t) == (sizeof(qgf_block_header_v1_t) + 285), "qff_ascii_glyph_table_v1_t must be 290 bytes in v1 of QFF");
+// STATIC_ASSERT(sizeof(qff_ascii_glyph_table_v1_t) == (sizeof(qgf_block_header_v1_t) + 285), "qff_ascii_glyph_table_v1_t must be 290 bytes in v1 of QFF");
 ```
 
 ## Unicode glyph table {#qff-unicode-table}

+ 4 - 4
docs/quantum_painter_qgf.md

@@ -32,7 +32,7 @@ typedef struct __attribute__((packed)) qgf_block_header_v1_t {
     uint8_t neg_type_id;  // Negated type ID, used for detecting parsing errors
     uint24_t length;      // 24-bit blob length, allowing for block sizes of a maximum of 16MB
 } qgf_block_header_v1_t;
-// _Static_assert(sizeof(qgf_block_header_v1_t) == 5, "qgf_block_header_v1_t must be 5 bytes in v1 of QGF");
+// STATIC_ASSERT(sizeof(qgf_block_header_v1_t) == 5, "qgf_block_header_v1_t must be 5 bytes in v1 of QGF");
 ```
 The _length_ describes the number of octets in the data following the block header -- a block header may specify a _length_ of `0` if no blob is specified.
 
@@ -56,7 +56,7 @@ typedef struct __attribute__((packed)) qgf_graphics_descriptor_v1_t {
     uint16_t              image_height;         // in pixels
     uint16_t              frame_count;          // minimum of 1
 } qgf_graphics_descriptor_v1_t;
-// _Static_assert(sizeof(qgf_graphics_descriptor_v1_t) == (sizeof(qgf_block_header_v1_t) + 18), "qgf_graphics_descriptor_v1_t must be 23 bytes in v1 of QGF");
+// STATIC_ASSERT(sizeof(qgf_graphics_descriptor_v1_t) == (sizeof(qgf_block_header_v1_t) + 18), "qgf_graphics_descriptor_v1_t must be 23 bytes in v1 of QGF");
 ```
 
 ## Frame offset block {#qgf-frame-offset-descriptor}
@@ -95,7 +95,7 @@ typedef struct __attribute__((packed)) qgf_frame_v1_t {
     uint8_t               transparency_index;  // palette index used for transparent pixels (not yet implemented)
     uint16_t              delay;               // frame delay time for animations (in units of milliseconds)
 } qgf_frame_v1_t;
-// _Static_assert(sizeof(qgf_frame_v1_t) == (sizeof(qgf_block_header_v1_t) + 6), "qgf_frame_v1_t must be 11 bytes in v1 of QGF");
+// STATIC_ASSERT(sizeof(qgf_frame_v1_t) == (sizeof(qgf_block_header_v1_t) + 6), "qgf_frame_v1_t must be 11 bytes in v1 of QGF");
 ```
 
 If this frame is grayscale, the _frame descriptor block_ (or _frame delta block_ if flags denote a delta frame) is immediately followed by this frame's corresponding _frame data block_.
@@ -160,7 +160,7 @@ typedef struct __attribute__((packed)) qgf_delta_v1_t {
     uint16_t right;                // The right pixel location to to draw the delta image
     uint16_t bottom;               // The bottom pixel location to to draw the delta image
 } qgf_delta_v1_t;
-// _Static_assert(sizeof(qgf_delta_v1_t) == 13, "qgf_delta_v1_t must be 13 bytes in v1 of QGF");
+// STATIC_ASSERT(sizeof(qgf_delta_v1_t) == 13, "qgf_delta_v1_t must be 13 bytes in v1 of QGF");
 ```
 
 ## Frame data block {#qgf-frame-data-descriptor}

+ 2 - 1
drivers/lcd/st7565.c

@@ -19,6 +19,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include <string.h>
 
+#include "compiler_support.h"
 #include "keyboard.h"
 #include "progmem.h"
 #include "timer.h"
@@ -265,7 +266,7 @@ void st7565_write_char(const char data, bool invert) {
     static uint8_t st7565_temp_buffer[ST7565_FONT_WIDTH];
     memcpy(&st7565_temp_buffer, st7565_cursor, ST7565_FONT_WIDTH);
 
-    _Static_assert(sizeof(font) >= ((ST7565_FONT_END + 1 - ST7565_FONT_START) * ST7565_FONT_WIDTH), "ST7565_FONT_END references outside array");
+    STATIC_ASSERT(sizeof(font) >= ((ST7565_FONT_END + 1 - ST7565_FONT_START) * ST7565_FONT_WIDTH), "ST7565_FONT_END references outside array");
 
     // set the reder buffer data
     uint8_t cast_data = (uint8_t)data; // font based on unsigned type for index

+ 3 - 1
drivers/oled/oled_driver.c

@@ -23,6 +23,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #        include "keyboard.h"
 #    endif
 #endif
+
+#include "compiler_support.h"
 #include "oled_driver.h"
 #include OLED_FONT_H
 #include "timer.h"
@@ -601,7 +603,7 @@ void oled_write_char(const char data, bool invert) {
     static uint8_t oled_temp_buffer[OLED_FONT_WIDTH];
     memcpy(&oled_temp_buffer, oled_cursor, OLED_FONT_WIDTH);
 
-    _Static_assert(sizeof(font) >= ((OLED_FONT_END + 1 - OLED_FONT_START) * OLED_FONT_WIDTH), "OLED_FONT_END references outside array");
+    STATIC_ASSERT(sizeof(font) >= ((OLED_FONT_END + 1 - OLED_FONT_START) * OLED_FONT_WIDTH), "OLED_FONT_END references outside array");
 
     // set the reder buffer data
     uint8_t cast_data = (uint8_t)data; // font based on unsigned type for index

+ 4 - 3
drivers/sensors/azoteq_iqs5xx.h

@@ -4,6 +4,7 @@
 
 #pragma once
 
+#include "compiler_support.h"
 #include "i2c_master.h"
 #include "pointing_device.h"
 #include "util.h"
@@ -79,7 +80,7 @@ typedef struct {
     azoteq_iqs5xx_relative_xy_t      y;
 } azoteq_iqs5xx_base_data_t;
 
-_Static_assert(sizeof(azoteq_iqs5xx_base_data_t) == 10, "azoteq_iqs5xx_basic_report_t should be 10 bytes");
+STATIC_ASSERT(sizeof(azoteq_iqs5xx_base_data_t) == 10, "azoteq_iqs5xx_basic_report_t should be 10 bytes");
 
 typedef struct {
     uint8_t                     number_of_fingers;
@@ -87,7 +88,7 @@ typedef struct {
     azoteq_iqs5xx_relative_xy_t y;
 } azoteq_iqs5xx_report_data_t;
 
-_Static_assert(sizeof(azoteq_iqs5xx_report_data_t) == 5, "azoteq_iqs5xx_report_data_t should be 5 bytes");
+STATIC_ASSERT(sizeof(azoteq_iqs5xx_report_data_t) == 5, "azoteq_iqs5xx_report_data_t should be 5 bytes");
 
 typedef struct PACKED {
     bool sw_input : 1;
@@ -159,7 +160,7 @@ typedef struct PACKED {
     uint16_t                                     zoom_consecutive_distance;
 } azoteq_iqs5xx_gesture_config_t;
 
-_Static_assert(sizeof(azoteq_iqs5xx_gesture_config_t) == 24, "azoteq_iqs5xx_gesture_config_t should be 24 bytes");
+STATIC_ASSERT(sizeof(azoteq_iqs5xx_gesture_config_t) == 24, "azoteq_iqs5xx_gesture_config_t should be 24 bytes");
 
 typedef struct {
     uint16_t x_resolution;

+ 3 - 2
drivers/sensors/pmw33xx_common.h

@@ -10,6 +10,7 @@
 
 #pragma once
 
+#include "compiler_support.h"
 #include "keyboard.h"
 #include <stdint.h>
 #include "spi_master.h"
@@ -39,8 +40,8 @@ typedef struct __attribute__((packed)) {
     int16_t delta_y; // displacement on y directions.
 } pmw33xx_report_t;
 
-_Static_assert(sizeof(pmw33xx_report_t) == 6, "pmw33xx_report_t must be 6 bytes in size");
-_Static_assert(sizeof((pmw33xx_report_t){0}.motion) == 1, "pmw33xx_report_t.motion must be 1 byte in size");
+STATIC_ASSERT(sizeof(pmw33xx_report_t) == 6, "pmw33xx_report_t must be 6 bytes in size");
+STATIC_ASSERT(sizeof((pmw33xx_report_t){0}.motion) == 1, "pmw33xx_report_t.motion must be 1 byte in size");
 
 #if !defined(PMW33XX_CLOCK_SPEED)
 #    define PMW33XX_CLOCK_SPEED 2000000

+ 5 - 4
lib/fnv/qmk_fnv_type_validation.c

@@ -1,14 +1,15 @@
 // Copyright 2022 Nick Brassel (@tzarc)
 // SPDX-License-Identifier: GPL-2.0-or-later
 #include "fnv.h"
+#include "compiler_support.h"
 
 // This library was originally sourced from:
 //     http://www.isthe.com/chongo/tech/comp/fnv/index.html
 //
 // Version at the time of retrieval on 2022-06-26: v5.0.3
 
-_Static_assert(sizeof(long long) == 8, "long long should be 64 bits");
-_Static_assert(sizeof(unsigned long long) == 8, "unsigned long long should be 64 bits");
+STATIC_ASSERT(sizeof(long long) == 8, "long long should be 64 bits");
+STATIC_ASSERT(sizeof(unsigned long long) == 8, "unsigned long long should be 64 bits");
 
-_Static_assert(sizeof(Fnv32_t) == 4, "Fnv32_t should be 32 bits");
-_Static_assert(sizeof(Fnv64_t) == 8, "Fnv64_t should be 64 bits");
+STATIC_ASSERT(sizeof(Fnv32_t) == 4, "Fnv32_t should be 32 bits");
+STATIC_ASSERT(sizeof(Fnv64_t) == 8, "Fnv64_t should be 64 bits");

+ 4 - 2
lib/python/qmk/cli/generate/community_modules.py

@@ -52,7 +52,7 @@ def _render_keycodes(module_jsons):
             lines.append('')
     lines.append('    LAST_COMMUNITY_MODULE_KEY')
     lines.append('};')
-    lines.append('_Static_assert((int)LAST_COMMUNITY_MODULE_KEY <= (int)(QK_COMMUNITY_MODULE_MAX+1), "Too many community module keycodes");')
+    lines.append('STATIC_ASSERT((int)LAST_COMMUNITY_MODULE_KEY <= (int)(QK_COMMUNITY_MODULE_MAX+1), "Too many community module keycodes");')
     return lines
 
 
@@ -215,9 +215,11 @@ def generate_community_modules_h(cli):
         '#include <stdbool.h>',
         '#include <keycodes.h>',
         '',
+        '#include "compiler_support.h"',
+        '',
         '#define COMMUNITY_MODULES_API_VERSION_BUILDER(ver_major,ver_minor,ver_patch) (((((uint32_t)(ver_major))&0xFF) << 24) | ((((uint32_t)(ver_minor))&0xFF) << 16) | (((uint32_t)(ver_patch))&0xFF))',
         f'#define COMMUNITY_MODULES_API_VERSION COMMUNITY_MODULES_API_VERSION_BUILDER({ver_major},{ver_minor},{ver_patch})',
-        f'#define ASSERT_COMMUNITY_MODULES_MIN_API_VERSION(ver_major,ver_minor,ver_patch) _Static_assert(COMMUNITY_MODULES_API_VERSION_BUILDER(ver_major,ver_minor,ver_patch) <= COMMUNITY_MODULES_API_VERSION, "Community module requires a newer version of QMK modules API -- needs: " #ver_major "." #ver_minor "." #ver_patch ", current: {api_version}.")',
+        f'#define ASSERT_COMMUNITY_MODULES_MIN_API_VERSION(ver_major,ver_minor,ver_patch) STATIC_ASSERT(COMMUNITY_MODULES_API_VERSION_BUILDER(ver_major,ver_minor,ver_patch) <= COMMUNITY_MODULES_API_VERSION, "Community module requires a newer version of QMK modules API -- needs: " #ver_major "." #ver_minor "." #ver_patch ", current: {api_version}.")',
         '',
         'typedef struct keyrecord_t keyrecord_t; // forward declaration so we don\'t need to include quantum.h',
         '',

+ 7 - 5
platforms/atomic_util.h

@@ -15,17 +15,19 @@
  */
 #pragma once
 
+#include "compiler_support.h"
+
 // Macro to help make GPIO and other controls atomic.
 
 #ifndef IGNORE_ATOMIC_BLOCK
 #    if __has_include_next("atomic_util.h")
 #        include_next "atomic_util.h" /* Include the platforms atomic.h */
 #    else
-#        define ATOMIC_BLOCK _Static_assert(0, "ATOMIC_BLOCK not implemented")
-#        define ATOMIC_BLOCK_RESTORESTATE _Static_assert(0, "ATOMIC_BLOCK_RESTORESTATE not implemented")
-#        define ATOMIC_BLOCK_FORCEON _Static_assert(0, "ATOMIC_BLOCK_FORCEON not implemented")
-#        define ATOMIC_FORCEON _Static_assert(0, "ATOMIC_FORCEON not implemented")
-#        define ATOMIC_RESTORESTATE _Static_assert(0, "ATOMIC_RESTORESTATE not implemented")
+#        define ATOMIC_BLOCK STATIC_ASSERT(0, "ATOMIC_BLOCK not implemented")
+#        define ATOMIC_BLOCK_RESTORESTATE STATIC_ASSERT(0, "ATOMIC_BLOCK_RESTORESTATE not implemented")
+#        define ATOMIC_BLOCK_FORCEON STATIC_ASSERT(0, "ATOMIC_BLOCK_FORCEON not implemented")
+#        define ATOMIC_FORCEON STATIC_ASSERT(0, "ATOMIC_FORCEON not implemented")
+#        define ATOMIC_RESTORESTATE STATIC_ASSERT(0, "ATOMIC_RESTORESTATE not implemented")
 #    endif
 #else /* do nothing atomic macro */
 #    define ATOMIC_BLOCK(t) for (uint8_t __ToDo = 1; __ToDo; __ToDo = 0)

+ 3 - 1
platforms/avr/drivers/i2c_slave.h

@@ -22,6 +22,8 @@
 
 #pragma once
 
+#include "compiler_support.h"
+
 #ifndef I2C_SLAVE_REG_COUNT
 
 #    if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
@@ -33,7 +35,7 @@
 
 #endif // I2C_SLAVE_REG_COUNT
 
-_Static_assert(I2C_SLAVE_REG_COUNT < 256, "I2C target registers must be single byte");
+STATIC_ASSERT(I2C_SLAVE_REG_COUNT < 256, "I2C target registers must be single byte");
 
 extern volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT];
 

+ 4 - 2
platforms/avr/gpio.h

@@ -16,6 +16,8 @@
 #pragma once
 
 #include <avr/io.h>
+
+#include "compiler_support.h"
 #include "pin_defs.h"
 
 typedef uint8_t pin_t;
@@ -24,9 +26,9 @@ typedef uint8_t pin_t;
 
 #define gpio_set_pin_input(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF))
 #define gpio_set_pin_input_high(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
-#define gpio_set_pin_input_low(pin) _Static_assert(0, "GPIO pulldowns in input mode are not available on AVR")
+#define gpio_set_pin_input_low(pin) STATIC_ASSERT(0, "GPIO pulldowns in input mode are not available on AVR")
 #define gpio_set_pin_output_push_pull(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF))
-#define gpio_set_pin_output_open_drain(pin) _Static_assert(0, "Open-drain outputs are not available on AVR")
+#define gpio_set_pin_output_open_drain(pin) STATIC_ASSERT(0, "Open-drain outputs are not available on AVR")
 #define gpio_set_pin_output(pin) gpio_set_pin_output_push_pull(pin)
 
 #define gpio_write_pin_high(pin) (PORTx_ADDRESS(pin) |= _BV((pin)&0xF))

+ 3 - 1
platforms/chibios/chibios_config.h

@@ -15,6 +15,8 @@
  */
 #pragma once
 
+#include "compiler_support.h"
+
 #ifndef USB_VBUS_PIN
 #    define SPLIT_USB_DETECT // Force this on when dedicated pin is not used
 #endif
@@ -26,7 +28,7 @@
 #    define REALTIME_COUNTER_CLOCK 1000000
 
 #    define USE_GPIOV1
-#    define PAL_OUTPUT_TYPE_OPENDRAIN _Static_assert(0, "RP2040 has no Open Drain GPIO configuration, setting this is not possible");
+#    define PAL_OUTPUT_TYPE_OPENDRAIN STATIC_ASSERT(0, "RP2040 has no Open Drain GPIO configuration, setting this is not possible");
 
 /* Aliases for GPIO PWM channels - every pin has at least one PWM channel
  * assigned */

+ 4 - 2
platforms/chibios/drivers/wear_leveling/wear_leveling_rp2040_flash.c

@@ -6,13 +6,15 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <stdbool.h>
+
 #include "pico/bootrom.h"
 #include "hardware/flash.h"
 #include "hardware/sync.h"
 #include "hardware/structs/ssi.h"
 #include "hardware/structs/ioqspi.h"
 
-#include <stdbool.h>
+#include "compiler_support.h"
 #include "timer.h"
 #include "wear_leveling.h"
 #include "wear_leveling_rp2040_flash_config.h"
@@ -178,7 +180,7 @@ bool backing_store_erase(void) {
 #endif
 
     // Ensure the backing size can be cleanly subtracted from the flash size without alignment issues.
-    _Static_assert((WEAR_LEVELING_BACKING_SIZE) % (FLASH_SECTOR_SIZE) == 0, "Backing size must be a multiple of FLASH_SECTOR_SIZE");
+    STATIC_ASSERT((WEAR_LEVELING_BACKING_SIZE) % (FLASH_SECTOR_SIZE) == 0, "Backing size must be a multiple of FLASH_SECTOR_SIZE");
 
     interrupts = save_and_disable_interrupts();
     flash_range_erase((WEAR_LEVELING_RP2040_FLASH_BASE), (WEAR_LEVELING_BACKING_SIZE));

+ 3 - 1
quantum/audio/audio.h

@@ -18,6 +18,8 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+
+#include "compiler_support.h"
 #include "musical_notes.h"
 #include "song_list.h"
 #include "voices.h"
@@ -38,7 +40,7 @@ typedef union audio_config_t {
     };
 } audio_config_t;
 
-_Static_assert(sizeof(audio_config_t) == sizeof(uint8_t), "Audio EECONFIG out of spec.");
+STATIC_ASSERT(sizeof(audio_config_t) == sizeof(uint8_t), "Audio EECONFIG out of spec.");
 
 /*
  * a 'musical note' is represented by pitch and duration; a 'musical tone' adds intensity and timbre

+ 3 - 1
quantum/backlight/backlight.h

@@ -20,6 +20,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include <stdint.h>
 #include <stdbool.h>
 
+#include "compiler_support.h"
+
 #ifndef BACKLIGHT_LEVELS
 #    define BACKLIGHT_LEVELS 3
 #elif BACKLIGHT_LEVELS > 31
@@ -44,7 +46,7 @@ typedef union backlight_config_t {
     };
 } backlight_config_t;
 
-_Static_assert(sizeof(backlight_config_t) == sizeof(uint8_t), "Backlight EECONFIG out of spec.");
+STATIC_ASSERT(sizeof(backlight_config_t) == sizeof(uint8_t), "Backlight EECONFIG out of spec.");
 
 void    backlight_init(void);
 void    backlight_toggle(void);

+ 15 - 0
quantum/compiler_support.h

@@ -0,0 +1,15 @@
+// Copyright 2025 QMK Contributors
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/**
+ * @brief Perfom an assertion at compile time.
+ *
+ * `_Static_assert` is C<23, while `static_assert` is C++/C23.
+ */
+#if !defined(STATIC_ASSERT)
+#    ifdef __cplusplus
+#        define STATIC_ASSERT static_assert
+#    else
+#        define STATIC_ASSERT _Static_assert
+#    endif
+#endif

+ 3 - 1
quantum/connection/connection.h

@@ -3,6 +3,8 @@
 #pragma once
 
 #include <stdint.h>
+
+#include "compiler_support.h"
 #include "util.h"
 
 /**
@@ -29,7 +31,7 @@ typedef union connection_config_t {
     connection_host_t desired_host : 8;
 } PACKED connection_config_t;
 
-_Static_assert(sizeof(connection_config_t) == sizeof(uint8_t), "Connection EECONFIG out of spec.");
+STATIC_ASSERT(sizeof(connection_config_t) == sizeof(uint8_t), "Connection EECONFIG out of spec.");
 
 /**
  * \brief Initialize the subsystem.

+ 3 - 1
quantum/haptic.h

@@ -20,6 +20,8 @@
 #include <stdint.h>
 #include <stdbool.h>
 
+#include "compiler_support.h"
+
 #ifndef HAPTIC_DEFAULT_FEEDBACK
 #    define HAPTIC_DEFAULT_FEEDBACK 0
 #endif
@@ -42,7 +44,7 @@ typedef union haptic_config_t {
     };
 } haptic_config_t;
 
-_Static_assert(sizeof(haptic_config_t) == sizeof(uint32_t), "Haptic EECONFIG out of spec.");
+STATIC_ASSERT(sizeof(haptic_config_t) == sizeof(uint32_t), "Haptic EECONFIG out of spec.");
 
 typedef enum HAPTIC_FEEDBACK {
     KEY_PRESS,

+ 2 - 4
quantum/keycode_config.h

@@ -16,9 +16,7 @@
 
 #pragma once
 
-#ifdef __cplusplus
-#    define _Static_assert static_assert
-#endif
+#include "compiler_support.h"
 
 #include "eeconfig.h"
 #include "keycode.h"
@@ -47,6 +45,6 @@ typedef union keymap_config_t {
     };
 } keymap_config_t;
 
-_Static_assert(sizeof(keymap_config_t) == sizeof(uint16_t), "Keycode (magic) EECONFIG out of spec.");
+STATIC_ASSERT(sizeof(keymap_config_t) == sizeof(uint16_t), "Keycode (magic) EECONFIG out of spec.");
 
 extern keymap_config_t keymap_config;

+ 7 - 6
quantum/keymap_introspection.c

@@ -13,6 +13,7 @@
 #    include INTROSPECTION_KEYMAP_C
 #endif // INTROSPECTION_KEYMAP_C
 
+#include "compiler_support.h"
 #include "keymap_introspection.h"
 #include "util.h"
 
@@ -30,9 +31,9 @@ __attribute__((weak)) uint8_t keymap_layer_count(void) {
 }
 
 #ifdef DYNAMIC_KEYMAP_ENABLE
-_Static_assert(NUM_KEYMAP_LAYERS_RAW <= MAX_LAYER, "Number of keymap layers exceeds maximum set by DYNAMIC_KEYMAP_LAYER_COUNT");
+STATIC_ASSERT(NUM_KEYMAP_LAYERS_RAW <= MAX_LAYER, "Number of keymap layers exceeds maximum set by DYNAMIC_KEYMAP_LAYER_COUNT");
 #else
-_Static_assert(NUM_KEYMAP_LAYERS_RAW <= MAX_LAYER, "Number of keymap layers exceeds maximum set by LAYER_STATE_(8|16|32)BIT");
+STATIC_ASSERT(NUM_KEYMAP_LAYERS_RAW <= MAX_LAYER, "Number of keymap layers exceeds maximum set by LAYER_STATE_(8|16|32)BIT");
 #endif
 
 uint16_t keycode_at_keymap_location_raw(uint8_t layer_num, uint8_t row, uint8_t column) {
@@ -61,7 +62,7 @@ __attribute__((weak)) uint8_t encodermap_layer_count(void) {
     return encodermap_layer_count_raw();
 }
 
-_Static_assert(NUM_KEYMAP_LAYERS_RAW == NUM_ENCODERMAP_LAYERS_RAW, "Number of encoder_map layers doesn't match the number of keymap layers");
+STATIC_ASSERT(NUM_KEYMAP_LAYERS_RAW == NUM_ENCODERMAP_LAYERS_RAW, "Number of encoder_map layers doesn't match the number of keymap layers");
 
 uint16_t keycode_at_encodermap_location_raw(uint8_t layer_num, uint8_t encoder_idx, bool clockwise) {
     if (layer_num < NUM_ENCODERMAP_LAYERS_RAW && encoder_idx < NUM_ENCODERS) {
@@ -106,7 +107,7 @@ __attribute__((weak)) uint16_t combo_count(void) {
     return combo_count_raw();
 }
 
-_Static_assert(ARRAY_SIZE(key_combos) <= (QK_KB), "Number of combos is abnormally high. Are you using SAFE_RANGE in an enum for combos?");
+STATIC_ASSERT(ARRAY_SIZE(key_combos) <= (QK_KB), "Number of combos is abnormally high. Are you using SAFE_RANGE in an enum for combos?");
 
 combo_t* combo_get_raw(uint16_t combo_idx) {
     if (combo_idx >= combo_count_raw()) {
@@ -133,7 +134,7 @@ __attribute__((weak)) uint16_t tap_dance_count(void) {
     return tap_dance_count_raw();
 }
 
-_Static_assert(ARRAY_SIZE(tap_dance_actions) <= (QK_TAP_DANCE_MAX - QK_TAP_DANCE), "Number of tap dance actions exceeds maximum. Are you using SAFE_RANGE in tap dance enum?");
+STATIC_ASSERT(ARRAY_SIZE(tap_dance_actions) <= (QK_TAP_DANCE_MAX - QK_TAP_DANCE), "Number of tap dance actions exceeds maximum. Are you using SAFE_RANGE in tap dance enum?");
 
 tap_dance_action_t* tap_dance_get_raw(uint16_t tap_dance_idx) {
     if (tap_dance_idx >= tap_dance_count_raw()) {
@@ -161,7 +162,7 @@ __attribute__((weak)) uint16_t key_override_count(void) {
     return key_override_count_raw();
 }
 
-_Static_assert(ARRAY_SIZE(key_overrides) <= (QK_KB), "Number of key overrides is abnormally high. Are you using SAFE_RANGE in an enum for key overrides?");
+STATIC_ASSERT(ARRAY_SIZE(key_overrides) <= (QK_KB), "Number of key overrides is abnormally high. Are you using SAFE_RANGE in an enum for key overrides?");
 
 const key_override_t* key_override_get_raw(uint16_t key_override_idx) {
     if (key_override_idx >= key_override_count_raw()) {

+ 3 - 1
quantum/led_matrix/led_matrix_types.h

@@ -18,6 +18,8 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+
+#include "compiler_support.h"
 #include "util.h"
 
 #if defined(LED_MATRIX_KEYPRESSES) || defined(LED_MATRIX_KEYRELEASES)
@@ -82,4 +84,4 @@ typedef union led_eeconfig_t {
     };
 } led_eeconfig_t;
 
-_Static_assert(sizeof(led_eeconfig_t) == sizeof(uint32_t), "LED Matrix EECONFIG out of spec.");
+STATIC_ASSERT(sizeof(led_eeconfig_t) == sizeof(uint32_t), "LED Matrix EECONFIG out of spec.");

+ 4 - 3
quantum/nvm/eeprom/nvm_dynamic_keymap.c

@@ -1,6 +1,7 @@
 // Copyright 2024 Nick Brassel (@tzarc)
 // SPDX-License-Identifier: GPL-2.0-or-later
 
+#include "compiler_support.h"
 #include "keycodes.h"
 #include "eeprom.h"
 #include "dynamic_keymap.h"
@@ -25,10 +26,10 @@
 #    define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR (TOTAL_EEPROM_BYTE_COUNT - 1)
 #endif
 
-_Static_assert(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR <= (TOTAL_EEPROM_BYTE_COUNT - 1), "DYNAMIC_KEYMAP_EEPROM_MAX_ADDR is configured to use more space than what is available for the selected EEPROM driver");
+STATIC_ASSERT(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR <= (TOTAL_EEPROM_BYTE_COUNT - 1), "DYNAMIC_KEYMAP_EEPROM_MAX_ADDR is configured to use more space than what is available for the selected EEPROM driver");
 
 // Due to usage of uint16_t check for max 65535
-_Static_assert(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR <= 65535, "DYNAMIC_KEYMAP_EEPROM_MAX_ADDR must be less than 65536");
+STATIC_ASSERT(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR <= 65535, "DYNAMIC_KEYMAP_EEPROM_MAX_ADDR must be less than 65536");
 
 // If DYNAMIC_KEYMAP_EEPROM_ADDR not explicitly defined in config.h,
 #ifndef DYNAMIC_KEYMAP_EEPROM_ADDR
@@ -56,7 +57,7 @@ _Static_assert(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR <= 65535, "DYNAMIC_KEYMAP_EEPROM_M
 // The keyboard should override DYNAMIC_KEYMAP_LAYER_COUNT to reduce it,
 // or DYNAMIC_KEYMAP_EEPROM_MAX_ADDR to increase it, *only if* the microcontroller has
 // more than the default.
-_Static_assert((DYNAMIC_KEYMAP_EEPROM_MAX_ADDR) - (DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR) >= 100, "Dynamic keymaps are configured to use more EEPROM than is available.");
+STATIC_ASSERT((DYNAMIC_KEYMAP_EEPROM_MAX_ADDR) - (DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR) >= 100, "Dynamic keymaps are configured to use more EEPROM than is available.");
 
 #ifndef TOTAL_EEPROM_BYTE_COUNT
 #    error Unknown total EEPROM size. Cannot derive maximum for dynamic keymaps.

+ 3 - 1
quantum/nvm/eeprom/nvm_eeprom_eeconfig_internal.h

@@ -4,6 +4,8 @@
 
 #include <stdint.h>
 #include <stddef.h> // offsetof
+
+#include "compiler_support.h"
 #include "eeconfig.h"
 #include "util.h"
 
@@ -58,4 +60,4 @@ typedef struct PACKED {
 // Size of EEPROM being used, other code can refer to this for available EEPROM
 #define EECONFIG_SIZE ((EECONFIG_BASE_SIZE) + (EECONFIG_KB_DATA_SIZE) + (EECONFIG_USER_DATA_SIZE))
 
-_Static_assert((intptr_t)EECONFIG_HANDEDNESS == 14, "EEPROM handedness offset is incorrect");
+STATIC_ASSERT((intptr_t)EECONFIG_HANDEDNESS == 14, "EEPROM handedness offset is incorrect");

+ 5 - 4
quantum/painter/qff.h

@@ -9,6 +9,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 
+#include "compiler_support.h"
 #include "qp_stream.h"
 #include "qp_internal.h"
 #include "qgf.h"
@@ -36,7 +37,7 @@ typedef struct QP_PACKED qff_font_descriptor_v1_t {
     uint8_t               transparency_index;  // palette index used for transparent pixels (not yet implemented)
 } qff_font_descriptor_v1_t;
 
-_Static_assert(sizeof(qff_font_descriptor_v1_t) == (sizeof(qgf_block_header_v1_t) + 20), "qff_font_descriptor_v1_t must be 25 bytes in v1 of QFF");
+STATIC_ASSERT(sizeof(qff_font_descriptor_v1_t) == (sizeof(qgf_block_header_v1_t) + 20), "qff_font_descriptor_v1_t must be 25 bytes in v1 of QFF");
 
 #define QFF_MAGIC 0x464651
 
@@ -54,14 +55,14 @@ typedef struct QP_PACKED qff_ascii_glyph_v1_t {
     uint32_t value : 24; // Uses QFF_GLYPH_*_(BITS|MASK) as bitfield ordering is compiler-defined
 } qff_ascii_glyph_v1_t;
 
-_Static_assert(sizeof(qff_ascii_glyph_v1_t) == 3, "qff_ascii_glyph_v1_t must be 3 bytes in v1 of QFF");
+STATIC_ASSERT(sizeof(qff_ascii_glyph_v1_t) == 3, "qff_ascii_glyph_v1_t must be 3 bytes in v1 of QFF");
 
 typedef struct QP_PACKED qff_ascii_glyph_table_v1_t {
     qgf_block_header_v1_t header;    // = { .type_id = 0x01, .neg_type_id = (~0x01), .length = 285 }
     qff_ascii_glyph_v1_t  glyph[95]; // 95 glyphs, 0x20..0x7E
 } qff_ascii_glyph_table_v1_t;
 
-_Static_assert(sizeof(qff_ascii_glyph_table_v1_t) == (sizeof(qgf_block_header_v1_t) + (95 * sizeof(qff_ascii_glyph_v1_t))), "qff_ascii_glyph_table_v1_t must be 290 bytes in v1 of QFF");
+STATIC_ASSERT(sizeof(qff_ascii_glyph_table_v1_t) == (sizeof(qgf_block_header_v1_t) + (95 * sizeof(qff_ascii_glyph_v1_t))), "qff_ascii_glyph_table_v1_t must be 290 bytes in v1 of QFF");
 
 /////////////////////////////////////////
 // Unicode glyph table descriptor
@@ -73,7 +74,7 @@ typedef struct QP_PACKED qff_unicode_glyph_v1_t {
     uint32_t value : 24; // Uses QFF_GLYPH_*_(BITS|MASK) as bitfield ordering is compiler-defined
 } qff_unicode_glyph_v1_t;
 
-_Static_assert(sizeof(qff_unicode_glyph_v1_t) == 6, "qff_unicode_glyph_v1_t must be 6 bytes in v1 of QFF");
+STATIC_ASSERT(sizeof(qff_unicode_glyph_v1_t) == 6, "qff_unicode_glyph_v1_t must be 6 bytes in v1 of QFF");
 
 typedef struct QP_PACKED qff_unicode_glyph_table_v1_t {
     qgf_block_header_v1_t  header;   // = { .type_id = 0x02, .neg_type_id = (~0x02), .length = (N * 6) }

+ 9 - 8
quantum/painter/qgf.h

@@ -9,6 +9,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 
+#include "compiler_support.h"
 #include "qp_stream.h"
 #include "qp_internal.h"
 
@@ -24,7 +25,7 @@ typedef struct QP_PACKED qgf_block_header_v1_t {
     uint32_t length : 24; // 24-bit blob length, allowing for block sizes of a maximum of 16MB.
 } qgf_block_header_v1_t;
 
-_Static_assert(sizeof(qgf_block_header_v1_t) == 5, "qgf_block_header_v1_t must be 5 bytes in v1 of QGF");
+STATIC_ASSERT(sizeof(qgf_block_header_v1_t) == 5, "qgf_block_header_v1_t must be 5 bytes in v1 of QGF");
 
 /////////////////////////////////////////
 // Graphics descriptor
@@ -42,7 +43,7 @@ typedef struct QP_PACKED qgf_graphics_descriptor_v1_t {
     uint16_t              frame_count;         // minimum of 1
 } qgf_graphics_descriptor_v1_t;
 
-_Static_assert(sizeof(qgf_graphics_descriptor_v1_t) == (sizeof(qgf_block_header_v1_t) + 18), "qgf_graphics_descriptor_v1_t must be 23 bytes in v1 of QGF");
+STATIC_ASSERT(sizeof(qgf_graphics_descriptor_v1_t) == (sizeof(qgf_block_header_v1_t) + 18), "qgf_graphics_descriptor_v1_t must be 23 bytes in v1 of QGF");
 
 #define QGF_MAGIC 0x464751
 
@@ -56,7 +57,7 @@ typedef struct QP_PACKED qgf_frame_offsets_v1_t {
     uint32_t              offset[0]; // '0' signifies that this struct is immediately followed by the frame offsets
 } qgf_frame_offsets_v1_t;
 
-_Static_assert(sizeof(qgf_frame_offsets_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_frame_offsets_v1_t must only contain qgf_block_header_v1_t in v1 of QGF");
+STATIC_ASSERT(sizeof(qgf_frame_offsets_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_frame_offsets_v1_t must only contain qgf_block_header_v1_t in v1 of QGF");
 
 /////////////////////////////////////////
 // Frame descriptor
@@ -72,7 +73,7 @@ typedef struct QP_PACKED qgf_frame_v1_t {
     uint16_t              delay;                  // frame delay time for animations (in units of milliseconds)
 } qgf_frame_v1_t;
 
-_Static_assert(sizeof(qgf_frame_v1_t) == (sizeof(qgf_block_header_v1_t) + 6), "qgf_frame_v1_t must be 11 bytes in v1 of QGF");
+STATIC_ASSERT(sizeof(qgf_frame_v1_t) == (sizeof(qgf_block_header_v1_t) + 6), "qgf_frame_v1_t must be 11 bytes in v1 of QGF");
 
 #define QGF_FRAME_FLAG_DELTA 0x02
 #define QGF_FRAME_FLAG_TRANSPARENT 0x01
@@ -88,14 +89,14 @@ typedef struct QP_PACKED qgf_palette_entry_v1_t {
     uint8_t v; // value component: `[0,1]` is mapped to `[0,255]` uint8_t.
 } qgf_palette_entry_v1_t;
 
-_Static_assert(sizeof(qgf_palette_entry_v1_t) == 3, "Palette entry is not 3 bytes in size");
+STATIC_ASSERT(sizeof(qgf_palette_entry_v1_t) == 3, "Palette entry is not 3 bytes in size");
 
 typedef struct QP_PACKED qgf_palette_v1_t {
     qgf_block_header_v1_t  header; // = { .type_id = 0x03, .neg_type_id = (~0x03), .length = (N * 3 * sizeof(uint8_t)) }
     qgf_palette_entry_v1_t hsv[0]; // N * hsv, where N is the number of palette entries depending on the frame format in the descriptor
 } qgf_palette_v1_t;
 
-_Static_assert(sizeof(qgf_palette_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_palette_v1_t must only contain qgf_block_header_v1_t in v1 of QGF");
+STATIC_ASSERT(sizeof(qgf_palette_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_palette_v1_t must only contain qgf_block_header_v1_t in v1 of QGF");
 
 /////////////////////////////////////////
 // Frame delta descriptor
@@ -110,7 +111,7 @@ typedef struct QP_PACKED qgf_delta_v1_t {
     uint16_t              bottom; // The bottom pixel location to to draw the delta image
 } qgf_delta_v1_t;
 
-_Static_assert(sizeof(qgf_delta_v1_t) == (sizeof(qgf_block_header_v1_t) + 8), "qgf_delta_v1_t must be 13 bytes in v1 of QGF");
+STATIC_ASSERT(sizeof(qgf_delta_v1_t) == (sizeof(qgf_block_header_v1_t) + 8), "qgf_delta_v1_t must be 13 bytes in v1 of QGF");
 
 /////////////////////////////////////////
 // Frame data descriptor
@@ -122,7 +123,7 @@ typedef struct QP_PACKED qgf_data_v1_t {
     uint8_t               data[0]; // 0 signifies that this struct is immediately followed by the length of data specified in the header
 } qgf_data_v1_t;
 
-_Static_assert(sizeof(qgf_data_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_data_v1_t must only contain qgf_block_header_v1_t in v1 of QGF");
+STATIC_ASSERT(sizeof(qgf_data_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_data_v1_t must only contain qgf_block_header_v1_t in v1 of QGF");
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 // QGF API

+ 2 - 1
quantum/painter/qp_draw_core.c

@@ -2,12 +2,13 @@
 // Copyright 2021 Paul Cotter (@gr1mr3aver)
 // SPDX-License-Identifier: GPL-2.0-or-later
 
+#include "compiler_support.h"
 #include "qp_internal.h"
 #include "qp_comms.h"
 #include "qp_draw.h"
 #include "qgf.h"
 
-_Static_assert((QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE > 0) && (QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE % 16) == 0, "QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE needs to be a non-zero multiple of 16");
+STATIC_ASSERT((QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE > 0) && (QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE % 16) == 0, "QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE needs to be a non-zero multiple of 16");
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 // Global variables

+ 3 - 1
quantum/painter/qp_internal.c

@@ -3,6 +3,8 @@
 
 #include "qp_internal.h"
 
+#include "compiler_support.h"
+
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 // Quantum Painter Core API: device registration
 
@@ -67,7 +69,7 @@ static void qp_internal_display_timeout_task(void) {
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 // Quantum Painter Core API: qp_internal_task
 
-_Static_assert((QUANTUM_PAINTER_TASK_THROTTLE) > 0 && (QUANTUM_PAINTER_TASK_THROTTLE) < 1000, "QUANTUM_PAINTER_TASK_THROTTLE must be between 1 and 999");
+STATIC_ASSERT((QUANTUM_PAINTER_TASK_THROTTLE) > 0 && (QUANTUM_PAINTER_TASK_THROTTLE) < 1000, "QUANTUM_PAINTER_TASK_THROTTLE must be between 1 and 999");
 
 void qp_internal_task(void) {
     // Perform throttling of the internal processing of Quantum Painter

+ 2 - 1
quantum/painter/qp_internal_formats.h

@@ -3,6 +3,7 @@
 
 #pragma once
 
+#include "compiler_support.h"
 #include "qp_internal.h"
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -29,7 +30,7 @@ typedef union QP_PACKED qp_pixel_t {
 
     uint32_t dummy;
 } qp_pixel_t;
-_Static_assert(sizeof(qp_pixel_t) == 4, "Invalid size for qp_pixel_t");
+STATIC_ASSERT(sizeof(qp_pixel_t) == 4, "Invalid size for qp_pixel_t");
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 // Quantum Painter image format

+ 3 - 1
quantum/rgb_matrix/rgb_matrix_types.h

@@ -18,6 +18,8 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+
+#include "compiler_support.h"
 #include "color.h"
 #include "util.h"
 
@@ -84,4 +86,4 @@ typedef union rgb_config_t {
     };
 } rgb_config_t;
 
-_Static_assert(sizeof(rgb_config_t) == sizeof(uint64_t), "RGB Matrix EECONFIG out of spec.");
+STATIC_ASSERT(sizeof(rgb_config_t) == sizeof(uint64_t), "RGB Matrix EECONFIG out of spec.");

+ 3 - 1
quantum/rgblight/rgblight.h

@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include "compiler_support.h"
+
 // DEPRECATED DEFINES - DO NOT USE
 #if defined(RGBLED_NUM)
 #    define RGBLIGHT_LED_COUNT RGBLED_NUM
@@ -260,7 +262,7 @@ typedef union rgblight_config_t {
     };
 } rgblight_config_t;
 
-_Static_assert(sizeof(rgblight_config_t) == sizeof(uint64_t), "RGB Light EECONFIG out of spec.");
+STATIC_ASSERT(sizeof(rgblight_config_t) == sizeof(uint64_t), "RGB Light EECONFIG out of spec.");
 
 typedef struct _rgblight_status_t {
     uint8_t base_mode;

+ 5 - 3
quantum/split_common/split_util.c

@@ -13,6 +13,8 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
+
+#include "compiler_support.h"
 #include "split_util.h"
 #include "matrix.h"
 #include "keyboard.h"
@@ -62,7 +64,7 @@ static struct {
 } split_config;
 
 #if defined(SPLIT_USB_DETECT)
-_Static_assert((SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL) <= UINT16_MAX, "Please lower SPLIT_USB_TIMEOUT and/or increase SPLIT_USB_TIMEOUT_POLL.");
+STATIC_ASSERT((SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL) <= UINT16_MAX, "Please lower SPLIT_USB_TIMEOUT and/or increase SPLIT_USB_TIMEOUT_POLL.");
 static bool usb_bus_detected(void) {
     for (uint16_t i = 0; i < (SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL); i++) {
         // This will return true if a USB connection has been established
@@ -88,9 +90,9 @@ static inline bool usb_bus_detected(void) {
 #        endif
 #    endif
 #    if defined(SPLIT_USB_DETECT)
-_Static_assert(SPLIT_USB_TIMEOUT < SPLIT_WATCHDOG_TIMEOUT, "SPLIT_WATCHDOG_TIMEOUT should not be below SPLIT_USB_TIMEOUT.");
+STATIC_ASSERT(SPLIT_USB_TIMEOUT < SPLIT_WATCHDOG_TIMEOUT, "SPLIT_WATCHDOG_TIMEOUT should not be below SPLIT_USB_TIMEOUT.");
 #    endif
-_Static_assert(SPLIT_MAX_CONNECTION_ERRORS > 0, "SPLIT_WATCHDOG_ENABLE requires SPLIT_MAX_CONNECTION_ERRORS be above 0 for a functioning disconnection check.");
+STATIC_ASSERT(SPLIT_MAX_CONNECTION_ERRORS > 0, "SPLIT_WATCHDOG_ENABLE requires SPLIT_MAX_CONNECTION_ERRORS be above 0 for a functioning disconnection check.");
 
 static uint32_t split_watchdog_started = 0;
 static bool     split_watchdog_done    = false;

+ 3 - 1
quantum/split_common/transaction_id_define.h

@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include "compiler_support.h"
+
 enum serial_transaction_id {
 #ifdef USE_I2C
     I2C_EXECUTE_CALLBACK,
@@ -122,4 +124,4 @@ enum serial_transaction_id {
 };
 
 // Ensure we only use 5 bits for transaction
-_Static_assert(NUM_TOTAL_TRANSACTIONS <= (1 << 5), "Max number of usable transactions exceeded");
+STATIC_ASSERT(NUM_TOTAL_TRANSACTIONS <= (1 << 5), "Max number of usable transactions exceeded");

+ 2 - 1
quantum/split_common/transport.c

@@ -17,6 +17,7 @@
 #include <string.h>
 #include <debug.h>
 
+#include "compiler_support.h"
 #include "transactions.h"
 #include "transport.h"
 #include "transaction_id_define.h"
@@ -36,7 +37,7 @@
 #    include "i2c_slave.h"
 
 // Ensure the I2C buffer has enough space
-_Static_assert(sizeof(split_shared_memory_t) <= I2C_SLAVE_REG_COUNT, "split_shared_memory_t too large for I2C_SLAVE_REG_COUNT");
+STATIC_ASSERT(sizeof(split_shared_memory_t) <= I2C_SLAVE_REG_COUNT, "split_shared_memory_t too large for I2C_SLAVE_REG_COUNT");
 
 split_shared_memory_t *const split_shmem = (split_shared_memory_t *)i2c_slave_reg;
 

+ 3 - 1
quantum/unicode/unicode.h

@@ -17,6 +17,8 @@
 #pragma once
 
 #include <stdint.h>
+
+#include "compiler_support.h"
 #include "unicode_keycodes.h"
 
 /**
@@ -33,7 +35,7 @@ typedef union unicode_config_t {
     };
 } unicode_config_t;
 
-_Static_assert(sizeof(unicode_config_t) == sizeof(uint8_t), "Unicode EECONFIG out of spec.");
+STATIC_ASSERT(sizeof(unicode_config_t) == sizeof(uint8_t), "Unicode EECONFIG out of spec.");
 
 extern unicode_config_t unicode_config;
 

+ 6 - 8
quantum/wear_leveling/wear_leveling_internal.h

@@ -2,9 +2,7 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 #pragma once
 
-#ifdef __cplusplus
-#    define _Static_assert static_assert
-#endif
+#include "compiler_support.h"
 
 #include <stdint.h>
 #include <string.h>
@@ -62,9 +60,9 @@ typedef uint64_t backing_store_int_t;
 #endif // WEAR_LEVELING_ASSERTS
 
 // Compile-time validation of configurable options
-_Static_assert(WEAR_LEVELING_BACKING_SIZE >= (WEAR_LEVELING_LOGICAL_SIZE * 2), "Total backing size must be at least twice the size of the logical size");
-_Static_assert(WEAR_LEVELING_LOGICAL_SIZE % BACKING_STORE_WRITE_SIZE == 0, "Logical size must be a multiple of write size");
-_Static_assert(WEAR_LEVELING_BACKING_SIZE % WEAR_LEVELING_LOGICAL_SIZE == 0, "Backing size must be a multiple of logical size");
+STATIC_ASSERT(WEAR_LEVELING_BACKING_SIZE >= (WEAR_LEVELING_LOGICAL_SIZE * 2), "Total backing size must be at least twice the size of the logical size");
+STATIC_ASSERT(WEAR_LEVELING_LOGICAL_SIZE % BACKING_STORE_WRITE_SIZE == 0, "Logical size must be a multiple of write size");
+STATIC_ASSERT(WEAR_LEVELING_BACKING_SIZE % WEAR_LEVELING_LOGICAL_SIZE == 0, "Backing size must be a multiple of logical size");
 
 // Backing Store API, to be implemented elsewhere by flash driver etc.
 bool backing_store_init(void);
@@ -86,7 +84,7 @@ typedef union write_log_entry_t {
     uint8_t  raw8[8];
 } write_log_entry_t;
 
-_Static_assert(sizeof(write_log_entry_t) == 8, "Wear leveling write log entry size was not 8");
+STATIC_ASSERT(sizeof(write_log_entry_t) == 8, "Wear leveling write log entry size was not 8");
 
 /**
  * Log entry type discriminator.
@@ -104,7 +102,7 @@ enum {
     LOG_ENTRY_TYPES
 };
 
-_Static_assert(LOG_ENTRY_TYPES <= (1 << 2), "Too many log entry types to fit into 2 bits of storage");
+STATIC_ASSERT(LOG_ENTRY_TYPES <= (1 << 2), "Too many log entry types to fit into 2 bits of storage");
 
 #define BITMASK_FOR_BITCOUNT(n) ((1 << (n)) - 1)
 

+ 2 - 1
tmk_core/protocol/vusb/vusb.c

@@ -21,6 +21,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include <usbdrv/usbdrv.h>
 
+#include "compiler_support.h"
 #include "usbconfig.h"
 #include "host.h"
 #include "report.h"
@@ -80,7 +81,7 @@ enum usb_interfaces {
 
 #define MAX_INTERFACES 3
 
-_Static_assert(TOTAL_INTERFACES <= MAX_INTERFACES, "There are not enough available interfaces to support all functions. Please disable one or more of the following: Mouse Keys, Extra Keys, Raw HID, Console.");
+STATIC_ASSERT(TOTAL_INTERFACES <= MAX_INTERFACES, "There are not enough available interfaces to support all functions. Please disable one or more of the following: Mouse Keys, Extra Keys, Raw HID, Console.");
 
 #if (defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)) && CONSOLE_ENABLE
 #    error Mouse/Extra Keys share an endpoint with Console. Please disable one of the two.