Re: [9fans] C compiler question
erik quanstrom wrote: assuming that pointers to incomplete types are themselves incomplete, and you haven't cited chapter and verse showing they are, i read that paragraph as saying that what plan 9 libraries do would be illegal, and therefore if we follow the standard, we'd need to remove Incomplete*s and replace them with void*s. if i'm wrong, can you explain how? The void type comprises an empty set of values; it is an incomplete type that cannot be completed. if a pointer to an incomplete type is incomplete, then void* is incomplete, too. as far as i can tell, the standard would allow an implementation where pointers vary in size and the sizes of pointers can't be determined at compile-time, but that would be insane.
Re: [9fans] C compiler question
On Tue, 14 Jul 2009 12:45:56 -0700 Russ Cox r...@swtch.com wrote: enough. there was a bug, plain and simple. struct T { struct S s; }; is not valid. never was, never will be. fix the compiler already. Newbie question: Does this statement apply to any struct S (meaning you can never have a struct as member of another struct), or does it only apply in cases where the structure of S is not known at that point? -- Ethan Grammatikidis Those who are slower at parsing information must necessarily be faster at problem-solving.
Re: [9fans] C compiler question
Newbie question: Does this statement apply to any struct S (meaning you can never have a struct as member of another struct), or does it only apply in cases where the structure of S is not known at that point? the latter. - erik
Re: [9fans] C compiler question
erik quanstrom wrote: Yes, but in my example - sorry - NeverDefined doesn't mean declared and defined elsewhere (or not) but not declared .and. not defined. true enough. the patch i sent still rejects your construct. i'd still be interested to hear a perspective of someone with more experience with the c compiler. - erik The point is how to compute the offset(s) of the last field at compile / run time. 8c should reject not defined (named only) types, as *nix compilers do. I think that it could be possible to allow the expansion of structs by a final struct field but this, in my opinion, would imply portability problems and in general more error prone code. I prefer to have only the tricky but standard char x[0] tails. Your patch will be included in the next distribution CD ? adriano
Re: [9fans] C compiler question
The point is how to compute the offset(s) of the last field at compile / run time. the offset of the last field is not in question. i believe you mean the size? 8c should reject not defined (named only) types, as *nix compilers do. yes. I prefer to have only the tricky but standard char x[0] tails. i'd prefer not to have them, either. but it's too late for that. Your patch will be included in the next distribution CD ? no. i haven't submitted it yet. - erik
Re: [9fans] C compiler question
erik quanstrom wrote: The point is how to compute the offset(s) of the last field at compile / run time. the offset of the last field is not in question. i believe you mean the size? It's really the same info. struct { . // total sizeof = 100 int B[..]; }A; offset(B) = 100, (A.B[7]) == address(A) + 100 + 7*sizeof(int). The compiler accept the dirty but legal expression A.B[-3] because it can compute the address (or the offset with respect the beginnig of A) of the B -3 cell. But in this case struct { . // total sizeof = 100 struct B B; }A; with B declared (just named), how 8c could determined the address of A.B.x ? To accept the above definition of A, say in a global .h, means that every .c should include the definition of B. They could be - legally - different, so generating different offsets of x with respect A in the same program. I prefer to have only the tricky but standard char x[0] tails. i'd prefer not to have them, either. but it's too late for that. :-) And what about char x[...] and x[2] == 2[x]:-) :-) Your patch will be included in the next distribution CD ? no. i haven't submitted it yet. - erik adriano
Re: [9fans] C compiler question
erik quanstrom wrote: The point is how to compute the offset(s) of the last field at compile / run time. the offset of the last field is not in question. i believe you mean the size? It's really the same info. it is not. the size and offset are different things. offset(B) = 100, (A.B[7]) == address(A) + 100 + 7*sizeof(int). The compiler accept the dirty but legal expression A.B[-3] because it can compute the address (or the offset with respect the beginnig of A) of the B -3 cell. this is completely beside the point and furthermore the sizeof A.B never enters into the picture. - erik
Re: [9fans] C compiler question
On Mon, 2009-07-13 at 23:14 -0400, erik quanstrom wrote: Yes, but in my example - sorry - NeverDefined doesn't mean declared and defined elsewhere (or not) but not declared .and. not defined. true enough. the patch i sent still rejects your construct. i'd still be interested to hear a perspective of someone with more experience with the c compiler. rejecting the struct seems like the right thing to do as per ISO/IEC 9899:1999 (http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf) sec. 6.7.2.1 para. 2 A structure or union shall not contain a member with incomplete or function type (hence, a structure shall not contain an instance of itself, but may contain a pointer to an instance of itself), except that the last member of a structure with more than one named member may have incomplete array type; such a structure (and any union containing, possibly recursively, a member that is such a structure) shall not be a member of a structure or an element of an array. Thanks, Roman.
Re: [9fans] C compiler question
rejecting the struct seems like the right thing to do as per ISO/IEC 9899:1999 (http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf) sec. 6.7.2.1 para. 2 A structure or union shall not contain a member with incomplete or function type (hence, a structure shall not contain an instance of itself, but may contain a pointer to an instance of itself), except that the last member of a structure with more than one named member may have incomplete array type; such a structure (and any union containing, possibly recursively, a member that is such a structure) shall not be a member of a structure or an element of an array. you're implying that the point of the plan 9 compilers is to toe the c99 line. also, a pointer to an incomplete type is used in many places in plan 9 libraries. - erik
Re: [9fans] C compiler question
On Tue, 2009-07-14 at 13:46 -0400, erik quanstrom wrote: rejecting the struct seems like the right thing to do as per ISO/IEC 9899:1999 (http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf) sec. 6.7.2.1 para. 2 A structure or union shall not contain a member with incomplete or function type (hence, a structure shall not contain an instance of itself, but may contain a pointer to an instance of itself), except that the last member of a structure with more than one named member may have incomplete array type; such a structure (and any union containing, possibly recursively, a member that is such a structure) shall not be a member of a structure or an element of an array. you're implying that the point of the plan 9 compilers is to toe the c99 line. For the dirty corner of any language one is usually better off with a written formal standard. Now, since Plan9 doesn't have such a document, relying on a work done by c99 committee would seem like a wise thing to do. And it is not like we are talking about C++ ISO standard here, the C99 is actually quite beautiful (except may be a couple of places like compound literals, and stuff). What's your problem with such an approach? also, a pointer to an incomplete type is used in many places in plan 9 libraries. The above paragraph has nothing to do with pointers to incomplete types (except for a clarification). Why are you bringing this up? Thanks, Roman.
Re: [9fans] C compiler question
For the dirty corner of any language one is usually better off with a written formal standard. Now, since Plan9 doesn't have such a document, relying on a work done by c99 committee would seem like a wise thing to do. And it is not like we are talking about C++ ISO standard here, the C99 is actually quite beautiful (except may be a couple of places like compound literals, and stuff). What's your problem with such an approach? only the part where i abdicate my ability to think to a committee. i'm difficult that way. also, a pointer to an incomplete type is used in many places in plan 9 libraries. The above paragraph has nothing to do with pointers to incomplete types (except for a clarification). Why are you bringing this up? assuming that pointers to incomplete types are themselves incomplete, and you haven't cited chapter and verse showing they are, i read that paragraph as saying that what plan 9 libraries do would be illegal, and therefore if we follow the standard, we'd need to remove Incomplete*s and replace them with void*s. if i'm wrong, can you explain how? - erik
Re: [9fans] C compiler question
enough. there was a bug, plain and simple. struct T { struct S s; }; is not valid. never was, never will be. fix the compiler already. russ
Re: [9fans] C compiler question
erik quanstrom wrote: 8c silently accept the above definition and sizeof(U) is 100. ??? The sources which include the definition of NeverDefined are regularly compiled too and sizeof(U) = 100 + sizeof(NeverDefined). i think the issue is that there isn't currently a distinction between this typedef struct A A; struct A { int expand[0]; }; which is perfectly legal and this typedef struct U U; typedef struct A A; struct A { U; }; Yes, but in my example - sorry - NeverDefined doesn't mean declared and defined elsewhere (or not) but not declared .and. not defined. No doubt this should be a fatal error, but 8c accepts. What's my mistake ? adriano
Re: [9fans] C compiler question
Yes, but in my example - sorry - NeverDefined doesn't mean declared and defined elsewhere (or not) but not declared .and. not defined. true enough. the patch i sent still rejects your construct. i'd still be interested to hear a perspective of someone with more experience with the c compiler. - erik
Re: [9fans] C compiler question
Yes, but in my example - sorry - NeverDefined doesn't mean declared and defined elsewhere (or not) but not declared .and. not defined. no and yes. union U { struct { struct NeverDefined nf; // Unknown, definition not #included } S1 }; declares a struct named NeverDefined just by mentioning it. the compiler should reject the use because NeverDefined is not defined. it's just a bug. i don't have a copy of the compiler to play with but erik's patch seems fine. russ
Re: [9fans] C compiler question
8c silently accept the above definition and sizeof(U) is 100. ??? The sources which include the definition of NeverDefined are regularly compiled too and sizeof(U) = 100 + sizeof(NeverDefined). i think the issue is that there isn't currently a distinction between this typedef struct A A; struct A { int expand[0]; }; which is perfectly legal and this typedef struct U U; typedef struct A A; struct A { U; }; which might be allowed, but i can't find any references that say it is. the argument for having expandable structures would be it would allow something like this typedef struct Priv Priv; typedef struct Pub Pub; struct Pub { ... Priv; }; #pragma incomplete Pub Pub *pubfn(void); but i don't see any such uses in /sys/include. this change will generate a diagnostic for your code, but be careful. this is a corner of c, and what seems intuitively correct in the corners can often be wrong. - erik ; diff -c dcl.c `{yesterday -n2 dcl.c} dcl.c:541,547 - /n/dump/2009/0710/sys/src/cmd/cc/dcl.c:541,547 l-offset = o; } else { if(l-width = 0) - if(l-down != T || l-width 0) + if(l-down != T) if(l-sym) diag(Z, incomplete structure element: %s, l-sym-name);