-
Notifications
You must be signed in to change notification settings - Fork 7.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[IDF 5.0] type 'uint32_t' {aka 'long unsigned int'} (IDFGH-8001) #9511
Comments
duplicate #6906 |
Sorry for the breakage folks, we meant to silence the formatting errors in all Espressif-maintained components before merging d10d57a, but apparently have missed those two. Will fix soon. I think #6906 will be closed with resolution "works as intended" now that we have uint32_t == unsigned long for both Xtensa and RISC-V. Linking also the relevant part of the v5.0 migration guide: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/migration-guides/release-5.x/gcc.html#int32-t-and-uint32-t-for-xtensa-compiler |
Not a big problem, i just wanted to play around, and as usually i am so unlucky and i picked 2 components which are the only affected by the issue. |
I ran into this issue because my project was depending on another project which doesn't compile with the new change. The workaround I posted can be used while you wait for upstream projects to merge fixes. |
Reported at espressif/esp-idf#9511 Follow-up in #65
With current esp-idf master tree, I got many build error in esp_littlefs: Also note I got similar errors in my application code. (Mostly in ESP_LOGx) |
some of my logging was a little loose on types; fixing them right now and will make a release. |
@BrianPugh |
Is it possible to keep "-Wno-error=format=" for a while so the out-of-tree modules have chance to fix this compile warnings. |
@AxelLin We could do that, however as far as I can tell from littlefs and a few other projects, CI builds aren't using -Werror flag, so the new warnings would mostly go unnoticed. For any component which doesn't compile with -Werror yet, you can add the following into the project CMakeLists.txt file, after the # e.g. for espressif/button component:
idf_component_get_property(lib espressif__button COMPONENT_LIB)
target_compile_options(${lib} PRIVATE -Wno-error=format) (optionally after checking that IDF version >= 5.0) Regarding the original issue report, usb_host_cdc_acm has also been updated with the fix. |
I think that this change will affect a lot of code. This was especially painful on my part, as about the only place I use printf style formatting is in ESP_LOGx, and the way the macros get defined will bury the actual location of the error under a number of entries shown for esp_log.h. It is, however, the right change to make and will result in better quality code. |
I can confirm: see Sample here: |
|
Ran into this trying to build the tot-reference-esp32c3 for esp32-s3. From the comment above: "I think #6906 will be closed with resolution "works as intended" now that we have uint32_t == unsigned long for both Xtensa and RISC-V" It appears that xtensa still has issues with unsigned long (c string specifiers in the logging calls). Thanks for the workaround!!! |
Hmmm, it is insane! |
@fpgamaster sizeof(uint32_t) == sizeof(unsigned int) == sizeof(unsigned long) for both the older toolchain releases and the new release. However C language distinguishes If you consider the following code, #include <stdint.h>
#include <stdio.h>
void print(int32_t num) {
printf("My %x\n", num);
} On several architectures, compiler will produce an error:
This is because This behavior is not unique to GCC for Xtensa architecture. Here you can see that the same error is produced by GCC for the 32-bit ARM: https://godbolt.org/z/Yfb1Tdbbc and for the 32-bit RISC-V: https://godbolt.org/z/ras4bvf86. It would have been nice if GCC had a command line option to disable such "pedantic" format string warnings while keeping the "useful" format string warnings. There is a request for this: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80060. We have decided that while the breakage caused by changing the uint32_t type is going to be painful in near term, longer term it is better to have the format warnings enabled, as these warnings often catch legitimate bugs. We are gradually fixing the format warnings in ESP-IDF components and removing the -Wno-format flags, and we hope that the developers building projects and components with ESP-IDF will do the same. |
Hi @igrr, Ok, But the size of int and unsigned int is 4 bytes, respectively long int is 8 bytes. 'unsigned long' stands for 'unsigned long int'? |
If we are talking about 32-bit RISC-V, Xtensa (or ARM, for that matter), that's not the case: both
You can check this for various compilers here: https://godbolt.org/z/hzbjMKKrs. (To make the size visible at compile time, the code produces a compiler error. The size can be seen as part of the error message on the right, e.g. the |
@igrr, Best regards |
Both variables will occupy 4 bytes, and incrementing the pointers to such variables will move the pointer by 4 bytes. It is the same for all of these: sizeof(unsigned int) == 4, sizeof(unsigned long) == 4, sizeof(uint32_t) == 4. If you were compiling the code for a 64-bit architecture, you would typically see |
@igrr, Best regards |
@mallaprashant please look into the latest hello World: the Printf must look like this: printf("Minimum free heap size: %" PRIu32 " bytes\n", esp_get_minimum_free_heap_size()); |
Why not use standard type 'uint32_t' which is a common definition coss all system. 'PRIu32' seems a duplicated definition introduce conflicts and complicity. |
PRIu32 is for printing formating to uint32_t variables. |
uint32_t is formating to 'unsigned int', that's the compiler needs, why do we do a formating fron 'PRIu32' -> 'uint32_t'? |
PRIu32 is string. uint32_t is a binary number. The printf transform de binary number in a string for better human readability. Example: uint32_t a = 0x12345678 To store this number in memory the computer need 4 bytes(each byte in a single memory address). Address 0: 0x78 The 'PRIu32' instruct printf to decode these 4 bytes in a string. Dont confuse string with number. That's more or less it. |
Not all compilers consider unsigned int 32 bits. This varies by compiler and hardware platform. Microchip's xc16 compiler, for example, considers unsigned int to be 16 bits. |
OK, I see. So PRIu32 is a string for "%d"? But I don't see any needs to introduct PRIu32 as a string for printf. It looks to me the fix is to hide the warning instead of fix it. 'int' is dynamic according with CPU architecture, specificaly it is the data bus width between CPU and it's memory. As I mentioned above, to eliminate the dynamic we want to use 'uint32_t' or 'uint16_t' instead of working with 'int' 'short' directly. So we tell our definition which CPU architecture we are working on, meanwhile tell c compiler what is the targeted CPU architcture, that's all we need to do. |
PRIu32 is a formatting string for uint32_t. PRId32 is a formatting string for int32_t. https://www.ibm.com/docs/en/zos/2.4.0?topic=files-inttypesh-io-format-integer-types |
OK, that is fine...
Which means uint32_t is wrongly defined as 64bits long? |
In this case uint32_t is defined as |
I dont complain, but this is misleading:
According to this error argument is
So, is Thanks |
The safest way to check the real size of the type is to use
This is indeed confusing, I agree. I'll try to explain why this happens. First, the macro CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ is expanded to an integer value, for example In C, variadic arguments undergo default argument promotions. Integer types with rank lower or equal than To compensate for this promotion of the argument, C language standard defines the
If you were to write the following code: unsigned short val = 160;
printf("%hu\n", val); the 16-bit value Now consider the case if unsigned int val = 160;
printf("%hu\n", val); The exact same thing happens as in the previous case: This code compiles and works, and the compiler doesn't warn about the mismatch between At the same time, the following code: unsigned long val = 160;
printf("%u\n", val); generates a warning. This is because The important thing to understand about these conversions and warnings is that they are all related to integer type ranks, not integer type sizes. The compiler treats Related to this topic, there is a feature request for GCC to provide a variant of |
I know the Thanks |
Sorry, maybe I misunderstood your question. Did you mean "what format specifier should i use to format an If the variable is declared as an
(See cppreference for the full list) |
I would like to ask, which version of the fix this BUG, I am now using 5.1.1, whether it is %x or %d will show incorrect type. error: format '%x' expects argument of type 'unsigned int', but argument 6 has type 'TickType_t' {aka 'long unsigned int'} [-Werror=format=] |
Reported at espressif/esp-idf#9511 Follow-up in espressif/idf-extra-components#65
Im not sure if its possible to reproduce with normal example, but i am trying to add managed component to my custom component as dependency (here it is USB host as example, but it was also with button). I think error log is self explaining the problem:
The question is why
uint32_t
is of typelong unsigned int
?With v4.4 it is building without problems.
Thanks
EDIT
The text was updated successfully, but these errors were encountered: