Defect Report #165
Submission Date: 16 Oct 95
Submittor: BSI
Source: Clive D.W. Feather
Question
Submitted to BSI by Clive D.W. Feather [email protected] .
In this Defect Report, identifiers lexically identical to those
declared in standard headers refer to the identifiers declared in those
standard headers, whether or not the header is explicitly mentioned.
This Defect Report has been prepared with considerable help from
Mark Brader, Jutta Degener, Ronald Guilmette, and a person whose
employment conditions require anonymity. However, except where stated,
opinions expressed or implied should not be assumed to be those of any
person other than myself.
Defect Report UK 013: Tags and incomplete types
The wording of subclause 6.5.2.3 concerning tags is defective in a number of ways.
Part 1
The first paragraph states that:
If this declaration of the tag is visible, a subsequent declaration that uses the tag and that
omits the bracketed list specifies the declared structure, union, or enumerated type.
This neither handles the case of a type name (for example, in the
operand of the sizeof operator), nor does it make it
clear whether or not the rule applies within the braces of the first
declaration (the tag is in scope from the open brace).
In other words, it fails to address either occurrence of struct tag * in the
following code:
{
struct tag { int i [sizeof (struct tag *)]; };
int j [sizeof (struct tag *)];
/* ... */
}
Part 2
The second paragraph does not adequately distinguish between type
specifiers which refer to an incomplete type and those which refer to a
type in an outer scope. For example, in the following code, it fails to
indicate whether or not all the uses of the tag refer to the same type:
struct tag;
struct tag *p;
{
struct
tag *q;
/* ... */
}
struct tag { int
member; };
Part 3
The handling of enumerated types before their content is defined
is also unclear; this was covered to some extent in DR013Q5 and subsequent discussion on the WG14 mailing list.
For example, what is the status of the following code:
enum tag { e = sizeof (enum tag ******) };
or of:
enum tag { e0, e1, e2, e3 };
{
enum tag2
{ e4 = sizeof (enum tag); };
enum tag { e5 = sizeof (enum
tag); };
}
If an enumeration tag cannot be used before the end of the list
defining its contents, a diagnostic ought to be required.
Part 4
If the same tag is used in a type specifier with a contents list
twice in the same scope, it is unclear whether or not a diagnostic is
required. It could be argued that, since this is forbidden by the
semantics in subclause 6.5.2.3, it is not excluded from the second
constraint of subclause 6.5, and so a diagnostic is required by that
constraint. However, this may be viewed as clutching at straws. An
explicit constraint should be added.
Suggested Technical Corrigendum
Rather than making piecemeal changes to address each issue
separately, the whole subclause should be rewritten. Footnote numbers
have been chosen to match the present footnotes.
Constraints
A specific type shall have its content defined at most once.
A type specifier of the form
enum identifier
without an enumerator list shall only appear when the type it
specifies is complete.
Semantics
All declarations of structure, union, or enumerated types that
have the same scope and use the same tag declare the same type. The
type is incomplete [63] until the closing brace of the list defining
the content, and complete thereafter. [Footnote 63: An incomplete type
may only be used when the size of an object of that type is not
needed.]
[Append the present wording, or see Defect Report CA-2-09 -
submitted independently - for alternative wording.]
Two declarations of structure, union, or enumerated types which
are in different scopes or use different tags declare distinct types.
Each declaration of a structure, union, or enumerated type which does
not include a tag declares a distinct type.
A type specifier of the form
struct-or-union identifier { struct-declaration-list }
opt or
enum identifier { enumerator-list }
opt
declares a structure, union, or enumerated type. The list
defines the structure content, union content, or enumeration
content. If an identifier is provided [64], the type specifier also
declares the identifier to be the tag of that type. [Footnote 64: If
there is no identifier, the type can, within the translation unit, only
be referred to by the declaration of which it is a part. Of course,
when the declaration is of a typedef name, subsequent declarations can
make use of that typedef name to declare objects having the specified
structure, union, or enumerated type.]
A declaration of the form
struct-or-union identifier ;
specifies a structure or union type and declares the
identifier as the tag of that type [62]. [Footnote 62: A similar
construction with enum does not exist.]
If a type specifier of the form
struct-or-union identifier
occurs other than as part of one of the above constructions,
and no other declaration of the identifier as a tag is visible, then it
declares a structure or union type which is incomplete at this point,
and declares the identifer as the tag of that type [62].
If a type specifier of the form
struct-or-union identifier
or
enum identifier
occurs other than as part of one of the above constructions,
and a declaration of the identifier as a tag is visible, then it
specifies the same type as that other declaration, and does not
redeclare the tag.
Previous Defect Report
< - >
Next Defect Report