On Jun 15, 2007, at 4:47 PM, Mark Mitchell wrote:
Chris Lattner wrote:
This construct seems like it should be rejected by the C++ front-end.
The source is making two contradictory claims: the struct is not
visible
outside this library, but part of it is implemented outside of it.
I don't think there's a contradiction. The declaration on the
structure
is the default for the members and applies to the vtable and other
class
data.
If we separate implementation details from the logical semantics, I
see that anonymous namespaces and hidden visibility, when applied to
a type, global impact the visibility of the type. If the *type* is
hidden, no members of that type, nor any other functions/methods that
take or refer to it, should be able to be dllimport.
In your example:
So, why not:
struct S __attribute__((visibility("hidden")) {
void f();
void g() __attribute__((dllimport));
};
void S::f() { S::g(); };
This may happen to work, but remember that there is an implicit
"this" pointer in "g". Regardless of whether "g" dereferences the
this pointer, it still takes one. I agree with Andrew that it is an
ODR violation, regardless of whether these cases happen to not get
caught in some cases. The this pointer in S::f and the this pointer
in S::g are two different types.
I'm not sure why you say that the code is broken. It works.
"working" and "making sense" are two different things :)
As far as I know it doesn't violate any specification.
Is there any formal spec at all that defines dllimport, hidden
visibility, and their interaction?
There's no reason the members shouldn't be implemented elsewhere,
and there's certainly existing code (in Windows, SymbianOS, and other
DLL-based operating systems, whether or not there is on GNU/Linux)
that
implements different class members in different DLLs, while still not
exporting the class from its home DLL. One situation where this is
useful is when the class members are actually shared between multiple
classes, or are also callable as C functions, etc.
IMO, regardless of whether this is accepted by other compilers, this
is a serious logical inconsistency and should be rejected by
default. For compatibility with other compilers, I agree that it
would be reasonable to add a compatibility flag to enable this more
lenient behavior.
-Chris