forked from espressif/esp-idf
CI: check_public_headers script will detect the use of static asserts in headers
When a public header contains _Static_assert or static_assert, check_public_headers.py script will detect it and report it as an issue. Indeed, public headers shall now use ESP_STATIC_ASSERT.
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
|
#include "esp_assert.h"
|
||||||
#if SOC_MCPWM_SUPPORTED
|
#if SOC_MCPWM_SUPPORTED
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "soc/soc.h"
|
#include "soc/soc.h"
|
||||||
@@ -74,7 +75,7 @@ typedef enum {
|
|||||||
MCPWM_UNIT_MAX, /*!<Max number of MCPWM units*/
|
MCPWM_UNIT_MAX, /*!<Max number of MCPWM units*/
|
||||||
} mcpwm_unit_t;
|
} mcpwm_unit_t;
|
||||||
|
|
||||||
_Static_assert(MCPWM_UNIT_MAX == SOC_MCPWM_GROUPS, "MCPWM unit number not equal to chip capabilities");
|
ESP_STATIC_ASSERT(MCPWM_UNIT_MAX == SOC_MCPWM_GROUPS, "MCPWM unit number not equal to chip capabilities");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Select MCPWM timer
|
* @brief Select MCPWM timer
|
||||||
|
@@ -16,8 +16,11 @@
|
|||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
|
|
||||||
/* Since IDF v5.0, C17 standard is used, which supports both _Static_assert and static_assert syntax */
|
#ifndef __cplusplus
|
||||||
#define ESP_STATIC_ASSERT static_assert
|
#define ESP_STATIC_ASSERT _Static_assert
|
||||||
|
#else // __cplusplus
|
||||||
|
#define ESP_STATIC_ASSERT static_assert
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
/* Assert at compile time if possible, runtime otherwise */
|
/* Assert at compile time if possible, runtime otherwise */
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
|
@@ -29,6 +29,7 @@ extern "C" {
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
#include "esp_assert.h"
|
||||||
#include "hal/misc.h"
|
#include "hal/misc.h"
|
||||||
#include "hal/twai_types.h"
|
#include "hal/twai_types.h"
|
||||||
#include "soc/twai_periph.h"
|
#include "soc/twai_periph.h"
|
||||||
|
@@ -23,6 +23,7 @@ extern "C" {
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "esp_assert.h"
|
||||||
#include "soc/timer_periph.h"
|
#include "soc/timer_periph.h"
|
||||||
#include "soc/timer_group_struct.h"
|
#include "soc/timer_group_struct.h"
|
||||||
#include "hal/wdt_types.h"
|
#include "hal/wdt_types.h"
|
||||||
|
@@ -28,6 +28,7 @@ extern "C" {
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "esp_assert.h"
|
||||||
#include "hal/misc.h"
|
#include "hal/misc.h"
|
||||||
#include "hal/twai_types.h"
|
#include "hal/twai_types.h"
|
||||||
#include "soc/twai_periph.h"
|
#include "soc/twai_periph.h"
|
||||||
|
@@ -28,6 +28,7 @@ extern "C" {
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "esp_assert.h"
|
||||||
#include "hal/misc.h"
|
#include "hal/misc.h"
|
||||||
#include "hal/twai_types.h"
|
#include "hal/twai_types.h"
|
||||||
#include "soc/twai_periph.h"
|
#include "soc/twai_periph.h"
|
||||||
|
@@ -28,6 +28,7 @@ extern "C" {
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "esp_assert.h"
|
||||||
#include "hal/misc.h"
|
#include "hal/misc.h"
|
||||||
#include "hal/twai_types.h"
|
#include "hal/twai_types.h"
|
||||||
#include "soc/twai_periph.h"
|
#include "soc/twai_periph.h"
|
||||||
|
@@ -333,9 +333,9 @@ static inline void i2c_ll_set_slave_addr(i2c_dev_t *hw, uint16_t slave_addr, boo
|
|||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline void i2c_ll_write_cmd_reg(i2c_dev_t *hw, i2c_hw_cmd_t cmd, int cmd_idx)
|
static inline void i2c_ll_write_cmd_reg(i2c_dev_t *hw, i2c_hw_cmd_t cmd, int cmd_idx)
|
||||||
{
|
{
|
||||||
ESP_STATIC_ASSERT(sizeof(i2c_comd0_reg_t) == sizeof(i2c_ll_hw_cmd_t),
|
ESP_STATIC_ASSERT(sizeof(i2c_comd0_reg_t) == sizeof(i2c_hw_cmd_t),
|
||||||
"i2c_comdX_reg_t structure size must be equal to i2c_ll_hw_cmd_t structure size");
|
"i2c_comdX_reg_t structure size must be equal to i2c_hw_cmd_t structure size");
|
||||||
volatile i2c_ll_hw_cmd_t* commands = (volatile i2c_ll_hw_cmd_t*) &hw->comd0;
|
volatile i2c_hw_cmd_t* commands = (volatile i2c_hw_cmd_t*) &hw->comd0;
|
||||||
commands[cmd_idx].val = cmd.val;
|
commands[cmd_idx].val = cmd.val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
#include "hal/spi_flash_ll.h"
|
#include "hal/spi_flash_ll.h"
|
||||||
#include "hal/spi_types.h"
|
#include "hal/spi_types.h"
|
||||||
#include "hal/spi_flash_types.h"
|
#include "hal/spi_flash_types.h"
|
||||||
|
#include "soc/soc_memory_types.h"
|
||||||
#include "esp_assert.h"
|
#include "esp_assert.h"
|
||||||
|
|
||||||
/* Hardware host-specific constants */
|
/* Hardware host-specific constants */
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include "esp_assert.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "soc/soc.h"
|
#include "soc/soc.h"
|
||||||
#include "ulp_common.h"
|
#include "ulp_common.h"
|
||||||
@@ -289,7 +290,7 @@ union ulp_insn {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_Static_assert(sizeof(ulp_insn_t) == 4, "ULP coprocessor instruction size should be 4 bytes");
|
ESP_STATIC_ASSERT(sizeof(ulp_insn_t) == 4, "ULP coprocessor instruction size should be 4 bytes");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delay (nop) for a given number of cycles
|
* Delay (nop) for a given number of cycles
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include "esp_assert.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "soc/soc.h"
|
#include "soc/soc.h"
|
||||||
#include "ulp_common.h"
|
#include "ulp_common.h"
|
||||||
@@ -265,7 +266,7 @@ union ulp_insn {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_Static_assert(sizeof(ulp_insn_t) == 4, "ULP coprocessor instruction size should be 4 bytes");
|
ESP_STATIC_ASSERT(sizeof(ulp_insn_t) == 4, "ULP coprocessor instruction size should be 4 bytes");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delay (nop) for a given number of cycles
|
* Delay (nop) for a given number of cycles
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include "esp_assert.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "soc/soc.h"
|
#include "soc/soc.h"
|
||||||
#include "ulp_common.h"
|
#include "ulp_common.h"
|
||||||
@@ -265,7 +266,7 @@ union ulp_insn {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_Static_assert(sizeof(ulp_insn_t) == 4, "ULP coprocessor instruction size should be 4 bytes");
|
ESP_STATIC_ASSERT(sizeof(ulp_insn_t) == 4, "ULP coprocessor instruction size should be 4 bytes");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delay (nop) for a given number of cycles
|
* Delay (nop) for a given number of cycles
|
||||||
|
@@ -56,6 +56,11 @@ class HeaderFailedContainsCode(HeaderFailed):
|
|||||||
return 'Header Produced non-zero object'
|
return 'Header Produced non-zero object'
|
||||||
|
|
||||||
|
|
||||||
|
class HeaderFailedContainsStaticAssert(HeaderFailed):
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return 'Header uses _Static_assert or static_assert instead of ESP_STATIC_ASSERT'
|
||||||
|
|
||||||
|
|
||||||
# Creates a temp file and returns both output as a string and a file name
|
# Creates a temp file and returns both output as a string and a file name
|
||||||
#
|
#
|
||||||
def exec_cmd_to_temp_file(what, suffix=''):
|
def exec_cmd_to_temp_file(what, suffix=''):
|
||||||
@@ -84,6 +89,7 @@ class PublicHeaderChecker:
|
|||||||
PREPROC_OUT_SAME_HRD_FAILED = 5 # -> Both preprocessors produce the same, non-zero output (header file FAILs)
|
PREPROC_OUT_SAME_HRD_FAILED = 5 # -> Both preprocessors produce the same, non-zero output (header file FAILs)
|
||||||
PREPROC_OUT_DIFFERENT_WITH_EXT_C_HDR_OK = 6 # -> Both preprocessors produce different, non-zero output with extern "C" (header seems OK)
|
PREPROC_OUT_DIFFERENT_WITH_EXT_C_HDR_OK = 6 # -> Both preprocessors produce different, non-zero output with extern "C" (header seems OK)
|
||||||
PREPROC_OUT_DIFFERENT_NO_EXT_C_HDR_FAILED = 7 # -> Both preprocessors produce different, non-zero output without extern "C" (header fails)
|
PREPROC_OUT_DIFFERENT_NO_EXT_C_HDR_FAILED = 7 # -> Both preprocessors produce different, non-zero output without extern "C" (header fails)
|
||||||
|
HEADER_CONTAINS_STATIC_ASSERT = 8 # -> Header file contains _Static_assert instead of static_assert or ESP_STATIC_ASSERT
|
||||||
|
|
||||||
def log(self, message, debug=False):
|
def log(self, message, debug=False):
|
||||||
if self.verbose or debug:
|
if self.verbose or debug:
|
||||||
@@ -99,6 +105,9 @@ class PublicHeaderChecker:
|
|||||||
self.error_macro = re.compile(r'#error')
|
self.error_macro = re.compile(r'#error')
|
||||||
self.error_orphan_kconfig = re.compile(r'#error CONFIG_VARS_USED_WHILE_SDKCONFIG_NOT_INCLUDED')
|
self.error_orphan_kconfig = re.compile(r'#error CONFIG_VARS_USED_WHILE_SDKCONFIG_NOT_INCLUDED')
|
||||||
self.kconfig_macro = re.compile(r'\bCONFIG_[A-Z0-9_]+')
|
self.kconfig_macro = re.compile(r'\bCONFIG_[A-Z0-9_]+')
|
||||||
|
self.static_assert = re.compile(r'(_Static_assert|static_assert)')
|
||||||
|
self.defines_assert = re.compile(r'#define[ \t]+ESP_STATIC_ASSERT')
|
||||||
|
self.auto_soc_header = re.compile(r'components/soc/esp[a-z0-9_]+/include(?:/rev[0-9]+)?/soc/[a-zA-Z0-9_]+.h')
|
||||||
self.assembly_nocode = r'^\s*(\.file|\.text|\.ident).*$'
|
self.assembly_nocode = r'^\s*(\.file|\.text|\.ident).*$'
|
||||||
self.check_threads = []
|
self.check_threads = []
|
||||||
|
|
||||||
@@ -170,6 +179,8 @@ class PublicHeaderChecker:
|
|||||||
return self.compile_one_header(header)
|
return self.compile_one_header(header)
|
||||||
elif res == self.PREPROC_OUT_SAME_HRD_FAILED:
|
elif res == self.PREPROC_OUT_SAME_HRD_FAILED:
|
||||||
raise HeaderFailedCppGuardMissing()
|
raise HeaderFailedCppGuardMissing()
|
||||||
|
elif res == self.HEADER_CONTAINS_STATIC_ASSERT:
|
||||||
|
raise HeaderFailedContainsStaticAssert()
|
||||||
else:
|
else:
|
||||||
self.compile_one_header(header)
|
self.compile_one_header(header)
|
||||||
temp_header = None
|
temp_header = None
|
||||||
@@ -196,12 +207,20 @@ class PublicHeaderChecker:
|
|||||||
|
|
||||||
def preprocess_one_header(self, header, num, ignore_sdkconfig_issue=False):
|
def preprocess_one_header(self, header, num, ignore_sdkconfig_issue=False):
|
||||||
all_compilation_flags = ['-w', '-P', '-E', '-DESP_PLATFORM', '-include', header, self.main_c] + self.include_dir_flags
|
all_compilation_flags = ['-w', '-P', '-E', '-DESP_PLATFORM', '-include', header, self.main_c] + self.include_dir_flags
|
||||||
|
# just strip comments to check for CONFIG_... macros or static asserts
|
||||||
|
rc, out, err = exec_cmd([self.gcc, '-fpreprocessed', '-dD', '-P', '-E', header] + self.include_dir_flags)
|
||||||
if not ignore_sdkconfig_issue:
|
if not ignore_sdkconfig_issue:
|
||||||
# just strip commnets to check for CONFIG_... macros
|
|
||||||
rc, out, err = exec_cmd([self.gcc, '-fpreprocessed', '-dD', '-P', '-E', header] + self.include_dir_flags)
|
|
||||||
if re.search(self.kconfig_macro, out):
|
if re.search(self.kconfig_macro, out):
|
||||||
# enable defined #error if sdkconfig.h not included
|
# enable defined #error if sdkconfig.h not included
|
||||||
all_compilation_flags.append('-DIDF_CHECK_SDKCONFIG_INCLUDED')
|
all_compilation_flags.append('-DIDF_CHECK_SDKCONFIG_INCLUDED')
|
||||||
|
# If the file contain _Static_assert or static_assert, make sure it does't not define ESP_STATIC_ASSERT and that it
|
||||||
|
# is not an automatically generated soc header file
|
||||||
|
grp = re.search(self.static_assert, out)
|
||||||
|
# Normalize the potential A//B, A/./B, A/../A, from the name
|
||||||
|
normalized_path = os.path.normpath(header)
|
||||||
|
if grp and not re.search(self.defines_assert, out) and not re.search(self.auto_soc_header, normalized_path):
|
||||||
|
self.log('{}: FAILED: contains {}. Please use ESP_STATIC_ASSERT'.format(header, grp.group(1)), True)
|
||||||
|
return self.HEADER_CONTAINS_STATIC_ASSERT
|
||||||
try:
|
try:
|
||||||
# compile with C++, check for errors, outputs for a temp file
|
# compile with C++, check for errors, outputs for a temp file
|
||||||
rc, cpp_out, err, cpp_out_file = exec_cmd_to_temp_file([self.gpp, '--std=c++17'] + all_compilation_flags)
|
rc, cpp_out, err, cpp_out_file = exec_cmd_to_temp_file([self.gpp, '--std=c++17'] + all_compilation_flags)
|
||||||
|
Reference in New Issue
Block a user