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...
The first example with arrays is PR 110057 also.