https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81078

--- Comment #1 from Arthur O'Dwyer <arthur.j.odwyer at gmail dot com> ---
I've found that the misbehavior actually depends on the *ordering* of bases in
the class graph, not just the shape of the graph.

// https://wandbox.org/permlink/DaKQxTc5Ldqj9FlY

#include <stdio.h>

struct Sideboard { virtual ~Sideboard() {} };
struct Shared { virtual ~Shared() {} };
struct Public : public virtual Shared {};
struct Protected : protected virtual Shared {};

template<class... Ts> struct Main : Ts... {};

template<class... Ts>
void test() {
    Main<Ts...> m;
    Sideboard *sb = &m;
    Shared *sh = &m;
    if (dynamic_cast<Shared*>(sb) != sh) {
        puts(__PRETTY_FUNCTION__);
    }
}

int main() {
    test<Protected, Public, Sideboard>();
    test<Protected, Sideboard, Public>();
    test<Public, Protected, Sideboard>();
    test<Public, Sideboard, Protected>();
    test<Sideboard, Protected, Public>();
    test<Sideboard, Public, Protected>();
}


OUTPUT is:
void test() [with Ts = {Public, Protected, Sideboard}]

That is, the failure case seems to be when (and only when):
- the base being casted "from" is laid out after any base descended from "to",
AND
- the last base (in lexical order) descended from "to" is not publicly
descended from "to".

Reply via email to