This is kind of a follow-up question to Symbol visibility and namespace
I'll modify the example slightly because it isn't really about namespacing:
namespace MyDSO {
struct __attribute__ ((visibility ("hidden"))) Foo {
void bar() {}
};
}
struct Bar {
MyDSO::Foo foo;
};
int main() {}
Compiling via gcc example.cpp -o example
spits out the warning ‘Bar’ declared with greater visibility than the type of its field ‘Bar::foo’
as in the linked question.
Question: Why don't I get the warning if I
a) explicitly add default visibility to the struct Bar, i.e. I have
namespace MyDSO {
struct __attribute__ ((visibility ("hidden"))) Foo {
void bar() {}
};
}
struct __attribute__ ((visibility ("default"))) Bar {
MyDSO::Foo foo;
};
int main() {}
b) delete the hidden visiblity, add default visibility to Bar and compile using -fvisibility="hidden"
?
It seems to me that the end result is the same, and indeed, all binaries are exactly the same (gcc 7.3.1, but also older ones). If I split the two structs into two classes and build a static library with them, the symbol tables (objdump -t -C) contain the exact same symbols with the exact same modifiers (global, local, etc), only a few entries in the first column (virtual adresses) differ.
In both cases, an explicit visibility attribute is the intended way to silence the warning on a per-class basis. From gcc/cp/decl2.c
:
/* Don't warn about visibility if the class has explicit visibility. */
if (CLASSTYPE_VISIBILITY_SPECIFIED (type))
vis = VISIBILITY_INTERNAL;