https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78304
--- Comment #4 from David Malcolm <dmalcolm at gcc dot gnu.org> --- Notes to self: PRIu32 etc are described in: http://en.cppreference.com/w/c/types/integer#Format_macro_constants Ideal would be a fix-it hint that suggests the correct macro, but that's clealy overambitious in stage 3. (gdb) p fmt_loc $2 = (const substring_loc &) @0x7fffffffc4e0: {m_fmt_string_loc = 22834856, m_string_type = 0x7ffff1a48738, m_caret_idx = 7, m_start_idx = 6, m_end_idx = 7} Indices suggest that we would highlight: %u ~^ i.e. with caret on the 'u'. (gdb) p fmt_substring_range $5 = {m_start = 22835072, m_finish = 5642112} (gdb) p fmt_loc_range $6 = {m_start = 22834848, m_finish = 22835104} (gdb) call inform (fmt_substring_range.m_start, "fmt_substring_range.m_start") ../../src/pr78304.c:8:18: note: fmt_substring_range.m_start printf ("size: %" PRIu32 "\n", size); ^ (gdb) call inform (fmt_substring_range.m_finish, "fmt_substring_range.m_finish") In file included from ../../src/pr78304.c:1:0: /usr/include/inttypes.h:104:19: note: fmt_substring_range.m_finish # define PRIu32 "u" ^ ...so we have a range that splits between two different files. Hence we erroneously hit case 1 of the conditional: if (fmt_substring_range.m_start >= fmt_loc_range.m_start && fmt_substring_range.m_finish <= fmt_loc_range.m_finish) /* Case 1. */ { substring_within_range = true; primary_loc = fmt_substring_loc; } ...since: (gdb) call inform (fmt_loc_range.m_start, "fmt_loc_range.m_start") ../../src/pr78304.c:8:11: note: fmt_loc_range.m_start printf ("size: %" PRIu32 "\n", size); ^ (gdb) call inform (fmt_loc_range.m_finish, "fmt_loc_range.m_finish") ../../src/pr78304.c:8:19: note: fmt_loc_range.m_finish printf ("size: %" PRIu32 "\n", size); ^ ...and hence we use: (gdb) p fmt_substring_loc $7 = 2147483653 (gdb) call inform (fmt_substring_loc, "fmt_substring_loc") In file included from ../../src/pr78304.c:1:0: /usr/include/inttypes.h:104:19: note: fmt_substring_loc # define PRIu32 "u" Case 1 seems to be missing a couple of conditionals: --- a/gcc/substring-locations.c +++ b/gcc/substring-locations.c @@ -113,11 +120,17 @@ format_warning_va (const substring_loc &fmt_loc, else { if (fmt_substring_range.m_start >= fmt_loc_range.m_start + && fmt_substring_range.m_start <= fmt_loc_range.m_finish + && fmt_substring_range.m_finish >= fmt_loc_range.m_start && fmt_substring_range.m_finish <= fmt_loc_range.m_finish) /* Case 1. */ { and doing so fixes the issue, by making format_warning_va use case 2 here: ../../src/pr78304.c: In function ‘main’: ../../src/pr78304.c:8:11: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 2 has type ‘size_t {aka long unsigned int}’ [-Wformat=] printf ("size: %" PRIu32 "\n", size); ^~~~~~~~~ In file included from ../../src/pr78304.c:1:0: /usr/include/inttypes.h:104:19: note: format string is defined here # define PRIu32 "u" Alternatively, perhaps the substring location code should detect when there's a big discontinuity within the requested range (e.g. not it same file), and fail if this happens, making format_warning_va use case 3.