[Bug c++/86908] New: static_cast(&derivedClassObject)->virtualMehod() calls base version of virtualMethod()

2018-08-10 Thread fro0m.spam at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86908

Bug ID: 86908
   Summary: static_cast(&derivedClassO
bject)->virtualMehod() calls base version of
virtualMethod()
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: fro0m.spam at gmail dot com
  Target Milestone: ---

#include 
#include 
#include 
#include 


class BaseStrategy{
public:
virtual void doIt() {
printf("base do it\n");
};
};

class AStrategy : public BaseStrategy 
{
public:
void doIt() {
printf("A do it\n");
};
};

class BStrategy : public BaseStrategy 
{
public:
void doIt() {
printf("B do it\n");
};
};

int main() 
{
BaseStrategy strategy;
BaseStrategy* strategyPtr = &strategy;
strategyPtr->doIt();

new(&strategy) AStrategy;
static_cast(&strategy)->doIt();
strategyPtr->doIt();
}


Output in gcc 4.9 and gcc 9.0 is
base do it
base do it
A do it

the right output must be (according to standard and behavior of MSVC 2015 and
clang 6) is
base do it
A do it
A do it

[Bug c++/86908] static_cast(&derivedClassObject)->virtualMehod() calls base version of virtualMethod()

2018-08-10 Thread fro0m.spam at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86908

Kostya Frumkin  changed:

   What|Removed |Added

 Status|RESOLVED|UNCONFIRMED
Version|unknown |9.0
 Resolution|INVALID |---

--- Comment #3 from Kostya Frumkin  ---
(In reply to Jonathan Wakely from comment #1)
> No, your program has undefined behaviour. To make it valid you either need
> to use std::launder, or use the pointer that is returned by the placement
> new.
> 
> The compiler is allowed to assume that the dynamic type of &strategy does
> not change (that's why you need to use std::launder).

Hi, for example msvc2013 calls base class's virtual method when msvc2015 calls
derived class's virtual method.
This is developer's mistake which can be predicted by compiler. Few developers
know about this behavior.
It'd be awesome to see the correct behavior or at least warning that base
method is being used after placement new.

[Bug c++/86908] static_cast(&derivedClassObject)->virtualMehod() calls base version of virtualMethod()

2018-08-10 Thread fro0m.spam at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86908

--- Comment #5 from Kostya Frumkin  ---
(In reply to Jonathan Wakely from comment #4)
> (In reply to Kostya Frumkin from comment #3)
> > Hi, for example msvc2013 calls base class's virtual method when msvc2015
> > calls derived class's virtual method.
> 
> It's undefined behaviour. Anything can happen.
> 
> > This is developer's mistake which can be predicted by compiler. Few
> > developers know about this behavior.
> 
> Using placement new to replace a polymorphic type is not a common idiom, I
> don't think it's worth adding a warning about it. Just don't do it.
> 
> > It'd be awesome to see the correct behavior or at least warning that base
> > method is being used after placement new.
> 
> GCC's behaviour is already correct.

It is best way to get away with heap allocation in many cases. Let's make a
warning about undefined behavior.

[Bug c++/86908] static_cast(&derivedClassObject)->virtualMehod() calls base version of virtualMethod()

2018-08-21 Thread fro0m.spam at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86908

--- Comment #8 from Kostya Frumkin  ---
> Either way you need to placement new the original type back again, otherwise
> the wrong destructor gets called on scope exit, which adds more undefined
> behaviour.

There should not be undefined behavior because the size of both classes is same
and destructors executes same code (in the case it is noop).
So the memory to be freed up is same.

The behavior must be defined by ISO committee because it is counterintuitive
when the base methods are being called. (where to ask?)

At the same time this design pattern (strategy) with placement-new is more
efficient than with common new. So it has no rationale if the base methods are
used when using placement-new. At the same time other compilers generates code
where the derived method is callsed after placement-new. 

So I see two ways:
- Ask the community to define behavior.
or
- Define behavior in gcc itself.