https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58822
--- Comment #29 from Jonathan Wakely <redi at gcc dot gnu.org> --- (In reply to Michi Henning from comment #27) > So, this is UB. Really nasty, in the sense that > > make_shared<T>(args) doesn't always do the same thing as shared_ptr<T>(new > T(args)) It does do effectively the same thing. The difference in behaviour is because when you use shared_ptr<T>(new T(this)) the implicit cast happens inside the class, and the compiler can resolve it without inspecting the vtable. When you use make_shared the implicit cast happens deep inside a nested function and so it inspects the vtable, which is not yet valid because the base object isn't constructed, so trying to access the vtable crashes. You can cause the same crash by doing: class InvalidArgumentException; Exception* cast(InvalidArgumentException*); class InvalidArgumentException : public virtual Exception { public: explicit InvalidArgumentException(std::string const&) : Exception(std::shared_ptr<ExceptionImplBase>(new ExceptionImplBase(cast(this)))) { } virtual ~InvalidArgumentException() noexcept {} }; Exception* cast(InvalidArgumentException* p) { return p; } The function 'cast' moves the implicit cast into a separate function, which reproduces the same crash. It should be possible to add a warning for the case where the cast happens inside the class (which doesn't crash, but is still UB) but it won't be possible to warn for the other cases, because at the site of the implicit cast the compiler doesn't know whether the pointer refers to a constructed object or not. I've created PR 70644.