https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90535
Bug ID: 90535 Summary: Wrong branch selected if (--(s.ptr)) Product: gcc Version: 9.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: vbraun.name at gmail dot com Target Milestone: --- Decrementing a struct member pointer is not seen in a subsequent if() branch, so tests like if (--(s.ptr)) jump to the wrong branch. This is with gcc 9.1.1 and -O1 or higher, -O0 works correctly. The following is a simplified testcase that was extracted from a real-world reference counting implementation: ======================================================= #include "stdio.h" struct MyStruct { void *ptr; }; int main() { struct MyStruct s; s.ptr = NULL + 1; // The bug only happens if we have a pointer to s, even though we don't really use it struct MyStruct *struct_ptr = &s; printf("MyStruct *struct_ptr = %p\n", struct_ptr); // need to use it once printf("------------ ptr = 0x1 ----------------------------\n"); printf("ptr is 0x1: %p\n", s.ptr); if (s.ptr) { printf("ptr is truthy (correct!) %p\n", s.ptr); } printf("------------ ptr = NULL ----------------------------\n"); (s.ptr)--; // We should be back to 0x0 now // Uncomenting the following line makes the bug disappear // printf("ptr is null: %p\n", s.ptr); if (!(s.ptr)) { printf("ptr is falsy (correct!) %p\n", s.ptr); } if (s.ptr) { printf("ptr is truthy (wrong!) %p\n", s.ptr); } return 0; } ======================================================= $ gcc -O1 test_char_ptr.c && ./a.out MyStruct *struct_ptr = 0x7ffd0b049758 ------------ ptr = 0x1 ---------------------------- ptr is 0x1: 0x1 ptr is truthy (correct!) 0x1 ------------ ptr = NULL ---------------------------- ptr is truthy (wrong!) (nil) $ gcc --version gcc (GCC) 9.1.1 20190503 (Red Hat 9.1.1-1) Copyright (C) 2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.