[Bug c/78304] [7 Regression] -Wformat doesn't warn anymore for inttypes.h format string argument type mismatches

dmalcolm at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Thu Jan 12 21:25:00 GMT 2017


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.


More information about the Gcc-bugs mailing list