[Bug middle-end/78977] [7 Regression] g++7 snprintf() of double produces wrong code with -O3

msebor at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Wed Jan 4 17:19:00 GMT 2017


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78977

--- Comment #11 from Martin Sebor <msebor at gcc dot gnu.org> ---
Thanks.  The preprocessed file is what we need.  I see two snprintf calls being
optimized in the SEQAN_TEST_test_random_beta_write function:

  On line 52569 substituting 3 for snprintf return value (output constant).
  On line 52569 snprintf in-bounds return value in range [3, 8].

The line numbers correspond to the preprocessed file with #line directives and
empty lines removed and point to the template below:

  inline typename Size<TTarget>::Type
  appendNumber(TTarget & target, double source);

Of the two lines, the first one is the one that would affect the subsequent
write call.  The source argument is 0.5 which is represented exactly in binary
and which snprintf formats as the three bytes "0.5" and that's also what GCC
assumes.  The second line corresponds to the argument value of 0.3.  0.3 is not
represented exactly and how it's formatted depends on the rounding mode.  When
rounded down, it's formatted as "0.299999" (8 bytes), when up or to nearest
(the typical default) it's "0.3" (3 bytes).  So GCC determines the return value
is [3, 8].  The range is not used in the subsequent write call but it could be
used if the return value of the function were used elsewhere.  I checked
appendNumber callers and none uses it.

From the assertion in comment #0:
Assertion failed : CharString("~Beta(0.5,0.3)") == os.str() was: ~Beta(0.5,0.3)
!= ~Beta(0.5,0.3
[NON-XML-CHAR-0x8]


)

it looks as though the return value with your version of GCC is greater than 3
and the function ends up writing junk after the "0.3".  You can see what GCC
thinks the return value is by compiling the file with
-fdump-tree-printf-return-value and looking in the output file (named something
like test_random.c.173t.printf-return-value2) for lines that start with the
text "On line "  You should see the same two lines as above (with different
line numbers).   When you look at the snprintf calls in the function body below
you should see something like this:

  snprintf (&buffer, 32, "%g", 5.0e-1);
  _204 = 3;
  ...
  _355 = snprintf (&buffer, 32, "%g",
2.99999999999999988897769753748434595763683319091796875e-1);
  len_356 = (size_t) _355;


showing that the first return value is optimized to the constant 3 and the
second return value is no optimized (it comes from the function call).  If the
return value from the second call is optimized into a constant that would point
to a bug in GCC.  If not, it would point to a bug in snprintf.

If this is too complicated please attach the output file produced by the
-fdump-tree-printf-return-value function to this report.


More information about the Gcc-bugs mailing list