* GCC 3.4 Heads-up
@ 2003-12-26 1:46 Chris Meadors
2003-12-26 3:46 ` H. Peter Anvin
2003-12-30 1:37 ` Rusty Russell
0 siblings, 2 replies; 26+ messages in thread
From: Chris Meadors @ 2003-12-26 1:46 UTC (permalink / raw)
To: Linux Kernel
I know it isn't the recommended compiler, heck it isn't even released
yet, but I was messing around with a GCC 3.4 snapshot, and figured I'd
give compiling the 2.6.0 kernel a shot.
Other than the constant barrage of warnings about the use of compound
expressions as lvalues being deprecated* (mostly because of lines 114,
116, and 117 of rcupdate.h, which is included everywhere), the build
goes very well.
It isn't until the final link that I get an error. It seems that
something goes funny with the ACPI's use of strcpy. I get undefined
references to strcpy in: acpi_bus_generate_event (twice),
acpi_power_add, acpi_thermal_add, and acpi_bus_add. There may be
additional different locations, but the error output stops there.
As I said, I'm just messing around, and figured I'd let everyone know
what's in the pipeline. But if it is a simple fix, I'll give any
changes anyone wants to try a shot.
*It also doesn't like cast or conditional expressions as lvalues.
--
Chris
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2003-12-26 1:46 GCC 3.4 Heads-up Chris Meadors
@ 2003-12-26 3:46 ` H. Peter Anvin
2003-12-26 4:34 ` Linus Torvalds
2003-12-30 1:37 ` Rusty Russell
1 sibling, 1 reply; 26+ messages in thread
From: H. Peter Anvin @ 2003-12-26 3:46 UTC (permalink / raw)
To: linux-kernel
Followup to: <1072403207.17036.37.camel@clubneon.clubneon.com>
By author: Chris Meadors <clubneon@hereintown.net>
In newsgroup: linux.dev.kernel
>
> Other than the constant barrage of warnings about the use of compound
> expressions as lvalues being deprecated* (mostly because of lines 114,
> 116, and 117 of rcupdate.h, which is included everywhere), the build
> goes very well.
>
> *It also doesn't like cast or conditional expressions as lvalues.
>
Okay, that's just insane...
-hpa
--
<hpa@transmeta.com> at work, <hpa@zytor.com> in private!
If you send me mail in HTML format I will assume it's spam.
"Unix gives you enough rope to shoot yourself in the foot."
Architectures needed: ia64 m68k mips64 ppc ppc64 s390 s390x sh v850 x86-64
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2003-12-26 3:46 ` H. Peter Anvin
@ 2003-12-26 4:34 ` Linus Torvalds
2003-12-26 6:04 ` H. Peter Anvin
` (2 more replies)
0 siblings, 3 replies; 26+ messages in thread
From: Linus Torvalds @ 2003-12-26 4:34 UTC (permalink / raw)
To: H. Peter Anvin; +Cc: linux-kernel
On Thu, 25 Dec 2003, H. Peter Anvin wrote:
> >
> > Other than the constant barrage of warnings about the use of compound
> > expressions as lvalues being deprecated* (mostly because of lines 114,
> > 116, and 117 of rcupdate.h, which is included everywhere), the build
> > goes very well.
> >
> > *It also doesn't like cast or conditional expressions as lvalues.
> >
>
> Okay, that's just insane...
Actually, those language extensions (while documented for a long time) are
pretty ugly.
Some of that ugliness turns into literal bugs when C++ is used.
The cast/conditional expression as lvalue are _particularly_ ugly
extensions, since there is absolutely zero point to them. They are very
much against what C is all about, and writing something like this:
a ? b : c = d;
is something that only a high-level language person could have come up
with. The _real_ way to do this in C is to just do
*(a ? &b : &c) = d;
which is portable C, does the same thing, and has no strange semantics.
Similarly, what the _hell_ does the gcc extension
int a;
(char)a += b;
really mean? The whole extension is just braindamaged, again probably
because there were non-C people involved at some point. It's very much
against the C philosophy. I bet 99% of the people on this list have no
clue what the exact semantics of the above are.
Linus
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2003-12-26 4:34 ` Linus Torvalds
@ 2003-12-26 6:04 ` H. Peter Anvin
2003-12-26 6:58 ` Andy Isaacson
2004-01-02 21:57 ` Bill Davidsen
2 siblings, 0 replies; 26+ messages in thread
From: H. Peter Anvin @ 2003-12-26 6:04 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel
Linus Torvalds wrote:
>
> Similarly, what the _hell_ does the gcc extension
>
> int a;
>
> (char)a += b;
>
> really mean? The whole extension is just braindamaged, again probably
> because there were non-C people involved at some point. It's very much
> against the C philosophy. I bet 99% of the people on this list have no
> clue what the exact semantics of the above are.
>
Oh, right. When I heard "cast as lvalue" I envisioned:
*(char *)foo = bar;
... being a warning, but that's not a cast, even though the pointer is.
-hpa
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2003-12-26 4:34 ` Linus Torvalds
2003-12-26 6:04 ` H. Peter Anvin
@ 2003-12-26 6:58 ` Andy Isaacson
2003-12-26 7:07 ` H. Peter Anvin
` (2 more replies)
2004-01-02 21:57 ` Bill Davidsen
2 siblings, 3 replies; 26+ messages in thread
From: Andy Isaacson @ 2003-12-26 6:58 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel
On Thu, Dec 25, 2003 at 08:34:33PM -0800, Linus Torvalds wrote:
> The cast/conditional expression as lvalue are _particularly_ ugly
> extensions, since there is absolutely zero point to them. They are very
> much against what C is all about, and writing something like this:
>
> a ? b : c = d;
>
> is something that only a high-level language person could have come up
> with. The _real_ way to do this in C is to just do
>
> *(a ? &b : &c) = d;
>
> which is portable C, does the same thing, and has no strange semantics.
But doesn't the first one potentially let the compiler avoid spilling to
memory, if b and c are both in registers?
Not that I'm fond of gccisms, but this one at least seems to have a
potential value. And I'm sure I came up with an instance of it making
my head ache, a while back, but I can't come up with a bad example now.
Care to elaborate on your "strange semantics"?
-andy
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2003-12-26 6:58 ` Andy Isaacson
@ 2003-12-26 7:07 ` H. Peter Anvin
2003-12-26 7:08 ` Linus Torvalds
2003-12-29 16:13 ` David Lloyd
2 siblings, 0 replies; 26+ messages in thread
From: H. Peter Anvin @ 2003-12-26 7:07 UTC (permalink / raw)
To: linux-kernel
Followup to: <20031226005840.A30827@hexapodia.org>
By author: Andy Isaacson <adi@hexapodia.org>
In newsgroup: linux.dev.kernel
>
> On Thu, Dec 25, 2003 at 08:34:33PM -0800, Linus Torvalds wrote:
> > The cast/conditional expression as lvalue are _particularly_ ugly
> > extensions, since there is absolutely zero point to them. They are very
> > much against what C is all about, and writing something like this:
> >
> > a ? b : c = d;
> >
> > is something that only a high-level language person could have come up
> > with. The _real_ way to do this in C is to just do
> >
> > *(a ? &b : &c) = d;
> >
> > which is portable C, does the same thing, and has no strange semantics.
>
> But doesn't the first one potentially let the compiler avoid spilling to
> memory, if b and c are both in registers?
>
> Not that I'm fond of gccisms, but this one at least seems to have a
> potential value. And I'm sure I came up with an instance of it making
> my head ache, a while back, but I can't come up with a bad example now.
> Care to elaborate on your "strange semantics"?
>
A decent compiler should be able to avoid spills in either case.
-hpa
--
<hpa@transmeta.com> at work, <hpa@zytor.com> in private!
If you send me mail in HTML format I will assume it's spam.
"Unix gives you enough rope to shoot yourself in the foot."
Architectures needed: ia64 m68k mips64 ppc ppc64 s390 s390x sh v850 x86-64
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2003-12-26 6:58 ` Andy Isaacson
2003-12-26 7:07 ` H. Peter Anvin
@ 2003-12-26 7:08 ` Linus Torvalds
2003-12-29 16:13 ` David Lloyd
2 siblings, 0 replies; 26+ messages in thread
From: Linus Torvalds @ 2003-12-26 7:08 UTC (permalink / raw)
To: Andy Isaacson; +Cc: linux-kernel
On Fri, 26 Dec 2003, Andy Isaacson wrote:
>
> But doesn't the first one potentially let the compiler avoid spilling to
> memory, if b and c are both in registers?
Sure, and you can do it as
tmp = d;
a ? b = tmp : c = tmp;
instead if you want to. It all depends on what b/c actually are (ie maybe
they are memory-backed anyway).
The point being that there are no actual _advantages_ to being
non-standard. And there are definitely disadvantages. Lack of portability
being one, semantic confusion being another (the semantic confusion is
more visible in C++, since there lvalue'ness is more complex. But it's
visible in C too, where the gcc extensions can cause buggy programs that
_should_ give syntax errors to possibly compile to unexpected results).
Linus
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
@ 2003-12-26 11:02 linux
2003-12-26 20:05 ` Linus Torvalds
2003-12-27 16:39 ` Andreas Schwab
0 siblings, 2 replies; 26+ messages in thread
From: linux @ 2003-12-26 11:02 UTC (permalink / raw)
To: linux-kernel, torvalds
> Similarly, what the _hell_ does the gcc extension
>
> int a;
>
> (char)a += b;
>
> really mean? The whole extension is just braindamaged,
It means a = (int)((char)a + b).
(Modulo the fact that the value of the expression is the sum of type
char and not the final value of type int.)
Applied to integer types, it *is* pretty brain damaged. But applied to
pointer types, it makes a lot more sense.
This is because "a += b" in C is actually "a += b * sizeof(*a)", and
sometimes you want a different *a.
In particular, 1 is a popular value.
Consider the common case of a structure which has a bunch of variable-sized
blocks with a standard header:
struct foo {
unsigned type, size;
...
} a;
Then you *do* have to write
a = (struct foo *)((char *)a + a->size);
and I might argue that
(char *)a += a->size;
is definitely cleaner.
Or consider the case when the structure doesn't have an explicit size
and you have a big case statement for parsing it:
switch (a->type) {
case BAR:
process_bar_chunk(((struct bar *)a)++);
break;
case BAZ:
process_baz_chunk(((struct baz *)a)++);
break;
...
};
Isn't that code a bit nicer looking? I put the redundant parens
in to remind people that I didn't mean to write "(struct bar *)(a++)"
(which also has its legitimate uses).
Necessary, no. But not "brain damaged", either.
It's well-defined and has legitimate uses.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2003-12-26 11:02 linux
@ 2003-12-26 20:05 ` Linus Torvalds
2003-12-27 16:39 ` Andreas Schwab
1 sibling, 0 replies; 26+ messages in thread
From: Linus Torvalds @ 2003-12-26 20:05 UTC (permalink / raw)
To: linux; +Cc: linux-kernel
On Fri, 26 Dec 2003 linux@horizon.com wrote:
>
> Applied to integer types, it *is* pretty brain damaged. But applied to
> pointer types, it makes a lot more sense.
No it doesn't.
Your example shows all the problems with the thing:
> Or consider the case when the structure doesn't have an explicit size
> and you have a big case statement for parsing it:
>
> switch (a->type) {
> case BAR:
> process_bar_chunk(((struct bar *)a)++);
> break;
Do you _really_ want to write unportable code for no reason?
This can trivially be done portably and readably by just adding a small
bit of verbiage, ie you could have
#define next_ptr(x,type) (void *)(1+(type *)(x))
and just write
process_bar_chunk(a);
a = next_ptr(a, struct bar);
or similar. Suddenly you can compile your code with any compiler you want
to, including one that maybe generates better code than gcc. Including
newer versions of gcc.
And suddenly people can look at your code, and understand what it is
doing, even if they don't know all the gcc extensions. That's _important_.
Some extensions are fairly obvious. I think the "a ? : b" one is pretty
simple, conceptually (ie you can explain it to even a novice C user
without there being any confusion). But the "cast as lvalue" definitely
isn't.
> It's well-defined and has legitimate uses.
It has no legitimate uses. The only upside of it is to avoid typing a few
extra characters, but since using macros can make the code more readable
anyway, that's not a very good argument.
Linus
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2003-12-26 11:02 linux
2003-12-26 20:05 ` Linus Torvalds
@ 2003-12-27 16:39 ` Andreas Schwab
1 sibling, 0 replies; 26+ messages in thread
From: Andreas Schwab @ 2003-12-27 16:39 UTC (permalink / raw)
To: linux; +Cc: linux-kernel
linux@horizon.com writes:
> Or consider the case when the structure doesn't have an explicit size
> and you have a big case statement for parsing it:
>
> switch (a->type) {
> case BAR:
> process_bar_chunk(((struct bar *)a)++);
> break;
> case BAZ:
> process_baz_chunk(((struct baz *)a)++);
> break;
> ...
> };
>
> Isn't that code a bit nicer looking? I put the redundant parens
Except that the parens are not redundant.
> in to remind people that I didn't mean to write "(struct bar *)(a++)"
> (which also has its legitimate uses).
Which is why it's parsed this way by default.
Andreas.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2003-12-26 6:58 ` Andy Isaacson
2003-12-26 7:07 ` H. Peter Anvin
2003-12-26 7:08 ` Linus Torvalds
@ 2003-12-29 16:13 ` David Lloyd
2 siblings, 0 replies; 26+ messages in thread
From: David Lloyd @ 2003-12-29 16:13 UTC (permalink / raw)
To: Andy Isaacson; +Cc: Linus Torvalds, linux-kernel
On Fri, 26 Dec 2003, Andy Isaacson wrote:
> On Thu, Dec 25, 2003 at 08:34:33PM -0800, Linus Torvalds wrote:
> > The cast/conditional expression as lvalue are _particularly_ ugly
> > extensions, since there is absolutely zero point to them. They are very
> > much against what C is all about, and writing something like this:
> >
> > a ? b : c = d;
> >
> > is something that only a high-level language person could have come up
> > with. The _real_ way to do this in C is to just do
> >
> > *(a ? &b : &c) = d;
> >
> > which is portable C, does the same thing, and has no strange semantics.
>
> But doesn't the first one potentially let the compiler avoid spilling to
> memory, if b and c are both in registers?
I can't imagine anything wrong with:
if (a) b = d else c = d;
- D
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2003-12-26 1:46 GCC 3.4 Heads-up Chris Meadors
2003-12-26 3:46 ` H. Peter Anvin
@ 2003-12-30 1:37 ` Rusty Russell
1 sibling, 0 replies; 26+ messages in thread
From: Rusty Russell @ 2003-12-30 1:37 UTC (permalink / raw)
To: Chris Meadors; +Cc: linux-kernel, akpm, trivial
On Thu, 25 Dec 2003 20:46:48 -0500
Chris Meadors <clubneon@hereintown.net> wrote:
> I know it isn't the recommended compiler, heck it isn't even released
> yet, but I was messing around with a GCC 3.4 snapshot, and figured I'd
> give compiling the 2.6.0 kernel a shot.
>
> Other than the constant barrage of warnings about the use of compound
> expressions as lvalues being deprecated* (mostly because of lines 114,
> 116, and 117 of rcupdate.h, which is included everywhere), the build
> goes very well.
Thanks, downloaded this and tried it. It's complaining about:
#define per_cpu(var, cpu) ((void)cpu, per_cpu__##var)
There are several ways of fixing this, but the simplest is:
#define per_cpu(var, cpu) (*((void)cpu, &per_cpu__##var))
Cheers,
Rusty.
--
there are those who do and those who hang on and you don't see too
many doers quoting their contemporaries. -- Larry McVoy
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.6.0/include/asm-generic/percpu.h working-2.6.0-new-gcc/include/asm-generic/percpu.h
--- linux-2.6.0/include/asm-generic/percpu.h 2003-09-22 10:26:12.000000000 +1000
+++ working-2.6.0-new-gcc/include/asm-generic/percpu.h 2003-12-30 12:35:20.000000000 +1100
@@ -29,7 +29,7 @@ do { \
#define DEFINE_PER_CPU(type, name) \
__typeof__(type) per_cpu__##name
-#define per_cpu(var, cpu) ((void)cpu, per_cpu__##var)
+#define per_cpu(var, cpu) (*((void)cpu, &per_cpu__##var))
#define __get_cpu_var(var) per_cpu__##var
#endif /* SMP */
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2003-12-26 4:34 ` Linus Torvalds
2003-12-26 6:04 ` H. Peter Anvin
2003-12-26 6:58 ` Andy Isaacson
@ 2004-01-02 21:57 ` Bill Davidsen
2004-01-03 21:11 ` Krzysztof Halasa
2 siblings, 1 reply; 26+ messages in thread
From: Bill Davidsen @ 2004-01-02 21:57 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel
Linus Torvalds wrote:
> Actually, those language extensions (while documented for a long time) are
> pretty ugly.
>
> Some of that ugliness turns into literal bugs when C++ is used.
>
> The cast/conditional expression as lvalue are _particularly_ ugly
> extensions, since there is absolutely zero point to them. They are very
> much against what C is all about, and writing something like this:
>
> a ? b : c = d;
>
> is something that only a high-level language person could have come up
> with. The _real_ way to do this in C is to just do
>
> *(a ? &b : &c) = d;
>
> which is portable C, does the same thing, and has no strange semantics.
I would probably write
( a ? b : c ) = d;
instead, having learned C when some compilers parsed ? wrong without
parens. Actually I can't imagine writing that at all, but at least with
parens humans can read it easily. Ugly code.
Your suggestion is not portable, if b or c are declared "register" there
are compilers which will not allow taking the address, and gcc will give
you a warning.
--
bill davidsen <davidsen@tmr.com>
CTO TMR Associates, Inc
Doing interesting things with small computers since 1979
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2004-01-02 21:57 ` Bill Davidsen
@ 2004-01-03 21:11 ` Krzysztof Halasa
2004-01-04 5:48 ` Bill Davidsen
0 siblings, 1 reply; 26+ messages in thread
From: Krzysztof Halasa @ 2004-01-03 21:11 UTC (permalink / raw)
To: Bill Davidsen; +Cc: Linus Torvalds, linux-kernel
Bill Davidsen <davidsen@tmr.com> writes:
> I would probably write
> ( a ? b : c ) = d;
> instead, having learned C when some compilers parsed ? wrong without
> parens. Actually I can't imagine writing that at all, but at least
> with parens humans can read it easily. Ugly code.
>
> Your suggestion is not portable, if b or c are declared "register"
> there are compilers which will not allow taking the address, and gcc
> will give you a warning.
One can write as well:
if (a)
b = d;
else
c = d;
Might be more readable and it is what the compiler does.
--
Krzysztof Halasa, B*FH
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2004-01-03 21:11 ` Krzysztof Halasa
@ 2004-01-04 5:48 ` Bill Davidsen
2004-01-04 20:41 ` Linus Torvalds
0 siblings, 1 reply; 26+ messages in thread
From: Bill Davidsen @ 2004-01-04 5:48 UTC (permalink / raw)
To: Krzysztof Halasa; +Cc: Linus Torvalds, linux-kernel
Krzysztof Halasa wrote:
> Bill Davidsen <davidsen@tmr.com> writes:
>
>
>>I would probably write
>> ( a ? b : c ) = d;
>>instead, having learned C when some compilers parsed ? wrong without
>>parens. Actually I can't imagine writing that at all, but at least
>>with parens humans can read it easily. Ugly code.
>>
>>Your suggestion is not portable, if b or c are declared "register"
>>there are compilers which will not allow taking the address, and gcc
>>will give you a warning.
>
>
> One can write as well:
>
> if (a)
> b = d;
> else
> c = d;
>
> Might be more readable and it is what the compiler does.
Since that's a matter of taste I can't disagree. The point was that the
original post used
*(a ? &b : &c) = d;
which generates either warnings or errors if b or c is a register
variable, because you are not allowed to take the address of a register.
It seems gcc does it anyway by intuiting what you mean, but it's not
portable in the sense of being error-free code.
It was a nit, I didn't mean to start a controversy, although if "d" is
actually a complex expression it is certainly less typing as I showed
it, and prevents a future maintainer from changing one RHS and not the
other. That's defensive programming.
--
bill davidsen <davidsen@tmr.com>
CTO TMR Associates, Inc
Doing interesting things with small computers since 1979
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2004-01-04 5:48 ` Bill Davidsen
@ 2004-01-04 20:41 ` Linus Torvalds
2004-01-05 1:28 ` Bill Davidsen
0 siblings, 1 reply; 26+ messages in thread
From: Linus Torvalds @ 2004-01-04 20:41 UTC (permalink / raw)
To: Bill Davidsen; +Cc: Krzysztof Halasa, linux-kernel
On Sun, 4 Jan 2004, Bill Davidsen wrote:
>
> Since that's a matter of taste I can't disagree. The point was that the
> original post used
> *(a ? &b : &c) = d;
> which generates either warnings or errors if b or c is a register
> variable, because you are not allowed to take the address of a register.
The thing is, the above case is the _only_ case where there is any point
to using a conditional expression and an assignment to the result in the
same expression.
If you have local variables (register or not), the sane thing to do is
if (a)
b = d;
else
c = d;
or variations on that. That's the readable code.
The only case where conditional assignment expressions are useful is when
you are literally trying to avoid doing branches, and the compiler isn't
smart enough to avoid them otherwise.
Check the compiler output some day. Try out what
int a, b;
void test_assignment_1(int val)
{
*(val ? &a : &b) = 1;
}
void test_assignment_2(int val)
{
if (val)
a = 1;
else
b = 1;
}
void test_assignment_3(int val)
{
(val ? a : b) = 1;
}
actually generate.
Hint: only the first one generates code without any jumps (on
architectures that have conditional moves and with "normal" compilers).
In short: the "*(a?&b:&c) = x" format actually has some advantages. It
also happens to be standard C. The "(a ? b : c) = x" format is not only
not real C code, but it has _zero_ advantages.
Linus
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2004-01-04 20:41 ` Linus Torvalds
@ 2004-01-05 1:28 ` Bill Davidsen
2004-01-05 1:38 ` Måns Rullgård
2004-01-05 2:25 ` Linus Torvalds
0 siblings, 2 replies; 26+ messages in thread
From: Bill Davidsen @ 2004-01-05 1:28 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Krzysztof Halasa, linux-kernel
Linus Torvalds wrote:
>
> On Sun, 4 Jan 2004, Bill Davidsen wrote:
>
>>Since that's a matter of taste I can't disagree. The point was that the
>>original post used
>> *(a ? &b : &c) = d;
>>which generates either warnings or errors if b or c is a register
>>variable, because you are not allowed to take the address of a register.
>
>
> The thing is, the above case is the _only_ case where there is any point
> to using a conditional expression and an assignment to the result in the
> same expression.
We disagree, see below.
> If you have local variables (register or not), the sane thing to do is
>
> if (a)
> b = d;
> else
> c = d;
>
> or variations on that. That's the readable code.
But may lead to errors in maintenence. Your first example below avoids
that problem. Imagine instead of "d" you have a 40-50 character RHS. Now
imagine that the code needs to be changed. If you have the long
expression in two places then it invites the possiblility of someone
changing only one of them. You may never make mistakes, but the rest of
us do, and the conditional LHS avoids that.
>
> The only case where conditional assignment expressions are useful is when
> you are literally trying to avoid doing branches, and the compiler isn't
> smart enough to avoid them otherwise.
>
> Check the compiler output some day. Try out what
>
> int a, b;
>
> void test_assignment_1(int val)
> {
> *(val ? &a : &b) = 1;
> }
You pointed out that this generates good code, I pointed out that it
also avoids future errors and is not just a trick for broken compilers.
I take your point about generating good code, I'm sorry you can't see
that avoiding code duplication is good practice even without the benefit
of better code.
--
bill davidsen <davidsen@tmr.com>
CTO TMR Associates, Inc
Doing interesting things with small computers since 1979
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2004-01-05 1:28 ` Bill Davidsen
@ 2004-01-05 1:38 ` Måns Rullgård
2004-01-05 23:49 ` Ingo Oeser
2004-01-05 2:25 ` Linus Torvalds
1 sibling, 1 reply; 26+ messages in thread
From: Måns Rullgård @ 2004-01-05 1:38 UTC (permalink / raw)
To: linux-kernel
Bill Davidsen <davidsen@tmr.com> writes:
>> If you have local variables (register or not), the sane thing to do is
>> if (a)
>> b = d;
>> else
>> c = d;
>> or variations on that. That's the readable code.
>
> But may lead to errors in maintenence. Your first example below avoids
> that problem. Imagine instead of "d" you have a 40-50 character
> RHS. Now imagine that the code needs to be changed. If you have the
> long expression in two places then it invites the possiblility of
> someone changing only one of them. You may never make mistakes, but
> the rest of us do, and the conditional LHS avoids that.
What's wrong with
d = long_expression;
if (a)
b = d;
else
c = d;
Your long expression is still only in one place.
--
Måns Rullgård
mru@kth.se
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2004-01-05 1:28 ` Bill Davidsen
2004-01-05 1:38 ` Måns Rullgård
@ 2004-01-05 2:25 ` Linus Torvalds
2004-01-05 4:15 ` Bill Davidsen
1 sibling, 1 reply; 26+ messages in thread
From: Linus Torvalds @ 2004-01-05 2:25 UTC (permalink / raw)
To: Bill Davidsen; +Cc: Krzysztof Halasa, linux-kernel
On Sun, 4 Jan 2004, Bill Davidsen wrote:
>
> You pointed out that this generates good code, I pointed out that it
> also avoids future errors and is not just a trick for broken compilers.
> I take your point about generating good code, I'm sorry you can't see
> that avoiding code duplication is good practice even without the benefit
> of better code.
Don't be silly. Using non-standard C is _never_ good practice.
If 'd' is a complex expression, and you want to avoid duplicating it, just
create another temporary variable.
THAT is good practice. Not strange gcc-only special code that other
compilers won't touch.
Linus
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2004-01-05 2:25 ` Linus Torvalds
@ 2004-01-05 4:15 ` Bill Davidsen
2004-01-05 4:36 ` Linus Torvalds
0 siblings, 1 reply; 26+ messages in thread
From: Bill Davidsen @ 2004-01-05 4:15 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Krzysztof Halasa, linux-kernel
Linus Torvalds wrote:
>
> On Sun, 4 Jan 2004, Bill Davidsen wrote:
>
>>You pointed out that this generates good code, I pointed out that it
>>also avoids future errors and is not just a trick for broken compilers.
>>I take your point about generating good code, I'm sorry you can't see
>>that avoiding code duplication is good practice even without the benefit
>>of better code.
>
>
> Don't be silly. Using non-standard C is _never_ good practice.
Your example, which I quoted, *is* standard C. And it avoids duplication
of code without extra variables, and is readable. We both agreed it was
standard, why have you canged your mind?
--
bill davidsen <davidsen@tmr.com>
CTO TMR Associates, Inc
Doing interesting things with small computers since 1979
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2004-01-05 4:15 ` Bill Davidsen
@ 2004-01-05 4:36 ` Linus Torvalds
0 siblings, 0 replies; 26+ messages in thread
From: Linus Torvalds @ 2004-01-05 4:36 UTC (permalink / raw)
To: Bill Davidsen; +Cc: Krzysztof Halasa, linux-kernel
On Sun, 4 Jan 2004, Bill Davidsen wrote:
>
> Your example, which I quoted, *is* standard C. And it avoids duplication
> of code without extra variables, and is readable. We both agreed it was
> standard, why have you canged your mind?
Oh, that one. I thought you were talking about the gcc extension.
My version is not what I'd call really readable unless you actually have
an agenda to access the variable though a pointer. In fact, the only case
where I have actually seen constructs like that is literally when you want
to avoid a branch for some specific reason, and you do something like
this:
int branchless_code(int *ptr)
{
int dummy;
...
*(ptr ? ptr : &dummy) = value;
...
}
it you'd rather do a unconditional store through a conditional pointer
than have a conditional store, and you use a dummy "sink" variable to take
the store if the condition isn't true.
Some compilers apparently generate this kind of code internally from
conditional statements. I've never seen gcc do it, though.
Linus
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2004-01-05 1:38 ` Måns Rullgård
@ 2004-01-05 23:49 ` Ingo Oeser
0 siblings, 0 replies; 26+ messages in thread
From: Ingo Oeser @ 2004-01-05 23:49 UTC (permalink / raw)
To: Måns Rullgård, linux-kernel
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On Monday 05 January 2004 02:38, Måns Rullgård wrote:
> What's wrong with
>
> d = long_expression;
> if (a)
> b = d;
> else
> c = d;
>
> Your long expression is still only in one place.
This seperates control and data flow quite nicely, which is good
programming practise anyway and helps the compiler optimizing, AFAIK.
Regards
Ingo Oeser
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (GNU/Linux)
iD8DBQE/+fgMU56oYWuOrkARAlOIAJ0c9QMsQRrXYv3RIV3r+8uAnJgETQCfQ7PJ
Zscp0VfGY2jS1RvWnuCAqoc=
=kY28
-----END PGP SIGNATURE-----
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
[not found] ` <16S5h-3no-5@gated-at.bofh.it>
@ 2004-01-06 21:06 ` David Mosberger-Tang
2004-01-06 22:33 ` Richard Henderson
0 siblings, 1 reply; 26+ messages in thread
From: David Mosberger-Tang @ 2004-01-06 21:06 UTC (permalink / raw)
To: torvalds; +Cc: rth, davidm, linux-kernel
>>>>> On Fri, 26 Dec 2003 05:50:07 +0100, Linus Torvalds <torvalds@osdl.org> 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; David.Mosberger@acm.org
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2004-01-06 21:06 ` David Mosberger-Tang
@ 2004-01-06 22:33 ` Richard Henderson
2004-01-06 23:23 ` Linus Torvalds
0 siblings, 1 reply; 26+ messages in thread
From: Richard Henderson @ 2004-01-06 22:33 UTC (permalink / raw)
To: David Mosberger-Tang; +Cc: torvalds, davidm, linux-kernel
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~
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2004-01-06 22:33 ` Richard Henderson
@ 2004-01-06 23:23 ` Linus Torvalds
2004-01-07 9:54 ` Richard Henderson
0 siblings, 1 reply; 26+ messages in thread
From: Linus Torvalds @ 2004-01-06 23:23 UTC (permalink / raw)
To: Richard Henderson; +Cc: David Mosberger-Tang, davidm, linux-kernel
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
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: GCC 3.4 Heads-up
2004-01-06 23:23 ` Linus Torvalds
@ 2004-01-07 9:54 ` Richard Henderson
0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2004-01-07 9:54 UTC (permalink / raw)
To: Linus Torvalds; +Cc: David Mosberger-Tang, davidm, linux-kernel
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~
^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2004-01-07 9:56 UTC | newest]
Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-12-26 1:46 GCC 3.4 Heads-up Chris Meadors
2003-12-26 3:46 ` H. Peter Anvin
2003-12-26 4:34 ` Linus Torvalds
2003-12-26 6:04 ` H. Peter Anvin
2003-12-26 6:58 ` Andy Isaacson
2003-12-26 7:07 ` H. Peter Anvin
2003-12-26 7:08 ` Linus Torvalds
2003-12-29 16:13 ` David Lloyd
2004-01-02 21:57 ` Bill Davidsen
2004-01-03 21:11 ` Krzysztof Halasa
2004-01-04 5:48 ` Bill Davidsen
2004-01-04 20:41 ` Linus Torvalds
2004-01-05 1:28 ` Bill Davidsen
2004-01-05 1:38 ` Måns Rullgård
2004-01-05 23:49 ` Ingo Oeser
2004-01-05 2:25 ` Linus Torvalds
2004-01-05 4:15 ` Bill Davidsen
2004-01-05 4:36 ` Linus Torvalds
2003-12-30 1:37 ` Rusty Russell
-- strict thread matches above, loose matches on Subject: below --
2003-12-26 11:02 linux
2003-12-26 20:05 ` Linus Torvalds
2003-12-27 16:39 ` Andreas Schwab
[not found] <16PqK-8eK-1@gated-at.bofh.it>
[not found] ` <16RiU-2kO-1@gated-at.bofh.it>
[not found] ` <16S5h-3no-5@gated-at.bofh.it>
2004-01-06 21:06 ` David Mosberger-Tang
2004-01-06 22:33 ` Richard Henderson
2004-01-06 23:23 ` Linus Torvalds
2004-01-07 9:54 ` Richard Henderson
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).