2004-01-06 21:06:23

by David Mosberger-Tang

[permalink] [raw]
Subject: Re: GCC 3.4 Heads-up

>>>>> On Fri, 26 Dec 2003 05:50:07 +0100, Linus Torvalds <[email protected]> said:
Linus> The cast/conditional expression as lvalue are _particularly_
Linus> ugly extensions, since there is absolutely zero point to
Linus> them.

I'd love to agree with that...

Linus> They are very much against what C is all about, and writing
Linus> something like this:

Linus> a ? b : c = d;

Linus> is something that only a high-level language person could
Linus> have come up with. The _real_ way to do this in C is to just
Linus> do

Linus> *(a ? &b : &c) = d;

Linus> which is portable C, does the same thing, and has no strange
Linus> semantics.

This works provided you can take the address of the lvalue, which
ain't true for bitfields. Example:

#define bit_field(var, bit, width) \
(((struct { long : bit; long _f : width; } *) &(var))->_f)

long l;

bit_field(l, 0, 4) = 13;
bit_field(l, 8, 12) = 42;

I wish I was making this up, but I know of at least one legacy app
where disabling GCC's ability to treat statement-expressions as
l-values will cause a major headache.

I'd love to know a way of doing this in ANSI C99 without requiring
changes to to uses of this kind of (atrocious) macro...

--david

--
David Mosberger; 35706 Runckel Lane; Fremont, CA 94536; [email protected]


2004-01-06 22:33:31

by Richard Henderson

[permalink] [raw]
Subject: Re: GCC 3.4 Heads-up

On Tue, Jan 06, 2004 at 01:06:19PM -0800, David Mosberger-Tang wrote:
> This works provided you can take the address of the lvalue, which
> ain't true for bitfields.

Indeed. Which means that the compiler almost certainly would have
done the wrong thing in certain cases with the conditional lvalue
extension.

There were real, hard to fix bugs here. Rather than sweat too much
about what the "right" semantics are supposed to be, and how to get
them all "correct", we just removed the ill-thought extension.

> I'd love to know a way of doing this in ANSI C99 without requiring
> changes to to uses of this kind of (atrocious) macro...

In ANSI C you've no alternative except memcpy, since you can't cast
the pointer and reference the object via some other type (assuming
neither type is char, yadda yadda).


r~

2004-01-06 23:23:52

by Linus Torvalds

[permalink] [raw]
Subject: Re: GCC 3.4 Heads-up



On Tue, 6 Jan 2004, Richard Henderson wrote:
>
> In ANSI C you've no alternative except memcpy, since you can't cast
> the pointer and reference the object via some other type (assuming
> neither type is char, yadda yadda).

Sure you have. You can _always_ change

(a ? b : c) = d;

to

tmp = d;
a ? (b = tmp) : (c = tmp);

which is not pretty, but with some macro abuse it won't be horrible. In
fact, once you do that, you might as well just do a real "if" statement.

Especially if you're going to continue to use (less odious) gcc-specific
stuff you can probably automate it fairly well with a replacement that
uses "typeof" and expresstion statements to do that "tmp" variable
properly.

Ie it might be _slightly_ more complex than running a "sed" script over
the sources, but it shouldn't be that much worse.

Linus

2004-01-07 09:56:00

by Richard Henderson

[permalink] [raw]
Subject: Re: GCC 3.4 Heads-up

On Tue, Jan 06, 2004 at 03:23:31PM -0800, Linus Torvalds wrote:
> > In ANSI C you've no alternative except memcpy, since you can't cast
> > the pointer and reference the object via some other type (assuming
> > neither type is char, yadda yadda).
>
> Sure you have. You can _always_ change
>
> (a ? b : c) = d;
>
> to
>
> tmp = d;
> a ? (b = tmp) : (c = tmp);

No, I meant his bitfield macro at all. You can't just go and
construct a bit field at random and dereference it.


r~