Bug 10093 – wrong unsigned arithmetic

Status
RESOLVED
Resolution
INVALID
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-05-16T06:29:00Z
Last change time
2013-05-17T08:14:33Z
Assigned to
nobody
Creator
luka8088

Comments

Comment #0 by luka8088 — 2013-05-16T06:29:40Z
The following code fails: static assert(-("foo".length) < 0);
Comment #1 by schveiguy — 2013-05-16T06:37:28Z
This is expected, array length is an unsigned property. unsigned math results in unsigned result. You are basically saying: static assert(-3u < 0) 0 is promoted to unsigned, and 0xff_ff_ff_fd is compared to it.
Comment #2 by sibaqexozequgaba — 2013-05-16T10:36:20Z
Should a negative unsigned number even compile? As far as I know, Visual C++ issues a warning in that case.
Comment #3 by schveiguy — 2013-05-16T11:11:38Z
(In reply to comment #2) > Should a negative unsigned number even compile? Debatable, but since it compiles in C, and is frequently used (-1u is 0xffffffff), I think it will continue to compile. > As far as I know, Visual C++ issues a warning in that case. But still compiles, right? C is full of questionable, yet valid, behavior.
Comment #4 by sibaqexozequgaba — 2013-05-16T11:25:00Z
Why would you ever do -1u? We don't talk about implicitly converting -1 to unsigned, right? That's a different case.
Comment #5 by schveiguy — 2013-05-16T11:44:46Z
(In reply to comment #4) > Why would you ever do -1u? Shortcut.
Comment #6 by sibaqexozequgaba — 2013-05-16T11:58:25Z
> We don't talk about implicitly converting -1 to unsigned, right? That's a different case. ^ Am I missing something? ^ We're not talking about: func: void SetText(char* text, uint len); call: SetText(text, -1); ^ here -1 is a special constant meaning e.g. calculate the len of a null terminated string. We're talking about: uint len = strlen(text); // ... Func(-len); // Why would you ever need this?
Comment #7 by schveiguy — 2013-05-16T12:44:36Z
(In reply to comment #6) > We're talking about: > uint len = strlen(text); > // ... > Func(-len); // Why would you ever need this? What about Func(1 - len) The compiler can't cover every case. If you want to propose something to make this illegal, go ahead, but I doubt you will get traction.
Comment #8 by luka8088 — 2013-05-16T12:49:27Z
(In reply to comment #6) > > We don't talk about implicitly converting -1 to unsigned, right? That's a different case. > ^ Am I missing something? ^ > > We're not talking about: > func: > void SetText(char* text, uint len); > call: > SetText(text, -1); > ^ here -1 is a special constant meaning e.g. calculate the len of a null > terminated string. > > We're talking about: > uint len = strlen(text); > // ... > Func(-len); // Why would you ever need this? The original issue was: auto offset = text1.length - text2.length; func(offset); and offset turned out to be around 4294967291 I was thinking, setting a uint to a negative value is kind of an overflow, should it maybe be treated the same way like array bounds and be checked by druntime (with optional disabling in production release)?
Comment #9 by sibaqexozequgaba — 2013-05-16T12:57:40Z
(In reply to comment #8) > The original issue was: > > auto offset = text1.length - text2.length; > func(offset); > > and offset turned out to be around 4294967291 > > I was thinking, setting a uint to a negative value is kind of an overflow, > should it maybe be treated the same way like array bounds and be checked by > druntime (with optional disabling in production release)? Well, that's probably something the compiler can't warn about. Not statically, that's for sure. You can use a custom type which checks for bound overflows, and fallback to regular int for release builds.
Comment #10 by luka8088 — 2013-05-16T13:07:39Z
(In reply to comment #9) > (In reply to comment #8) > > The original issue was: > > > > auto offset = text1.length - text2.length; > > func(offset); > > > > and offset turned out to be around 4294967291 > > > > I was thinking, setting a uint to a negative value is kind of an overflow, > > should it maybe be treated the same way like array bounds and be checked by > > druntime (with optional disabling in production release)? > > Well, that's probably something the compiler can't warn about. Not statically, > that's for sure. > You can use a custom type which checks for bound overflows, and fallback to > regular int for release builds. Yeah, I could, but should that maybe be in druntime? Also... void main () { auto a = 5 - 10u; // 4294967291u auto b = 5u - 10; // 4294967291u } Why are they both unsigned? I will take this to the forum.
Comment #11 by schveiguy — 2013-05-16T13:43:31Z
(In reply to comment #8) > The original issue was: > > auto offset = text1.length - text2.length; > func(offset); > > and offset turned out to be around 4294967291 > > I was thinking, setting a uint to a negative value is kind of an overflow, > should it maybe be treated the same way like array bounds and be checked by > druntime (with optional disabling in production release)? No. Just change func's parameter to an int.
Comment #12 by luka8088 — 2013-05-16T13:48:38Z
(In reply to comment #11) > (In reply to comment #8) > > The original issue was: > > > > auto offset = text1.length - text2.length; > > func(offset); > > > > and offset turned out to be around 4294967291 > > > > I was thinking, setting a uint to a negative value is kind of an overflow, > > should it maybe be treated the same way like array bounds and be checked by > > druntime (with optional disabling in production release)? > > No. Just change func's parameter to an int. http://dpaste.dzfl.pl/611c13d7 Yeah, it is easy to solve when you add a writeln and see that unsigned is causing the issue. =) Btw: http://forum.dlang.org/thread/[email protected]
Comment #13 by schveiguy — 2013-05-17T08:14:33Z