This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: RFC: Make dllimport/dllexport imply default visibility



On Jun 16, 2007, at 11:52 AM, Mark Mitchell wrote:


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.

That is a limited view of things based on the current implementation of GCC. When future developments (e.g. LTO) occur, this will change: types certainly do live in object files.


Even now, "types" can live in object files through debug info, RTTI, vtables, etc. Obviously there is a subset of cases where these don't apply and where the approach you propose can make sense.

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.

Yes.


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.

I'll paraphrase this as saying: "this is already an extension, not a standard - we can extend the extension without remorse".


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.

Because there is no standard to reference, I think it's important to consider these things in terms of explainability. It is very easy (and common) to explain visibility and anon namespaces in terms of types (when applied to a type).


I notice that your original patch did not include a documentation patch explaining the new semantics of the extension. I believe it would be very difficult to convey the proposed semantics to people who are not familiar with the Itanium ABI class layout and other related details of the G++ implementation. I suspect that the realview compiler accepts this as an oversight or a bug, not as an intentional feature.

For better or worse (usually worse), people's understanding of the language they code in is often defined by what their compiler happens to accept. Because this is an (one of many) il-documented extension, the *only* documentation is in what the compiler accepts.

How does that serve our users?

There are two conflicting goals to balance:


1. Define our extensions as well as possible and make their semantics as explainable and logical as possible.
2. Compile existing code with maximum compatibility.


To me, the best way to handle this is to reject this by default (based on #1). To handle #2, add a flag (defaulting to off) to enable this extended extension. In the diagnostic, tell the user about the option, and in the manual document the option and the issue.

I believe that rejecting this by default is important because people often define what is valid by what their compiler accepts, not what the standard says or what is logically consistent. :)

-Chris


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]