Jump to page: 1 2 3
Thread overview
Why do shift operators undergo integral promotion?
Aug 09, 2011
Don
Aug 09, 2011
Walter Bright
Aug 09, 2011
Jonathan M Davis
Aug 09, 2011
so
Aug 09, 2011
Andrew Wiley
Aug 09, 2011
so
Aug 09, 2011
Jonathan M Davis
Aug 09, 2011
bearophile
Aug 09, 2011
so
Aug 09, 2011
Jonathan M Davis
Aug 09, 2011
so
Aug 09, 2011
Jonathan M Davis
Aug 09, 2011
so
Aug 09, 2011
Walter Bright
Aug 09, 2011
Jonathan M Davis
Aug 09, 2011
Walter Bright
Aug 09, 2011
Jonathan M Davis
Aug 09, 2011
Timon Gehr
Aug 09, 2011
bearophile
Aug 10, 2011
KennyTM~
Aug 10, 2011
Don
August 09, 2011
From a discussion on D.learn.

If x and y are different integral types, then in an expression like
  x >> y
the integral promotion rules are applied to x and y.
This behaviour is obviously inherited from C, but why did C use such a counter-intuitive and bug-prone rule?
Why isn't typeof(x >> y) simply typeof(x) ?
What would break if it did?

You might think the the rule is that typeof( x >> y) is typeof( x + y),
but it isn't: the arithmetic conversions are NOT applied:
typeof(int >> long) is int, not long, BUT
typeof(short >> int) is int.
And we have this death trap (bug 2809):

void main()
{
  short s = -1;
  ushort u = s;
  assert( u == s );
  assert ( (s >>> 1) == (u >>> 1) ); // FAILS
}
August 09, 2011
On 8/9/2011 2:46 AM, Don wrote:
>  From a discussion on D.learn.
>
> If x and y are different integral types, then in an expression like
> x >> y
> the integral promotion rules are applied to x and y.
> This behaviour is obviously inherited from C, but why did C use such a
> counter-intuitive and bug-prone rule?
> Why isn't typeof(x >> y) simply typeof(x) ?
> What would break if it did?
>
> You might think the the rule is that typeof( x >> y) is typeof( x + y),
> but it isn't: the arithmetic conversions are NOT applied:
> typeof(int >> long) is int, not long, BUT
> typeof(short >> int) is int.
> And we have this death trap (bug 2809):
>
> void main()
> {
> short s = -1;
> ushort u = s;
> assert( u == s );
> assert ( (s >>> 1) == (u >>> 1) ); // FAILS
> }


That last is why we can't just change the behavior from C.
August 09, 2011
> On 8/9/2011 2:46 AM, Don wrote:
> > From a discussion on D.learn.
> > 
> > If x and y are different integral types, then in an expression like
> > x >> y
> > the integral promotion rules are applied to x and y.
> > This behaviour is obviously inherited from C, but why did C use such a
> > counter-intuitive and bug-prone rule?
> > Why isn't typeof(x >> y) simply typeof(x) ?
> > What would break if it did?
> > 
> > You might think the the rule is that typeof( x >> y) is typeof( x + y),
> > but it isn't: the arithmetic conversions are NOT applied:
> > typeof(int >> long) is int, not long, BUT
> > typeof(short >> int) is int.
> > And we have this death trap (bug 2809):
> > 
> > void main()
> > {
> > short s = -1;
> > ushort u = s;
> > assert( u == s );
> > assert ( (s >>> 1) == (u >>> 1) ); // FAILS
> > }
> 
> That last is why we can't just change the behavior from C.

The question though is whether that is ever _desired_ behavior in a C program. If it's always a bug when it happens, then I'd argue that we can and should change the behavior. If there's a legitimate reason why could would want the C behavior, then changing it in D would cause problems for porting code, but if the difference only matters when there's a bug in the C code, then breaking compatibility is only an issue for broken code, and changing it would help prevent issues in D.

- Jonathan M Davis
August 09, 2011
On Tue, 09 Aug 2011 21:37:18 +0300, Jonathan M Davis <jmdavisProg@gmx.com> wrote:

