I believe the following testcase: struct A { virtual int foo (void) {return foo();} }; struct B { struct A a; }; struct A a[7]; int test(void) { return a[3].foo(); } int test2(struct B *b) { return b->a.foo(); } ought to get devirtualized by C++ FE based on the fact that the object is contained within an structure or array. (this is related to PR46507) In the following testcase: namespace { struct A { virtual int foo (void) {return 42;} }; } int test(void) { struct A a, *b=&a; return b->foo(); } We can now probably use ipa-devirt's type inheritance graph to work out right away that A is a final class. And finally: struct A { virtual int foo (void) {return foo();} }; IMO allows devirtualization of self recursive functions
The self-recursion testcase is wrong, as can be seen by the following testcase: #include <stdio.h> struct A { virtual int foo (void) {return foo()+1;} }; struct B: public A { virtual int foo (void) {return 1;} }; main() { struct B b; printf("%i\n",b.A::foo()); } Still, given that recursive virtual functions seems frequent, I wonder if we can't try to track such explicit calls that breaks the assumption that a virtual function is called only for derived types that do not overwrite it and try to optimize at least for local functions...