9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] C compiler question
@ 2009-07-12  3:59 Adriano Verardo
  2009-07-12 16:59 ` erik quanstrom
  0 siblings, 1 reply; 18+ messages in thread
From: Adriano Verardo @ 2009-07-12  3:59 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

Hi, all.

Yesterday I observed different sizeof() of a union in a library function
and in the main program. The reason seems to be a forgotten #include
in a library source.

union U
{
    struct
    {
          <fields of defined types>            //  sizeof = 100
          struct NeverDefined  nf;              //  Unknown, definition
not #included
    } S1

    struct
    {
          <fields of defined types>            //  sizeof = 20
    } S2
};

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).

This happens only if the undefined field is the last of the structure.
If it is followed by other (defined or not defined) field(s), the compiler
correctly detects the error.

Is this behaviour correct ?

Thanks in advance.

a.verardo







^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [9fans] C compiler question
  2009-07-12  3:59 [9fans] C compiler question Adriano Verardo
@ 2009-07-12 16:59 ` erik quanstrom
  2009-07-14  2:58   ` Adriano Verardo
  0 siblings, 1 reply; 18+ messages in thread
From: erik quanstrom @ 2009-07-12 16:59 UTC (permalink / raw)
  To: 9fans

> 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);



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [9fans] C compiler question
  2009-07-12 16:59 ` erik quanstrom
@ 2009-07-14  2:58   ` Adriano Verardo
  2009-07-14  3:14     ` erik quanstrom
  2009-07-14  4:00     ` Russ Cox
  0 siblings, 2 replies; 18+ messages in thread
From: Adriano Verardo @ 2009-07-14  2:58 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

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



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [9fans] C compiler question
  2009-07-14  2:58   ` Adriano Verardo
@ 2009-07-14  3:14     ` erik quanstrom
  2009-07-14 14:00       ` Adriano Verardo
  2009-07-14 17:18       ` Roman V Shaposhnik
  2009-07-14  4:00     ` Russ Cox
  1 sibling, 2 replies; 18+ messages in thread
From: erik quanstrom @ 2009-07-14  3:14 UTC (permalink / raw)
  To: 9fans

> 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



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [9fans] C compiler question
  2009-07-14  2:58   ` Adriano Verardo
  2009-07-14  3:14     ` erik quanstrom
@ 2009-07-14  4:00     ` Russ Cox
  1 sibling, 0 replies; 18+ messages in thread
From: Russ Cox @ 2009-07-14  4:00 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

> 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


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [9fans] C compiler question
  2009-07-14  3:14     ` erik quanstrom
@ 2009-07-14 14:00       ` Adriano Verardo
  2009-07-14 14:57         ` erik quanstrom
  2009-07-14 17:18       ` Roman V Shaposhnik
  1 sibling, 1 reply; 18+ messages in thread
From: Adriano Verardo @ 2009-07-14 14:00 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

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



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [9fans] C compiler question
  2009-07-14 14:00       ` Adriano Verardo
@ 2009-07-14 14:57         ` erik quanstrom
  2009-07-14 16:26           ` Adriano Verardo
  0 siblings, 1 reply; 18+ messages in thread
From: erik quanstrom @ 2009-07-14 14:57 UTC (permalink / raw)
  To: 9fans

> 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



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [9fans] C compiler question
  2009-07-14 14:57         ` erik quanstrom
@ 2009-07-14 16:26           ` Adriano Verardo
  2009-07-14 16:38             ` erik quanstrom
  0 siblings, 1 reply; 18+ messages in thread
From: Adriano Verardo @ 2009-07-14 16:26 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

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





^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [9fans] C compiler question
  2009-07-14 16:26           ` Adriano Verardo
@ 2009-07-14 16:38             ` erik quanstrom
  0 siblings, 0 replies; 18+ messages in thread
From: erik quanstrom @ 2009-07-14 16:38 UTC (permalink / raw)
  To: a.verardo, 9fans

> 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



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [9fans] C compiler question
  2009-07-14  3:14     ` erik quanstrom
  2009-07-14 14:00       ` Adriano Verardo
@ 2009-07-14 17:18       ` Roman V Shaposhnik
  2009-07-14 17:46         ` erik quanstrom
  1 sibling, 1 reply; 18+ messages in thread
From: Roman V Shaposhnik @ 2009-07-14 17:18 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

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.




^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [9fans] C compiler question
  2009-07-14 17:18       ` Roman V Shaposhnik
@ 2009-07-14 17:46         ` erik quanstrom
  2009-07-14 18:59           ` Roman V Shaposhnik
  0 siblings, 1 reply; 18+ messages in thread
