GCC

[中文]

GCC Version

The previous GCC version was GCC 8.4.0. This has now been upgraded to GCC 11.2.0 on all targets. Users that need to port their code from GCC 8.4.0 to 11.2.0 should refer to the series of official GCC porting guides listed below:

Warnings

The upgrade to GCC 11.2.0 has resulted in the addition of new warnings, or enhancements to existing warnings. The full details of all GCC warnings can be found in GCC Warning Options. Users are advised to double-check their code, then fix the warnings if possible. Unfortunately, depending on the warning and the complexity of the user's code, some warnings will be false positives that require non-trivial fixes. In such cases, users can choose to suppress the warning in multiple ways. This section outlines some common warnings that users are likely to encounter, and ways to suppress them.

Warning

Users are advised to check that a warning is indeed a false positive before attempting to suppress them it.

-Wstringop-overflow, -Wstringop-overread, -Wstringop-truncation, and -Warray-bounds

Users that use memory/string copy/compare functions will run into one of the -Wstringop warnings if the compiler cannot properly determine the size of the memory/string. The examples below demonstrate code that triggers these warnings and how to suppress them.

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#pragma GCC diagnostic ignored "-Warray-bounds"
    memset(RTC_SLOW_MEM, 0, CONFIG_ULP_COPROC_RESERVE_MEM); // <<-- This line leads to warnings
#pragma GCC diagnostic pop
#pragma GCC diagnostic push
#if     __GNUC__ >= 11
#pragma GCC diagnostic ignored "-Wstringop-overread" // <<-- This key had been introduced since GCC 11
#endif
#pragma GCC diagnostic ignored "-Warray-bounds"
            memcpy(backup_write_data, (void *)EFUSE_PGM_DATA0_REG, sizeof(backup_write_data)); // <<-- This line leads to warnings
#pragma GCC diagnostic pop

-Waddress-of-packed-member

GCC will issue this warning when accessing an unaligned member of a packed struct due to the incurred penalty of unaligned memory access. However, all ESP chips (on both Xtensa and RISC-V architectures) allow for unaligned memory access and incur no extra penalty. Thus, this warning can be ignored in most cases.

components/bt/host/bluedroid/btc/profile/std/gatt/btc_gatt_util.c: In function 'btc_to_bta_gatt_id':
components/bt/host/bluedroid/btc/profile/std/gatt/btc_gatt_util.c:105:21: warning: taking address of packed member of 'struct <anonymous>' may result in an unaligned pointer value [-Waddress-of-packed-member]
  105 |     btc_to_bta_uuid(&p_dest->uuid, &p_src->uuid);
      |                     ^~~~~~~~~~~~~

If the warning occurs in multiple places across multiple source files, users can suppress the warning at the CMake level as demonstrated below.

set_source_files_properties(
    "host/bluedroid/bta/gatt/bta_gattc_act.c"
    "host/bluedroid/bta/gatt/bta_gattc_cache.c"
    "host/bluedroid/btc/profile/std/gatt/btc_gatt_util.c"
    "host/bluedroid/btc/profile/std/gatt/btc_gatts.c"
    PROPERTIES COMPILE_FLAGS -Wno-address-of-packed-member)

However, if there are only one or two instances, users can suppress the warning directly in the source code itself as demonstrated below.

#pragma GCC diagnostic push
#if     __GNUC__ >= 9
#pragma GCC diagnostic ignored "-Waddress-of-packed-member" <<-- This key had been introduced since GCC 9
#endif
    uint32_t* reg_ptr = (uint32_t*)src;
#pragma GCC diagnostic pop

llabs() for 64-bit Integers

The function abs() from stdlib.h takes int argument. Please use llabs() for types that are intended to be 64-bit. It is particularly important for time_t.

Espressif Toolchain Changes

int32_t and uint32_t for Xtensa Compiler

The types int32_t and uint32_t have been changed from the previous int and unsigned int to long and unsigned long respectively for the Xtensa compiler. This change now matches upstream GCC which long integers for int32_t and uint32_t on Xtensa, RISC-V, and other architectures.

2021r2 and older, GCC 8

2022r1, GCC 11

Xtensa

(unsigned) int

(unsigned) long

riscv32

(unsigned) long

(unsigned) long

The change mostly affects code that formats strings using types provided by <inttypes.h>. When using these fixed-width types (e.g., uint32_t), users will need to replace placeholders such as %i and %x with PRIi32 and PRIx32 respectively. Types not defined in <inttypes.h> (e.g., int) do not need this special formatting.

In other cases, it should be noted that enums have the int type.

In common, int32_t and int, as well as uint32_t and unsigned int, are different types.

If users do not make the aforementioned updates to format strings in their applications, the following error will be reported during compilation:

/Users/name/esp/esp-rainmaker/components/esp-insights/components/esp_diagnostics/include/esp_diagnostics.h:238:29: error: format '%u' expects argument of type 'unsigned int', but argument 3 has type 'uint32_t' {aka 'long unsigned int'} [-Werror=format=]
238 |     esp_diag_log_event(tag, "EV (%u) %s: " format, esp_log_timestamp(), tag, ##__VA_ARGS__); \
    |                             ^~~~~~~~~~~~~~         ~~~~~~~~~~~~~~~~~~~
    |                                                    |
    |                                                    uint32_t {aka long unsigned int}
                                              uint32_t {aka long unsigned int}

Removing CONFIG_COMPILER_DISABLE_GCC8_WARNINGS Build Option

CONFIG_COMPILER_DISABLE_GCC8_WARNINGS option was introduced to allow building of legacy code dating from the rigid GCC 5 toolchain. However, enough time has passed to allow for the warnings to be fixed, thus this option has been removed.

For now in GCC 11, users are advised to review their code and fix the compiler warnings where possible.