>> On 8/9/2011 2:46 AM, Don wrote:
>> > From a discussion on D.learn.
>> >
>> > If x and y are different integral types, then in an expression like
>> > x >> y
>> > the integral promotion rules are applied to x and y.
>> > This behaviour is obviously inherited from C, but why did C use such a
>> > counter-intuitive and bug-prone rule?
>> > Why isn't typeof(x >> y) simply typeof(x) ?
>> > What would break if it did?
>> >
>> > You might think the the rule is that typeof( x >> y) is typeof( x +  
>> y),
>> > but it isn't: the arithmetic conversions are NOT applied:
>> > typeof(int >> long) is int, not long, BUT
>> > typeof(short >> int) is int.
>> > And we have this death trap (bug 2809):
>> >
>> > void main()
>> > {
>> > short s = -1;
>> > ushort u = s;
>> > assert( u == s );
>> > assert ( (s >>> 1) == (u >>> 1) ); // FAILS
>> > }
>>
>> That last is why we can't just change the behavior from C.
>
> The question though is whether that is ever _desired_ behavior in a C program.
> If it's always a bug when it happens, then I'd argue that we can and should
> change the behavior. If there's a legitimate reason why could would want the C
> behavior, then changing it in D would cause problems for porting code, but if
> the difference only matters when there's a bug in the C code, then breaking
> compatibility is only an issue for broken code, and changing it would help
> prevent issues in D.
>
> - Jonathan M Davis

Can't we finally get rid of this compatibility issue by separating?
. for the whole file which can be enabled with a flag to compiler "dmd -Cmode ...."
. default it is not enforced, if we desire compatibility we could just write:

version(Cmode) // or something better instead of version
{
}

What would be the problem other than the trouble of implementing this?
I hate to see the shield of C compatibility against every good idea/solution.
August 09, 2011
On Tue, Aug 9, 2011 at 1:10 PM, so <so@so.xn--s-fka> wrote:

> On Tue, 09 Aug 2011 21:37:18 +0300, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
>
>  On 8/9/2011 2:46 AM, Don wrote:
>>> > From a discussion on D.learn.
>>> >
>>> > If x and y are different integral types, then in an expression like
>>> > x >> y
>>> > the integral promotion rules are applied to x and y.
>>> > This behaviour is obviously inherited from C, but why did C use such a
>>> > counter-intuitive and bug-prone rule?
>>> > Why isn't typeof(x >> y) simply typeof(x) ?
>>> > What would break if it did?
>>> >
>>> > You might think the the rule is that typeof( x >> y) is typeof( x + y),
>>> > but it isn't: the arithmetic conversions are NOT applied:
>>> > typeof(int >> long) is int, not long, BUT
>>> > typeof(short >> int) is int.
>>> > And we have this death trap (bug 2809):
>>> >
>>> > void main()
>>> > {
>>> > short s = -1;
>>> > ushort u = s;
>>> > assert( u == s );
>>> > assert ( (s >>> 1) == (u >>> 1) ); // FAILS
>>> > }
>>>
>>> That last is why we can't just change the behavior from C.
>>>
>>
>> The question though is whether that is ever _desired_ behavior in a C
>> program.
>> If it's always a bug when it happens, then I'd argue that we can and
>> should
>> change the behavior. If there's a legitimate reason why could would want
>> the C
>> behavior, then changing it in D would cause problems for porting code, but
>> if
>> the difference only matters when there's a bug in the C code, then
>> breaking
>> compatibility is only an issue for broken code, and changing it would help
>> prevent issues in D.
>>
>> - Jonathan M Davis
>>
>
> Can't we finally get rid of this compatibility issue by separating?
> . for the whole file which can be enabled with a flag to compiler "dmd
> -Cmode ...."
>

That would essentially mean we have two compilers to maintain at the end of the day because the semantics of certain operations would depend entirely on whether the compiler was in C mode or not.


August 09, 2011
so:

> Can't we finally get rid of this compatibility issue by separating?
> . for the whole file which can be enabled with a flag to compiler "dmd
> -Cmode ...."

See:
http://d.puremagic.com/issues/show_bug.cgi?id=4580

Bye,
bearophile
August 09, 2011
On Tue, 09 Aug 2011 23:20:02 +0300, Andrew Wiley <wiley.andrew.j@gmail.com> wrote:

>> Can't we finally get rid of this compatibility issue by separating?
>> . for the whole file which can be enabled with a flag to compiler "dmd
>> -Cmode ...."
>>
>
> That would essentially mean we have two compilers to maintain at the end of
> the day because the semantics of certain operations would depend entirely on
> whether the compiler was in C mode or not.

