https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91859
Bug ID: 91859 Summary: Optnization -O2 removes valid and necessary code Product: gcc Version: 9.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: mingodad at gmail dot com Target Milestone: --- When compiling the sample bellow with g++9 (9.1 and 9.2) with optmization -O2 the generated code eliminates a valid and necessary code: ===== #include <stdio.h> #include <stdlib.h> struct Expression { Expression *next; Expression *right; void *operator new(size_t); void operator delete(void *); }; void * Expression::operator new(size_t sz) { return malloc(sz); } void Expression::operator delete(void *p) { Expression *e = (Expression*)p; printf("%p : %p\n", e, e->next); while(e->next) { Expression *f = e->next; //pretend doing something printf("delete is doing something with %p\n", e->next); e = f; } free(p); } int main() { Expression *etmp, *ebase; etmp = ebase = new Expression(); for(int i = 0; i < 10; ++i) { etmp->next = new Expression(); etmp->right = new Expression(); etmp->right->next = NULL; etmp->next->right = new Expression(); etmp->next->right->next = NULL; etmp->next->right->right = NULL; etmp = etmp->next; } etmp->next = NULL; Expression *e, *e0, *e1, *efirst, **ep; if ((efirst = ebase)) { ep = &e0; while((e = efirst)) { *ep = e1 = e->right; efirst = e->next; e->next = 0; //!! with -O2 this line is eliminated delete e; while((e = e1->next)) e1 = e; ep = &e1->next; } } return 0; } ===== To build: ===== g++-8 -g -o gcc8-bug-no-optmization gcc9-bug.cpp g++-8 -O2 -g -o gcc8-bug-O2 gcc9-bug.cpp g++-9 -g -o gcc9-bug-no-optmization gcc9-bug.cpp g++-9 -O2 -g -o gcc9-bug-O2 gcc9-bug.cpp ===== Output: ===== ./gcc8-bug-no-optmization 0x560315ecc260 : (nil) 0x560315ecc280 : (nil) 0x560315ecc2e0 : (nil) ./gcc8-bug-O2 0x5562bab29260 : (nil) 0x5562bab29280 : (nil) 0x5562bab292e0 : (nil) ./gcc9-bug-no-optmization 0x557550cd0260 : (nil) 0x557550cd0280 : (nil) 0x557550cd02e0 : (nil) ./gcc9-bug-O2 0x5617642e3260 : 0x5617642e3280 delete is doing something with 0x5617642e3280 delete is doing something with 0x5617642e32e0 0x5617642e3280 : 0x5617642e32e0 delete is doing something with 0x5617642e32e0 0x5617642e32e0 : (nil) ===== The sample code is similar to a production code that do some work inside the custom delete if the "next" pointer is not NULL. g++-8 and older works as we expect so far only gcc9 (9.1 and 9.2) changed the generated code breaking our build.