Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!usc!apple!olivea!mintaka!bloom-picayune.mit.edu!news From: scs@adam.mit.edu (Steve Summit) Newsgroups: comp.std.c Subject: Re: Pointers to Incomplete Types in Prototypes Message-ID: <1991May10.021509.9862@athena.mit.edu> Date: 10 May 91 02:15:09 GMT References: <1991May7.043654.4795@tkou02.enet.dec.com> <1991May8.043353.28983@athena.mit.edu> <1991May8.072112.20866@tkou02.enet.dec.com> Sender: news@athena.mit.edu (News system) Reply-To: scs@adam.mit.edu Organization: Thermal Technologies, Cambridge, MA Lines: 130 In article <1991May8.072112.20866@tkou02.enet.dec.com> diamond@jit533.enet@tkou02.enet.dec.com (Norman Diamond) writes: >In article <1991May8.043353.28983@athena.mit.edu> scs@adam.mit.edu writes: >>...there is no meaningful distinction [between struct type >>"declarations" and "definitions]." >>...a struct declaration, with or without a tag and with or >>without a struct-declaration-list, only enters identifier and >>type information into symbol tables. > >And scope and storage class information. If definitions were distinguished >from declarations, then the difference would be that declarations don't >enter type information into the table, and the scope issue might be cloudy. Structure type definitions/declarations don't have a storage class. "Scope information," to my view, is the implicit property of which (nested) symbol table a given symbol is declared/defined in, which is of course the whole issue here. >>There's nothing wrong here. In the absence of any previous >>mention of a struct bar, >> type foo(struct bar *arg); >>is as much of a struct "definition" as is >> type foo(struct bar { ... } *arg); > >No. The standard says that the presence of "{ ... }" declares the a type. Well, I hope this doesn't sound like overly-persnickety verbal nitpicking, but the standard also says things like "A string literal is a primary expression." I don't conclude that the presence of "{...}" is necessarily the only way of declaring a new type. >No part of the standard says that "struct bar *" declares a new type. >"struct bar *" must be a reference. > >Now: The standard allows forward references for structure tags that >haven't been declared/[defined] yet. It also allows references to structure >tags that are declared in outer scopes. It does not explicitly say that a >single reference may take advantage of both of these features simultaneously. >But I think it must be allowed. There is still no other meaning. I sort of agree, to the extent that neither analysis can be conclusively disproved. To make things clear for everybody, consider struct a *aptr; struct a {int a;}; struct b *bptr; { struct b {int b;}; } { struct c *cptr; } struct c {int c;}; The declaration of aptr is clearly legal; the following line completes the incomplete struct a type. Section 3.5.2.3 discusses this case. The incomplete struct b type with which bptr is declared is clearly not completed two lines down. This, too, is explicitly stated in section 3.5.2.3 . (The wording here talks about "defining the content," so it was not quite correct of me to suggest that the standard makes no distinction between "declaring" and "defining" structures. I'm still not convinced it's a formal distinction, however.) The sticky case is the third one. I don't think that a struct type can be completed in an outer scope, but the standard doesn't explicitly say that it can't. Nor does it say that it can. >>If mentioning >> struct bar * >>didn't suffice to "define" a struct bar (assuming it wasn't already "defined"), > >You betcha! It doesn't! RTFS. > >>then the one-line translation unit >> struct bar *bp; >>would have to give some kind of an error, much like the "warning: >>struct bar never defined" which lint issues under the -h option. > >I think this might be true. (Sorry, I'm not in the mood to look it up >at the moment.) Well, I was, and I did, and from (still in section 3.5.2.3): If a type specifier of the form struct-or-union identifier occurs prior to the declaration that defines the content, the structure or union is an incomplete type. It declares a tag that specifies a type that may be used only when the size of an object of the specified type is not needed. If the type is to be completed, another declaration of the tag *in the same scope* ... shall define the content [emphasis mine]. I concluded that the incomplete declaration, when not followed by another declaration of the tag in the same scope, was sufficient to declare a type, as long as that type's size was not needed. That's why I think that the one-line translation unit struct bar *bp; is conforming, and need elicit no diagnostic. Since section 3.5.2.3 specifically mentions that a later declaration in the same scope can complete a struct type (and the same point is made in the paragraph on incomplete types in section 3.1.2.5), I am led to believe that it was not the intention that a declaration in an outer scope be able to do so. I admit that there may be some ambiguity here. I had realized that an interpretation like Norm's was possible while composing my first reply, and almost mentioned it. (I hadn't realized until now that Norm was advancing this interpretation as the way out of the dissatisfaction.) To repeat, though, I think that both interpretations are viable in that neither is explicitly ruled out. I leaned the way I did (inner-scope incomplete struct types aren't completed in outer scopes) because of the "in the same scope" language, and because I think that's the way compilers have tended to do it. (The ones I've written have, anyway, but I just checked pcc and it seems to, too.) Steve Summit scs@adam.mit.edu