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

Jason Merrill <jason at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P3                          |P1
                 CC|                            |aldyh at gcc dot gnu.org,
                   |                            |jason at gcc dot gnu.org

--- Comment #5 from Jason Merrill <jason at gcc dot gnu.org> ---
The dataflow analysis seems to be:

We set the length of one string to 0, and the other string to 16.  Then we
store a char to the string buffer, which the compiler thinks could possibly
have clobbered the  length we previously set to 0, so we reload it.  And we add
the two together.  So now we have a combined length about which we think we
know nothing

We should really somehow tell the compiler that stores to the string char
buffer can't alias other non-char objects.  And maybe in general we could do
branch prediction based on assuming that char stores don't clobber values we
knew before?  But let's put that missed-optimization issue in a separate PR.

So, let's focus away from that problem by making the second string unknown:

#include <string>
std::string foo(std::string x)
{
  return std::string("1234567890123456") + x;
}

I get the same surprising warning with this testcase.

Now, we have an unknown total length.  We compare this length to the size of
the local buffer, which partitions the range at 16.  On the path where the sum
of the lengths is <=16, we conclude that the length of string A must either be
0 or a number so large that adding 16 to it causes it to wrap around to [0,16]
(because integer overflow in unsigned arithmetic is defined).  Which branch
prediction thinks is just as likely as 0.

So then along that branch we try to append this impossibly large hypothetical
string to this string we do know the length of, and we get this warning.

So, the warning seems to be that if we were to call _M_append with a
ridiculously large __n argument, we would get undefined behavior.  In other
words, if x happened to be the longest possible string.  It seems that we check
for unreasonable length arguments in the char* append functions, but not in the
string append function.  Changing them to do that check silences the warning. 
I'll attach a patch in a moment.

Reply via email to