Daniel Jacobowitz wrote:

> This doesn't make a lick of sense to me.  If the type is hidden, how
> on earth can it get a member function _of that type_ from another
> library?  That library would, by definition, have to have a type of
> the same name... but it would be a "different" type.

You and Chris are taking the view that "the type" has a location.  But,
a lot of people don't look at it this way.  The things that have
locations are variables (including class data) and functions.  After
all, types don't appear in object files; only variables and functions do.

Furthermore, you're taking the view that:

  __attribute__((visibility ("hidden"))

on a type means something about visibility of the type in a linguistic
sense, i.e., that it provides some kind of scoping, perhaps like an
anonymous namespace that is different in each shared library.

But, the visibility attribute is only specified in terms of its effects
on ELF symbols, not as having C++ semantics per se.  The hidden
visibility attribute says that all members of the class have hidden
visibility, unless otherwise specified.

We also allow:

struct __attribute__((visibility("hidden"))) S {
  __attribute__((visibility("default"))) void f();
  void g();
};

which may seem equally odd: it says that you can call a function from
outside this translation unit even though you can't see the type.  But,
code like this is reasonable; it says that within the defining shared
object you can call all the functions, but that elsewhere you can call
"f" but not "g".  (That's orthogonal to C++ access specifiers; private
functions can have default visibility, and public ones can have hidden
visibility.)

The above class should be exactly the same as:

struct S {
  __attribute__((visibility("default"))) void f();
  __attribute__((visibility("hidden"))) void g();
};

since there is no virtual table or other class data.

As a motivating example for things like the original case I posted, this
is a technique for permitting users to provide member functions for
classes that you provide in a DLL.  If your DLL needs some
system-specific routines, one way to get them is to have the user
provide another DLL containing implementations of various functions in
the class hierarchy.  That can be more efficient at run-time than
passing in a separate callback object for the DLL to use, because it
avoids indirecting through the vtable of the callback object.

The bottom line is that you're taking the view that a construct with
well-defined semantics (namely, that the GNU visibility attribute map
directly to the ELF visibility without any further linguistic
implications) and which is easy to implement should be considered
invalid, despite conflicting with existing practice of other compilers
and large bodies of application code.

How does that serve our users?

Note: I'm not arguing about issuing a warning about this with "-W", if
people want to do that.  These mixtures of visibility are certainly not
the typical case.

-- 
Mark Mitchell
CodeSourcery
[EMAIL PROTECTED]
(650) 331-3385 x713

Reply via email to