(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

Reply via email to