I believe this is a known problem, but I couldn't find it anywhere. The inliner at -O2 will attempt to inline any small functions. It will not however try to inline functions will external linkage, which includes all templated functions. As much C++ code (including libstdc++) contains many small templated functions, this means it is necessary to mark all these functions as inline to ensure they are even considered at -O2. Example: given: void foo() {} void foo2() {foo();} int main() {foo2();} then main() is optimised away to an empty function at -O2. However: template<class T> void foo() {} template<class T> void foo2() {foo<T>();} int main() {foo2<int>();} leaves the calls to foo2 and foo in at -O2. Is there a good reason to not pull inlining of small functions (which in C++ typically consist of simply calling a new function with almost identical parameters) into -O2, even when they have external linkage? (or make an exception for templated functions?)
Note there are two problems here, foo2/foo in the orginal example are found to pure/const function so they are optimizated away which is different than inlining. This all fixed on the tree profiling branch where we actually find the templates functions are pure/const also. Note at -Os we do turn on -finline-functions and inline small functions.
Fixed in 4.1.0.