Can someone show me a minimum example showing that -fvisibility-inlines-hidden are still necessary if I'm already using -fvisibility=hidden ?
The example is as follows, compile it as part of your shared library:
struct __attribute__((visibility("default"))) A {
void foo() {}
void bar();
};
auto pfoo = &A::foo;
auto pbar = &A::bar;
void A::bar() {}
If you build using only -fvisibility=hidden flag then both A::foo and A::bar will be visible in shared library (as shown by objdump -T libYours.so | c++filt). But if you add -fvisibility-inlines-hidden flag then only A::bar remain visible.
According to http://gcc.gnu.org/wiki/Visibility
... command line switch: -fvisibility-inlines-hidden. This causes all inlined class member functions to have hidden visibility, causing significant export symbol table size & binary size reductions though not as much as using -fvisibility=hidden. However, -fvisibility-inlines-hidden can be used with no source alterations, unless you need to override it for inlines where address identity is important either for the function itself or any function local static data.
So in most situations, -fvisibility-inlines-hidden is implied by -fvisibility=hidden, except for rare cases as above example.
The benefit of -fvisibility-inlines-hidden flag is that it can be almost safely added to build a program where previously all symbols were visible and get some reduction in export symbol table for free, because excluded symbols are anyway inline and so they are available in other modules without export symbol table "unless you need to override it for inlines where address identity is important either for the function itself or any function local static data".
And the usage of -fvisibility=hidden requires manual marking with __attribute__((visibility("default"))) of the symbols needed outside of a shared library.