[comp.std.c] Definition With Incomplete Type Should Be An Error

blodgett@apollo.HP.COM (Bruce Blodgett) (03/28/91)

Are my comments about the following program correct?  I feel that that
the declarations of s1 and a2 should ideally require a diagnostic.

static int s1[]; /* Violates a "shall" requirement: */
/*
External Object Definitions 3.7.2 p 84 l 29:  A declaration of an
identifier for an object that has file scope without an initializer,
and ... with the storage-class specifier static, constitutes a
tentative definition.

The declaration of array s1 is a tentative definition.

Linkages of Identifiers 3.1.2.2 p 22 l 14:  If the declaration of a
file scope identifier for an object ... contains the storage-class
specifier static, the identifier has internal linkage.

s1 has internal linkage.

Array Declarators 3.5.4.2 p 68 l 9:  If the size is not present, the
array type is an incomplete type.

Array s1 has incomplete type.

External Object Definitions 3.7.2 p 84 l 35:  If the declaration of
an identifier for an object is a tentative definition and has internal
linkage, the declared type shall not be an incomplete type.

Definitions of Terms 1.6 p 3 l 42:  If a "shall" ... requirement that
appears outside of a constraint is violated, the behavior is
undefined.

Regardless of whether the compilation unit contains any further
references to array s1, this produces undefined behavior.
*/

extern void main(void)
{
    auto int a2[]; /* Undefined behavior? */
/*
Array Declarators 3.5.4.2 p 68 l 9:  If the size is not present, the
array type is an incomplete type.

Array a2 has incomplete type.

Linkages of Identifiers 3.1.2.2 p 22 l 24:  The following
identifiers have no linkage: ...; a block scope identifier for an
object declared without the storage-class specifier extern.

Array a2 has no linkage.

Declarations 3.5 p 58 l 17:  If an identifier has no linkage, there
shall be no more than one declaration of the identifier (in a
declarator or type specifier) with the same scope and in the same name
space....

There shall be no more declarations of array a2 in this scope.  So the
type of array a2 cannot be completed.  So the amount of storage to be
reserved for array a2 cannot be determined.  This is exactly the
reason that the declaration of array s1 violates a "shall" requirement
above.

Regardless of whether the compilation unit contains any further
references to array a2, this declaration should cause the same
severity of diagnostic as the declaration of array s1 above.
*/
}
Bruce Blodgett
blodgett@apollo.hp.com
(508) 256-0176 x4037

karl@ima.isc.com (Karl Heuer) (03/28/91)

In article <509f2397.20b6d@apollo.HP.COM> blodgett@apollo.HP.COM (Bruce Blodgett) writes:
>Are my comments about the following program correct?  I feel that that
>the declarations of s1 and a2 should ideally require a diagnostic.

When you cross-post an article like this, you should include a warning that
you're doing so.  My comments apply to ANSI C, not C++.

>static int s1[]; /* Violates a "shall" requirement: */

Last time this came up, the conclusion was that, yes, this is illegal.
Personally, I think the Standard should have said that this is a declaration
rather than a tentative definition, and so it would only produce an error if
no actual definition is encountered.  (It would also have been nice if Dennis
had used keywords to distinguish declarations from definitions in the first
place, so we wouldn't need this tentative-definition kludge.  But there's no
point in dwelling on that.)

>extern void main(void) {
>    auto int a2[]; /* Undefined behavior? */
>}

Sounds right to me.  You've also misdeclared |main|, though; the Standard says
its return type is |int|, not |void|.

Karl W. Z. Heuer (karl@ima.isc.com or uunet!ima!karl), The Walking Lint

diamond@jit345.swstokyo.dec.com (Norman Diamond) (03/29/91)

In article <509f2397.20b6d@apollo.HP.COM> blodgett@apollo.HP.COM (Bruce Blodgett) writes:

>Are my comments about the following program correct?  I feel that that
>the declarations of s1 and a2 should ideally require a diagnostic.

Both of them violate "shall" assertions in SEMANTICS sections.
Neither of them violates any assertion in CONSTRAINTS sections.
Therefore they both yield undefined behavior, and neither of them
requires a diagnostic.  (Though high-quality processors would produce
diagnostics for both.)

>static int s1[]; /* Violates a "shall" requirement: */
>External Object Definitions 3.7.2 p 84 l 29: ...
>The declaration of array s1 is a tentative definition.
>Linkages of Identifiers 3.1.2.2 p 22 l 14: ...
>s1 has internal linkage.
>Array Declarators 3.5.4.2 p 68 l 9: ...
>Array s1 has incomplete type.
>External Object Definitions 3.7.2 p 84 l 35: ...
>Definitions of Terms 1.6 p 3 l 42:  If a "shall" ... requirement that
>appears outside of a constraint is violated, the behavior is
>undefined.

Yes.

>extern void main(void)
Let's correct this to extern int main(void) and continue.
>{ auto int a2[]; /* Undefined behavior? */
>Array Declarators 3.5.4.2 p 68 l 9: ...
>Array a2 has incomplete type.
>Linkages of Identifiers 3.1.2.2 p 22 l 24: ...
>Array a2 has no linkage.

Yes, and let's continue.

>Declarations 3.5 p 58 l 17: ...
>There shall be no more declarations of array a2 in this scope.

That paragraph has no bearing on this example.  However, this one does --
Declarations 3.5 p 58 l 30:
If an identifier for an object is declared with no linkage, the type for the
object shall be complete by the end of its declarator, or by the end of its
init-declarator if it has an initializer.

--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.