www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Correct comparison of signed type with unsigned type (and vice versa)

reply "Xinok" <xinok live.com> writes:
The following statement prints false:

writeln(-1 < uint.max);

This came up in another topic recently. I think this is silly and
an unnecessary source of bugs (it's bitten me before and
presumably many others as well). I'm making a proposal to add an
extra check so that comparisons of signed with unsigned types is
always correct. Simply, if the signed type is negative, it is by
default less than the unsigned value. The compiler has all the
information it needs at compile time to add this check where
necessary. I demonstrate the problem and solution here:

http://dpaste.dzfl.pl/acd819d1a9ea

Others have suggested disallowing comparing a signed type with an
unsigned type. I think this is a better solution. Yes, it will
add a small bit of overhead, but I believe it's more important
for code to be correct than to be fast.

Any takers?
Feb 20 2014
next sibling parent "Meta" <jared771 gmail.com> writes:
On Thursday, 20 February 2014 at 20:52:23 UTC, Xinok wrote:
 The following statement prints false:

 writeln(-1 < uint.max);

 This came up in another topic recently. I think this is silly 
 and
 an unnecessary source of bugs (it's bitten me before and
 presumably many others as well). I'm making a proposal to add an
 extra check so that comparisons of signed with unsigned types is
 always correct. Simply, if the signed type is negative, it is by
 default less than the unsigned value. The compiler has all the
 information it needs at compile time to add this check where
 necessary. I demonstrate the problem and solution here:

 http://dpaste.dzfl.pl/acd819d1a9ea

 Others have suggested disallowing comparing a signed type with 
 an
 unsigned type. I think this is a better solution. Yes, it will
 add a small bit of overhead, but I believe it's more important
 for code to be correct than to be fast.

 Any takers?

This will silently change the semantics of any C code compiled with DMD (even if those semantics were extremely bug prone in the first place). Is this a good or bad thing? I can't think of any C code that would rely on such behaviour, but I think it'd just be safer all-around to make it an error.
Feb 20 2014
prev sibling next sibling parent "ponce" <contact gam3sfrommars.fr> writes:
On Thursday, 20 February 2014 at 20:52:23 UTC, Xinok wrote:
 The following statement prints false:

 writeln(-1 < uint.max);

I don't see this as a bug, this is exactly what I expect from a language with intact C integer semantics.
 This came up in another topic recently. I think this is silly 
 and
 an unnecessary source of bugs (it's bitten me before and
 presumably many others as well). I'm making a proposal to add an
 extra check so that comparisons of signed with unsigned types is
 always correct. Simply, if the signed type is negative, it is by
 default less than the unsigned value.

That subtly breaks C compatiblity.
 Others have suggested disallowing comparing a signed type with 
 an
 unsigned type. I think this is a better solution.

Currently in C the unsigned vs signed operations all follow the same rules. If you do this, would you also disallow unsigned vs signed addition, subtraction, divide? I feel this would make porting C code much longer, and it's already quite a bit of work.
Feb 21 2014
prev sibling next sibling parent "ponce" <contact gam3sfrommars.fr> writes:
On Thursday, 20 February 2014 at 22:52:55 UTC, Meta wrote:
 I can't think of any C code that would rely on such behaviour, 
 but I think it'd just be safer all-around to make it an error.

Eg this optimization: if ((unsigned int)(a - min) < (max - min)) // only one comparison instead of two { } And there is many C codes relying on unsigned promotion, since signed overflow in C99 is undefined behaviour. The easiest way to force an operation is then to use one cast.
Feb 21 2014
prev sibling next sibling parent "Francesco Cattoglio" <francesco.cattoglio gmail.com> writes:
On Thursday, 20 February 2014 at 20:52:23 UTC, Xinok wrote:
 Others have suggested disallowing comparing a signed type with 
 an
 unsigned type. I think this is a better solution. Yes, it will
 add a small bit of overhead, but I believe it's more important
 for code to be correct than to be fast.

more features than this. I was surprised to find out that we don't have any "SafeInt" type in D... I was sure someone had made it but I wasn't able to find it anywhere. My ideal int type: -Has an equivalent of NaN, meaning it doesn't have "0 initialization" which is somewhat bug-prone. -Is able to signal errors like overflow/division by zero, would be nice if throwing could be avoided. -Signed, but can be flagged as ">0 only", and signals an error if it gets assigned a negative value. -Some extra features that are surely awesome but I'm forgetting right now.
 Any takers?

Feb 21 2014
prev sibling next sibling parent Nick Treleaven <ntrel-public yahoo.co.uk> writes:
On 20/02/2014 20:52, Xinok wrote:
 Others have suggested disallowing comparing a signed type with an
 unsigned type.

Yes, that solution is pre-approved: https://d.puremagic.com/issues/show_bug.cgi?id=259 I think that's a very important bug to solve.
Feb 21 2014
prev sibling parent "Xinok" <xinok live.com> writes:
On Friday, 21 February 2014 at 10:45:50 UTC, ponce wrote:
 I don't see this as a bug, this is exactly what I expect from a 
 language with intact C integer semantics.

I didn't call it a bug. I said that it's prone to causing bugs.
 That subtly breaks C compatibility.

Personally, I wish we would drop some of the C semantics and allow the language evolve. In it's place, add a function attribute which would enable C semantics for the sake of migrating code.
 Currently in C the unsigned vs signed operations all follow the 
 same rules. If you do this, would you also disallow unsigned vs 
 signed addition, subtraction, divide?

Unfortunately, those operations don't have such simple solutions. D is a statically typed language and the compiler simply can't predict what the resultant type should be. However, comparisons do have a simple fix with minimal overhead.
Feb 21 2014