https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99093
Bug ID: 99093 Summary: [missed optimization] Missed devirtualization involving internal-linkage class type (but only sometimes) Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: arthur.j.odwyer at gmail dot com Target Milestone: --- // https://godbolt.org/z/hx7h7v struct Base { virtual int f() { return 1; } }; namespace { struct Derived1 : public Base { int f() override { return 2; } }; struct Derived2 : public Base {}; } int leaf_class1(Base *p) { return ((Derived1*)p)->f(); } // devirtualized by GCC, because PrivateDerived is provably a leaf int leaf_class2(Base *p) { return ((Derived2*)p)->f(); } // not devirtualized by GCC -- this smells like a missed-optimization bug ==== GCC 4.9 started to be able to devirtualize things in the compiler, based on translation-unit-wide (but still compiler-time) information. GCC 4.9.0 is able to devirtualize the call in `leaf_class1`. This is awesome! However, both GCC 4.9 and GCC trunk fail to apply the exact same optimization to `leaf_class2`. The only difference between `Derived1` and `Derived2` is that `Derived1::f` is declared directly in `Derived1` whereas `Derived2::f` is technically a member of `Base`. That shouldn't matter at all to the devirtualization logic. But apparently it does. ==== Barely possibly related missed-devirtualization bugs: #47316, #60674, #89924, #94243.