https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70955
--- Comment #12 from Richard Biener <rguenth at gcc dot gnu.org> --- The patch hints at type merging not being performed properly. AFAIR I saw that for some of the eventually late built "global" types in the backend: /* Calling abi specific va_list type nodes. */ static GTY(()) tree sysv_va_list_type_node; static GTY(()) tree ms_va_list_type_node; those are not streamed by-index and thus while cross-TU merging will produce exactly _one_ ms_va_list_type_node the one created by the backend for lto1 is _not_ merged with the one coming from the input TUs. And type "sharing" in the middle-end is broken by the explicit call to build_variant_type_copy in /* Setup the builtin va_list data type and for 64-bit the additional calling convention specific va_list data types. */ static tree ix86_build_builtin_va_list (void) { if (TARGET_64BIT) { /* Initialize ABI specific va_list builtin types. */ tree sysv_va_list, ms_va_list; sysv_va_list = ix86_build_builtin_va_list_64 (); sysv_va_list_type_node = build_variant_type_copy (sysv_va_list); /* For MS_ABI we use plain pointer to argument area. */ ms_va_list = build_pointer_type (char_type_node); ms_va_list_type_node = build_variant_type_copy (ms_va_list); return (ix86_abi == MS_ABI) ? ms_va_list : sysv_va_list; because just having a char * pointer would otherwise be matching too many "random" pointers? Anyway, dispatching based on the type given the above "non-difference" is not going to work reliably. LTO type merging will have merged the incoming TUs ms_va_list_type_node with char_type_node. I suggest to differentiate the type by attaching an attribute, say, do the equivalent of typedef char *ms_va_list_type_node __attribute__((ms_va_list_type)); or similar.