From: erik quanstrom @ 2009-07-14 17:46 UTC (permalink / raw)
  To: 9fans

> 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



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [9fans] C compiler question
  2009-07-14 17:46         ` erik quanstrom
@ 2009-07-14 18:59           ` Roman V Shaposhnik
  2009-07-14 19:29             ` erik quanstrom
  0 siblings, 1 reply; 18+ messages in thread
From: Roman V Shaposhnik @ 2009-07-14 18:59 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

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.




^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [9fans] C compiler question
  2009-07-14 18:59           ` Roman V Shaposhnik
@ 2009-07-14 19:29             ` erik quanstrom
  2009-07-14 19:45               ` Russ Cox
                                 ` (2 more replies)
  0 siblings, 3 replies; 18+ messages in thread
From: erik quanstrom @ 2009-07-14 19:29 UTC (permalink / raw)
  To: 9fans

> 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



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [9fans] C compiler question
  2009-07-14 19:29             ` erik quanstrom
@ 2009-07-14 19:45               ` Russ Cox
  2009-07-15 11:34                 ` Ethan Grammatikidis
  2009-07-14 20:28               ` [9fans] pointers to incomplete types Roman V Shaposhnik
  2009-07-15  9:25               ` [9fans] C compiler question robert wilson
  2 siblings, 1 reply; 18+ messages in thread
From: Russ Cox @ 2009-07-14 19:45 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

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


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [9fans] pointers to incomplete types
  2009-07-14 19:29             ` erik quanstrom
  2009-07-14 19:45               ` Russ Cox
@ 2009-07-14 20:28               ` Roman V Shaposhnik
  2009-07-15  9:25               ` [9fans] C compiler question robert wilson
  2 siblings, 0 replies; 18+ messages in thread
From: Roman V Shaposhnik @ 2009-07-14 20:28 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

On Tue, 2009-07-14 at 15:29 -0400, erik quanstrom wrote:
> > 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?

The pointer to the incomplete type is a "pointer type",
not an incomplete type. It is part of the section
describing tye type system of C99 (section 6.2.5).

Look for "derived types".

Thanks,
Roman.




^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [9fans] C compiler question
  2009-07-14 19:29             ` erik quanstrom
  2009-07-14 19:45               ` Russ Cox
  2009-07-14 20:28               ` [9fans] pointers to incomplete types Roman V Shaposhnik
@ 2009-07-15  9:25               ` robert wilson
  2 siblings, 0 replies; 18+ messages in thread
From: robert wilson @ 2009-07-15  9:25 UTC (permalink / raw)
  To: 9fans

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.



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [9fans] C compiler question
  2009-07-14 19:45               ` Russ Cox
@ 2009-07-15 11:34                 ` Ethan Grammatikidis
  2009-07-15 11:38                   ` erik quanstrom
  0 siblings, 1 reply; 18+ messages in thread
From: Ethan Grammatikidis @ 2009-07-15 11:34 UTC (permalink / raw)
  To: 9fans

On Tue, 14 Jul 2009 12:45:56 -0700
Russ Cox <rsc@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.



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [9fans] C compiler question
  2009-07-15 11:34                 ` Ethan Grammatikidis
@ 2009-07-15 11:38                   ` erik quanstrom
  0 siblings, 0 replies; 18+ messages in thread
From: erik quanstrom @ 2009-07-15 11:38 UTC (permalink / raw)
  To: 9fans

> 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



^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2009-07-15 11:38 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-07-12  3:59 [9fans] C compiler question Adriano Verardo
2009-07-12 16:59 ` erik quanstrom
2009-07-14  2:58   ` Adriano Verardo
2009-07-14  3:14     ` erik quanstrom
2009-07-14 14:00       ` Adriano Verardo
2009-07-14 14:57         ` erik quanstrom
2009-07-14 16:26           ` Adriano Verardo
2009-07-14 16:38             ` erik quanstrom
2009-07-14 17:18       ` Roman V Shaposhnik
2009-07-14 17:46         ` erik quanstrom
2009-07-14 18:59           ` Roman V Shaposhnik
2009-07-14 19:29             ` erik quanstrom
2009-07-14 19:45               ` Russ Cox
2009-07-15 11:34                 ` Ethan Grammatikidis
2009-07-15 11:38                   ` erik quanstrom
2009-07-14 20:28               ` [9fans] pointers to incomplete types Roman V Shaposhnik
2009-07-15  9:25               ` [9fans] C compiler question robert wilson
2009-07-14  4:00     ` Russ Cox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).