(copying your mail to the gcc mailing list again)
Benjamin Smedberg wrote:
Jason Merrill wrote:
It seems that you have a different mental model of type visibility.
The way I was thinking about it, if a type has hidden visibility, we
can't refer to it from outside its object. Thus, it doesn't make
sense for members or objects with that type to have greater visibility
because even if people can call the accessor they can't do anything
with the return value.
You certainly can refer to an hidden-visibility object outside it's
translation unit. Firstly, you should absolutely be able to pass
pointers to these objects around, even if you can't call any methods on
them. Secondly, you can safely call any virtual method, because the
method pointers is contained in the vtable and no symbol lookup is
performed. This is how all XPCOM objects are constructed: they have a
pure-virtual base class (interface), and implementation class(es); both
of these classes are completely hidden-visibility. Then there is an
accessor method which hands out the object; client code can safely call
the virtual methods.
To be clear: the reason we mark the pure-virtual interface classes
with hidden visibility is so that the class vtable is not exported as
a weak symbol from any DSOs (I'm not sure why GCC is generating a
vtable at all, since it's a pure-virtual class and cannot possibly be
instantiated), as well as the automatically-generated
constructor/destructor functions.
However, I'm not attached to this in defiance of practical concerns.
What is your model of type visibility?
The type visibility is simply the visibility of the vtable/typeinfo, and
the default for all member functions/data, but individual members/data
can be overridden if appropriate.
For instance, in my case "B" we have a class which is partially
implemented in a static library that each client links against (and thus
use hidden visibility), but one particularly complicated method is
provided by a shared library (and therefore uses default visibility):
class __attribute__ ((visibility ("hidden"))) nsID {
PRBool Equals(const nsID& aOther) const;
char* ToString() const;
__attribute__ ((visibility ("default"))) ParseFromString(const char
*aID);
};
This is fairly easy to workaround, as I said, by making the class
default-visibility and hiding the static-library-implemented methods.
OK, you've convinced me that the compiler shouldn't override or complain
about explicit visibility attributes. Do you have a problem with
implicit propagation of visibility in the absence of an attribute?
Specifically:
Do you agree with implicitly giving template instantiations the minimum
visibility of the template and arguments unless explicitly overridden?
Do you agree with implicitly lowering the visibility of declarations to
match their type if not explicitly set (e.g. if your CreateAClass didn't
have an explicit visibility attribute)?
Also, do you agree with warning about a class with greater visibility
than its data members/bases?
Jason