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

Peter Bisroev <peter at int19h dot net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|INVALID                     |FIXED

--- Comment #5 from Peter Bisroev <peter at int19h dot net> ---
Thank you for your explanation Richard, it makes perfect sense to me now. GCC
is being insanely clever here!

However I still think there is something not 100% right. If I change
containsBackwards() function to look like this:

////////////////////
int containsBackwards(const uint8_t* p, uint8_t target)
{
    for (;;)
    {
        if (*p == target)
        {
            return 1;
        }

        --p;
        if (!p)
        {
            return 0;
        }
    }
}
////////////////////

I apologize in advance as I know the code is far from ideal and is definitely a
corner case, but unless I am mistaken there is no undefined behavior here
assuming p is always valid at the time of the call and it is just to illustrate
the example. So for the above gcc 10.1 generates the following:


////////////////////
containsBackwards(unsigned char const*, unsigned char):
        mov     eax, 1
        ret
////////////////////

So my question is, is gcc allowed to assume that the target will always match?

Additionally, if I make this function a bit safer and unless I am mistaken
without any undefined behavior:

////////////////////
int containsBackwardsSafe(const uint8_t* p, uint8_t target)
{
    if (!p)
    {
        return 0;
    }

    for (;;)
    {
        if (*p == target)
        {
            return 1;
        }

        --p;
        if (!p)
        {
            return -1;
        }
    }
}
////////////////////

Then gcc 10.1 generates the following:

////////////////////
containsBackwardsSafe(unsigned char const*, unsigned char):
        xor     eax, eax
        test    rdi, rdi
        setne   al
        ret
////////////////////

Which matches the generated output of the original function. However unless I
am mistaken the result here is supposed to be different to the original
function:
* If p == NULL, return 0.
* If target matched while p was valid, return 1.
* If target did not match while p was valid return -1.

You can see these above examples at Compiler Explorer here:

https://godbolt.org/z/ha1c1h


I apologize if there is something critical I am missing here so I hope I am not
wasting your time.

Thank you!
--peter

Reply via email to