Defect Report #011

Submission Date: 10 Dec 92
Submittor: WG14
Source: X3J11/90-008 (Rich Peterson)
Question 1
Merging of declarations for linked identifier
When more than one declaration is present in a program for an externally-linked identifier, exactly when do the declared types get formed into a composite type?
Certainly, if two declarations have file scope, then after the second, the effective type for semantic analysis is the composite type of the two declarations (subclause 6.1.2.6, page 25, lines 19-20). However, if one declaration is in an inner scope and one is in an outer scope, are their types formed into a composite type?
In particular, consider the code:
{
extern int i[];
{
/*
a different declaration of the same object */
extern int i[10];
}
/*
Is the following legal?
That is, does the outer declaration
inherit any information from the inner one?
*/
sizeof (i);
}

Similar situations can be constructed with internally linked identifiers. For instance:
/* File scope */
static int i[];

main()
{
/*
a different declaration of the same object */
extern int i[10];
}

/*
Is the following legal?
That is, does the outer declaration
inherit any information from the inner one?
*/
int j = sizeof (i);

Further variants of this question can be asked:
{
extern int i[10];
{
/*
a different declaration of the same object */
extern int i[];

/*
Is the following legal?
That is, does the inner declaration
inherit any information from the outer one?
*/
sizeof (i);
}
}

Correction
In subclause 6.1.2.6, page 25, lines 19-20, change:
For an identifier with external or internal linkage declared in the same scope as another declaration for that identifier, the type of the identifier becomes the composite type.
to:
For an identifier with internal or external linkage declared in a scope in which a prior declaration of that identifier is visible*, if the prior declaration specifies internal or external linkage, the type of the identifier at the latter declaration becomes the composite type.
[Footnote *: As specified in 6.1.2.1, the latter declaration might hide the prior declaration.]
Question 2
Interpretation of extern
Consider the code:
/* File scope */
static int i; /*
declaration 1 */

main()
{
extern int i; /*
declaration 2 */
{
extern int i; /*
declaration 3 */
}
}

A literal reading of subclause 6.1.2.2 says that declarations 1 and 2 have internal linkage, but that declaration 3 has external linkage (since declaration 1 is not visible, being hidden by declaration 2). (This combination of internal and external linkage is undefined by subclause 6.1.2.2, page 21, lines 27-28.)
Is this what is intended?
Correction
In subclause 6.1.2.2, page 21, change:
If the declaration of an identifier for an object or a function contains the storage-class specifier extern, the identifier has the same linkage as any visible declaration of the identifier with file scope. If there is no visible declaration with file scope, the identifier has external linkage.
to:
For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible*, if the prior declaration specifies internal or external linkage, the linkage of the identifier at the latter declaration becomes the linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage. [Footnote *: As specified in 6.1.2.1, the latter declaration might hide the prior declaration.]
Question 3
Initialization of tentative definitions
If the file scope declaration
int i[10];
appears in a translation unit, subclause 6.7.2 suggests that it is implicitly initialized as if
int i[10] = 0;
appears at the end of the translation unit. However, this initializer is invalid, since subclause 6.5.7 prescribes that the initializer for any object of array type must be brace-enclosed. We believe that the intention of subclause 6.7.2 is that this declaration has an implicit initializer of
int i[10] = {0};
Is this true?
Response
Subclause 6.7.2 External object definitions contains the following excerpt:
If a translation unit contains one or more tentative definitions for an identifier, and the translation unit contains no external definition for that identifier, then the behavior is exactly as if the translation unit contains a file scope declaration of that identifier, with the composite type as of the end of the translation unit, with an initializer equal to 0.
This statement describes an effect and not a literal token sequence. Therefore, this example does not contain an error.
Question 4
Tentative definition of externally-linked object with incomplete type
If one writes the file-scope declaration
int i[];
then subclause 6.7.2 suggests that at the end of the translation unit the implicit declaration
int i[] = {0};
or equivalently
int i[1] = {0};
appears. This seems peculiar, since subclause 6.7.2, (page 83, lines 35-36) specifically forbids this case for internally linked identifiers.
Is this what is intended?
Correction
Add to subclause 6.7.2, page 84, a second Example:
If at the end of the translation unit containing
int i[];
the array i still has incomplete type, the array is assumed to have one element. This element is initialized to zero on program startup.
Previous Defect Report < - > Next Defect Report