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

            Bug ID: 104359
           Summary: GCC Treats bool with value != 1 as falsey when picking
                    branches
           Product: gcc
           Version: 11.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: will at willusher dot io
  Target Milestone: ---

The following code when compiled with -O0 (or no -O option), will incorrectly
take both if branches:

#include <iostream>
#include <cstring>

int main() {
    bool b = false;
    std::memset(&b, 255, 1);

    if (!b) {
        std::cout << "!b = true branch\n";
    } else {
        std::cout << "!b = false branch\n";
    }
    if (b) {
        std::cout << "b = true branch\n";
    } else {
        std::cout << "b = false branch\n";
    }
    return 0;
}

the resulting incorrect output is:

!b = true branch
b = true branch

However, b's "value" is 255, which should evaluate to "true". Recompiling the
program with -O1 or higher results in the correct output:

!b = false branch
b = true branch

Looking at compiler explorer: https://godbolt.org/z/TeMvMEc19 , it looks like
the if (!b) branch is compiled to:

        movzx   eax, BYTE PTR [rbp-1]
        xor     eax, 1
        test    al, al
        je      .L2

Which will evaluate to true for values != 1

This version of the code: https://godbolt.org/z/rhrP5W36v adds a loop and we
can see in -O1 and higher, the condition looks to just be a comparison vs. 0:

        cmp     BYTE PTR [rbp+0+rbx], 0
        jne     .L2

Reply via email to