0

In my C code, there were some instances of non-static symbols with the same name but different types across multiple compilation units. For example,

// file_a.c
#include <stdio.h>
#include <stdint.h>

struct a {
    uint32_t value;
} global;

int main()
{
    printf("%u\n", global.value);
    return 0;
}

and

// file_b.c
#include <stdint.h>

struct b {
    uint32_t *value_p;
} global;

Yes i understand this is a stupid program...it's meant to approximate code at a company I work at and cannot post but this is the idea. Compilation like so

gcc -O0 -o executable file_a.c file_b.c

gives no errors. When I enable -flto

gcc -O0 -o executable -flto file_a.c file_b.c

it gives a build error "warning: type of ‘global’ does not match original declaration [-Wlto-type-mismatch]" as expected. As far as I understand, these global variables with the same name are resolved to the same symbol at link time since they are not static. I am not sure what role -flto would play but regardless this coding style can give rise to bugs with or without -flto. For various reasons, I cannot enable -flto but would like to catch these instances as warnings or errors. If I enable the listed flag from the error output:

gcc -O0 -o executable -Wlto-type-mismatch file_a.c file_b.c

it builds, since it seems the flag does nothing unless -flto is enabled. So my question is how can I catch these errors (duplicate names for symbols across compilation units, with or without differing types) and use that flag without enabling -flto. Is it just not an error unless link time optimization is on?

Thank you very much.

someone serious
  • 197
  • 1
  • 1
  • 8
  • 1
    Don't use `-O0`. Do use `-Wall -Wextra -Werror`. Do use one header to declare `global`. Do use the same header in every source file that references the variable, and the sole source file that defines the variable. Then the compiler can point to mismatches in each TU (translation unit). Spotting it otherwise is beyond the compiler's ability — processes each TU separately, and cannot spot inter-TU inconsistencies unless you use `-flto`. Yes, legacy code bases can be appallingly bad about such issues — I work on a code base that used to have such problems until depressingly recently. – Jonathan Leffler Jul 17 '23 at 18:12
  • 1
    GCC 10 changed the default from `-fcommon` to `-fno-common`. Under the old default, your code would link (for better or worse). Under the new default, the code won't link because the variable will be multiply defined. This conforms better to the standard; the old behaviour was recognized as a 'common extension'. See also [How do I use `extern` to share variables between source files?](https://stackoverflow.com/q/1433204/15168) – Jonathan Leffler Jul 17 '23 at 18:18
  • @JonathanLeffler `-fno-common` helps with a mismatch between definitions, but not with a mismatch between declarations. – n. m. could be an AI Jul 17 '23 at 19:06
  • @n.m.willseey'allonReddit: yes. My prior comment says that you can’t spot those inconsistencies unless you use `-flto`. That stands even in the light of my latter comment. – Jonathan Leffler Jul 17 '23 at 19:09
  • @JonathanLeffler thanks. `-fno-common` gets the job done and was exactly what i needed, as the errors caught seem to be a superset of the errors caught by `-Werror=lto-type-mismatch` – someone serious Jul 19 '23 at 18:54

0 Answers0