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