linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* 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).