If the following code is compiled with -O3
and -fPIC
, the compiler will not be able to inline Foo::priv()
since it has external linkage. In contrast, Foo::priv2()
can be inlined since it has internal linkage. Live on Compiler Explorer
// foo.hpp
class Foo {
public:
int fn();
int fn2();
private:
static int priv();
static __attribute__((visibility("hidden"))) int priv2();
};
// foo.cpp
#include <functional>
template <std::invocable Func>
int run(Func func)
{
int sum = 0;
for (int i = 0; i < 10'000'000; ++i) {
sum += func();
}
return sum;
}
int Foo::fn() { return run(&Foo::priv); }
int Foo::fn2() { return run(&Foo::priv2); }
int Foo::priv() { return 1; }
int Foo::priv2() { return 1; }
I acknowledge that the compiler can't optimize Foo::fn()
by inlining Foo::priv()
since it is possible for a) some other dynamic library to provide an implementation for Foo::priv()
and b) the other dynamic library is linked first. In the above code, the cost of not inlining Foo::priv()
is substantial.
Imagine a large code base with many shared libraries and it is possible to guarantee that exactly one shared library will provide a definition for a private member function. If it is helpful, that guarantee can be extended to all member functions.
In this situation, is there some viable option for compiling the code to enable inlining for Foo::priv()
without manually specifying the visibility (or manually inlining the code)?
There are of course ways of applying symbol visibility to many declarations at once, but that’s sort of missing the point: symbol visibility isn’t the same as linkage as defined by the language (since the latter exists in an idealized world without dynamic objects at all). If you really were happy with internal linkage (which applies per translation unit, not per shared object), you want the question linked from your own comment.
A third option here might be to simply use -fno-semantic-interposition
which disables the other-dynamic-library feature that you don’t want.