On 01/20/2013 08:02 PM, Russell Shaw wrote:
> On 21/01/13 01:08, Eric Sosman wrote:
>> On 1/19/2013 8:46 PM, Russell Shaw wrote:
>>> [... two "identical" struct types are incompatible ...]
>>>
>>> The problem is that if you #include the declaration of an anonymous
>>> struct sa from a separate translation unit, then the compiler complains
>>> about sb = sa.
>>
>> I don't understand this. A "translation unit" is all of
>> the source the compiler sees at one time: The original source
>> file, all the files and headers it #includes, all the files and
>> headers they in turn #include, all macros defined on compiler
>> command lines or whatever, ... If you #include a declaration,
>> that declaration is part of *the* translation unit; it is not
>> an interloper from "a separate translation unit."
>
> Precisely. Because of that problem, i could not see how declarations from
> separate translation units should be compatible, when including a header with
> the second declaration now becomes a part of the first translation unit anyway,
> thus making the point mute.
I'm not sure I understand your objection. #include is a red herring
here; all that matters is what the translation units contain after all
#include directives have been processed. Therefore, I'll give an example
involving no shared header files (which would, in general, be a bad
coding practice - but then, IMO, so is the use of unnamed struct types).
file declared.c:
extern struct {unsigned u:4; _Alignas(long long) double d;} a, b;
file defined.c:
struct {unsigned u:4; _Alignas(_Alignof(long long)) double d;} a, b;
In each file, 'a' is compatible with 'b', despite the fact that they
both have an anonymous struct type, because the same anonymous struct
definition was used to declare both objects.
The one definition rule requires that the external declarations in
declared.c be compatible with the definitions in defined.c, and they
are, but for a different reason: the definitions of the
struct types in the two different translation units meet all of the
requirements of 6.2.7p1:
"If one is declared with a tag, the other shall be declared with the
same tag." - neither one is declared with a tag.
"If both are completed anywhere within their respective translation
units, then the following additional requirements apply: there shall
be a one-to-one correspondence between their members such that each pair
of corresponding members are declared with compatible types; ..." -
There is such a correspondence - the types of the corresponding members
are not merely compatible, but identical.
"... if one member of the pair is declared with an alignment specifier,
the other is declared with an equivalent alignment specifier; ..."
- 'd' is declared with equivalent alignment specifiers in both struct
definitions.
"... and if one member of the pair is declared with a name, the other is
declared with the same name. ..." - for every pair, the names are in
fact the same.
"For two structures, corresponding members shall be declared in the same
order." - they are declared in the same order.
"For two structures or unions, corresponding bit-fields shall have the
same widths." - 'u' has the same width in both structure definitions.
The key point is that these requirements only render compatible struct
definitions that appear in different translation units. Therefore, even
though the following line define struct types that also meet all of
those requirements, because they occur in the same translation unit,
they define incompatible struct types:
struct {unsigned u:4; _Alignof(long long) double d;} a;
struct {unsigned u:4; _Alignof(long long) double d;} b;
This may seem counter-intuitive, but the reason for this difference is
that it was not considered necessary to extend this specification to
include struct types declared in the same translation unit. The standard
already provides three different ways to define structure objects in the
same translation unit to have compatible types: struct tags, typedefs,
or sharing the same anonymous struct definition, as in my example above.
None of those things would be sufficient to allow declarations of struct
types in different translation units to be compatible - it's only
6.2.7p1 that makes that possible.
Note: I don't agree with this decision; I don't see any advantage to
restricting the guarantee of compatibility to structs defined in
different translation units. However, that is what the standard specifies.
> I'll go with the interpretation as stated in this group, because it makes for
> less complication in the compiler, and is safer to use.
I'm not sure what you consider to be "the interpretation as stated in
this group". Is it compatible with what I've said above?
--
James Kuyper
--
James Kuyper