True, but we are now doing something similar (probably something much harder) which unlikely produces a positive outcome.
We say there is a compatibility where there was not (to which extend no one knows), on the other hand there are new rules/syntax for the same problems in the same language which would create awful amount of confusion, not to mention ignoring the solutions to the problems.

On maintaining two compilers, i don't think this is a bigger issue because C compiler and spec already here and never changes.
August 09, 2011
> On Tue, 09 Aug 2011 23:20:02 +0300, Andrew Wiley
> 
> <wiley.andrew.j@gmail.com> wrote:
> >> Can't we finally get rid of this compatibility issue by separating?
> >> . for the whole file which can be enabled with a flag to compiler "dmd
> >> -Cmode ...."
> > 
> > That would essentially mean we have two compilers to maintain at the end
> > of
> > the day because the semantics of certain operations would depend
> > entirely on
> > whether the compiler was in C mode or not.
> 
> True, but we are now doing something similar (probably something much
> harder) which unlikely produces a positive outcome.
> We say there is a compatibility where there was not (to which extend no
> one knows), on the other hand there are new rules/syntax for the same
> problems in the same language which would create awful amount of
> confusion, not to mention ignoring the solutions to the problems.
> 
> On maintaining two compilers, i don't think this is a bigger issue because C compiler and spec already here and never changes.

Generally speaking, when C or C++ code compiles as D code, it has identical behavior (there are a few exceptions - such as passing static arrays - but it's almost always true). The reason for this is so that you don't end up with tons of bugs when porting code to D from C or C++. If it weren't for that, then corner cases such as this wouldn't really matter, and we could just make D to the smart thing. But because we don't want code which is ported to break in all kinds of subtle ways, we maintain compatibility with C/C++ as long as the C/C++ code is valid D code.

There's no reason to have a separate version of the language which is more compatible with C than another version. It would just complicate things. Not only would it be a burden on the compiler maintainers, but then you would have to know whether code was intended to be compiled with the standard D compiler or with the one which is more compatible with C. It would be a mess for very little benefit.

The question here is whether we can safely make the change to D's behavior without breaking code which is ported from C or C++. As long as it is pretty much a guarantee that any code which relies on the C behavior is buggy, then I don't see any reason why we can't fix the behavior in D. However, if there are valid reasons for C code to rely on the C behavior, then we're kind of stuck.
>From what I can see though, it sure looks like any C code which relies on the
C behavior would be buggy.

- Jonathan M Davis
August 09, 2011
Jonathan M Davis:

> There's no reason to have a separate version of the language which is more compatible with C than another version. It would just complicate things. Not only would it be a burden on the compiler maintainers, but then you would have to know whether code was intended to be compiled with the standard D compiler or with the one which is more compatible with C. It would be a mess for very little benefit.

You are too much quick at dismissing this. There are several advantages you aren't even listing.

Bye,
bearophile
August 09, 2011
On Wed, 10 Aug 2011 00:08:02 +0300, Jonathan M Davis <jmdavisProg@gmx.com> wrote:

> There's no reason to have a separate version of the language which is more
> compatible with C than another version. It would just complicate things.

> Not
> only would it be a burden on the compiler maintainers, but then you would have
> to know whether code was intended to be compiled with the standard D compiler
> or with the one which is more compatible with C. It would be a mess for very
> little benefit.

I see having a compiler flag is a bad idea, it would be entirely in the source code.
It is not about having more/less compatible compilers. There is only one compiler to be maintained and it is D.
Getting rid of such a restriction (C compatibility) would be priceless i can't express, and i don't understand why it is not obvious.
Our problem is this very restriction. D should be called "C like (easy to learn if you know C/C++) and supports C natively", not "C compatible". Because if being out of date was the only thing wrong about C then someone would just add some modern features and call it maybe... C++-+%?

> The question here is whether we can safely make the change to D's behavior
> without breaking code which is ported from C or C++. As long as it is pretty
> much a guarantee that any code which relies on the C behavior is buggy, then I
> don't see any reason why we can't fix the behavior in D. However, if there are
> valid reasons for C code to rely on the C behavior, then we're kind of stuck.
>> From what I can see though, it sure looks like any C code which relies on the
> C behavior would be buggy.

We are falling a trap C didn't. How is it any different than maintaining ASM compatibility in C? But they didn't, they just separated it.
They had a very compelling argument, so much more important than ours, that ASM is THE machine itself. Yet they just dropped it.

c code:
....
asm {
 ....
}

and d would be better of like:

...
asm {
...
}

...
C {
}
« First   ‹ Prev
1 2 3