https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119215
--- Comment #20 from Harald van Dijk <harald at gigawatt dot nl> ---
(In reply to James K. Lowden from comment #18)
> A type that is not shared is not shared, and "another translation unit"
> cannot use it, whether or not by mistake.
I wrote about typeinfo as a reason why the rule *has* to be that even types
that are not visibly used externally have to be compatible if they have
external linkage. Consider this as a concrete contrived example of that:
a.cc
#include <typeinfo>
#include <stdio.h>
enum Foo : char {};
void a() { printf("%p\n", (void *) &typeid(Foo)); }
b.cc
#include <typeinfo>
#include <stdio.h>
enum Foo : short {};
void a();
void b() { printf("%p\n", (void *) &typeid(Foo)); }
int main() { a(); b(); }
Clearly a.cc and b.cc's Foo cannot be the same type as they do not even have
the same size. Therefore either this program must print two distinct values, or
must have undefined behaviour despite the fact that Foo is not used across
translation units. When compiled with GCC, this prints the same value twice, so
either GCC has a bug, or this program has undefined behaviour.
The answer is the latter, the lto-type-mismatch diagnostic is correct. The C++
standard specifies in [basic.link]p4 that named enumerations have linkage just
like variables and functions do, none of the exceptions to give it internal
linkage apply here, therefore it has external linkage, and then [basic.def.odr]
applies as normal, the definitions have to match.