https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95221
--- Comment #2 from Marek Polacek <mpolacek at gcc dot gnu.org> --- I think the thing is that we have a CALL_EXPR, something like OBJ_TYPE_REF (...) (.UBSAN_VPTR ()) and now we first evaluate the OBJ_TYPE_REF. In this case this is what seems to happen here: 1) we evaluate OBJ_TYPE_REF before the arguments: OBJ_TYPE_REF(_2;(struct MyClass)c->0) (c.0); I think this calls the destructor of 'c', and that clears up the vptr: this->_vptr.MyClass = 0B; 2) then we fetch the vptr: _5 = c->_vptr.MyClass; // _5 == null 3) we add the offset to the vtable for Doit: _6 = _5 + 16; // _6 == 16 4) we deref the pointer and crash _7 = *_6; With -fstrong-eval-order=some we instead do this _3 = c->_vptr.MyClass; _4 = *_3; OBJ_TYPE_REF(_4;(struct MyClass)c->0) (c.0); so there's no crash, and the subsequent call to the ubsan routine: _5 = c.1->_vptr.MyClass; _6 = (long unsigned int) _5; .UBSAN_VPTR (c.1, _6, 2968783897514143607, &_ZTI7MyClass, 4B); reports the error, because it sees that _6 is null.