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.

Reply via email to