16997 – Integral promotion rules not being followed for unary + - ~ expressions

D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 16997 - Integral promotion rules not being followed for unary + - ~ expressions
Summary: Integral promotion rules not being followed for unary + - ~ expressions
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P1 major
Assignee: No Owner
URL:
Keywords:
: 17637 (view as issue list)
Depends on:
Blocks:
Reported: 2016年12月21日 00:18 UTC by ponce
Modified: 2018年02月05日 22:41 UTC (History)
2 users (show)

See Also:


Attachments
Patch in ketmar DMD fork ("aliced") to make unary +/- on small integers a warning (3.16 KB, patch)
2016年12月21日 00:32 UTC, ponce
Details | Diff
warning on unary minus/plus (3.26 KB, patch)
2016年12月21日 04:58 UTC, Ketmar Dark
Details | Diff
Show Obsolete (1) Add an attachment (proposed patch, testcase, etc.)

Note You need to log in before you can comment on or make changes to this issue.
Description ponce 2016年12月21日 00:18:49 UTC
Consider the following C++ program:
-----
#include <cstdio>
int main()
{
 signed char c = -128;
 printf("%d\n", (int)(-c));
 return 0;
}
-----
This prints "128".
Consider the supposedly identical D code:
-----
import core.stdc.stdio;
void main()
{
	byte c = -128;
	printf("%d\n", cast(int)(-c)); // -128
}
-----
Since the D unary minus doesn't promote byte to int, it yields a different result.
This is a real case that costed ketmar 40 min, while porting working C code.
Porting to D silently broke the code due to subtly different integer promotion rules. I'm pretty sure I would have given up becasue code that is translated is often enough not understood yet.
After investigation:
 * Taking the unary minus of byte and short and then asting to int yield different results for the lowest values: -128 and -32768
 * Taking the unary minus of ubyte and ushort and then casting to int
 yield different results for any value except 0
Why are the promotion rules for unary + and - different from C?
Comment 1 ponce 2016年12月21日 00:32:04 UTC
Created attachment 1626 [details] 
Patch in ketmar DMD fork ("aliced") to make unary +/- on small integers a warning
Comment 2 Ketmar Dark 2016年12月21日 04:58:18 UTC
Created attachment 1627 [details] 
warning on unary minus/plus
fixed patch, made against vanilla. it will show warning for unary -/+ for (u)byte and (u)short, but one can silence that with `-(expr)`. it prolly needs better message with explanation of what it is, and what to do, and why -- but i leave that for that one who will make a PR out of the patch.
Comment 3 Ketmar Dark 2016年12月21日 05:02:24 UTC
as for the question: promotion rules are what they are currently to allow this:
byte n;
n = -n;
if unary minus will promote `n`, you will need to add `cast` there. and negate never ever drop bits from integer (even byte.min is essentially unchanged, so no info is lost), so it is -- relatively -- safe to not promote here.
Comment 4 Ketmar Dark 2016年12月21日 05:03:34 UTC
p.s.: i'm not that smart, tbh, i understood the rationale behind the design after alot of hard thinking.
Comment 5 Walter Bright 2017年07月22日 09:48:58 UTC
https://github.com/dlang/dmd/pull/7013 
Comment 6 Walter Bright 2017年07月22日 09:50:33 UTC
*** Issue 17637 has been marked as a duplicate of this issue. ***
Comment 7 Walter Bright 2017年07月22日 10:27:41 UTC
Unary + and unary ~ are also broken in the same way.
Comment 8 Walter Bright 2017年07月22日 10:35:53 UTC
Note that the spec says:
"Note: unlike in C and C++, the usual integral promotions are not performed prior to the complement operation."
 http://dlang.org/spec/expression.html#complement_expressions
And the spec says nothing about unary - or unary +.
 http://dlang.org/spec/expression.html#unary-expression 
Comment 9 github-bugzilla 2017年07月24日 23:08:43 UTC
Commits pushed to master at https://github.com/dlang/phobos
https://github.com/dlang/phobos/commit/47d9a09e66d7fde929b596a72450a92d51d0b3e1
bigint: fix dependency on broken Issue 16997
https://github.com/dlang/phobos/commit/c1832981e3818a151ee25805d47d472633a218ad
Merge pull request #5646 from WalterBright/bigint-cast
bigint: fix dependency on broken Issue 16997
merged-on-behalf-of: Andrei Alexandrescu <andralex@users.noreply.github.com>
Comment 10 github-bugzilla 2017年08月16日 13:24:15 UTC
Commits pushed to stable at https://github.com/dlang/phobos
https://github.com/dlang/phobos/commit/47d9a09e66d7fde929b596a72450a92d51d0b3e1
bigint: fix dependency on broken Issue 16997
https://github.com/dlang/phobos/commit/c1832981e3818a151ee25805d47d472633a218ad
Merge pull request #5646 from WalterBright/bigint-cast
Comment 11 github-bugzilla 2017年10月23日 21:59:18 UTC
Commits pushed to master at https://github.com/dlang/dmd
https://github.com/dlang/dmd/commit/71403b6cd3781cd4d97104be1f4194e168a75d02
fix Issue 16997 - Integral promotion rules not being followed for unary + - ~ expressions
https://github.com/dlang/dmd/commit/7253190083cd66ae11711f2f6ff15497810d34c5
Merge pull request #7013 from WalterBright/fix16997
fix Issue 16997 - Integral promotion rules not being followed for neg...
Comment 12 github-bugzilla 2017年12月18日 22:55:09 UTC
Commits pushed to stable at https://github.com/dlang/dmd
https://github.com/dlang/dmd/commit/71403b6cd3781cd4d97104be1f4194e168a75d02
fix Issue 16997 - Integral promotion rules not being followed for unary + - ~ expressions
https://github.com/dlang/dmd/commit/7253190083cd66ae11711f2f6ff15497810d34c5
Merge pull request #7013 from WalterBright/fix16997
Comment 13 github-bugzilla 2018年01月05日 13:30:35 UTC
Commits pushed to dmd-cxx at https://github.com/dlang/phobos
https://github.com/dlang/phobos/commit/47d9a09e66d7fde929b596a72450a92d51d0b3e1
bigint: fix dependency on broken Issue 16997
https://github.com/dlang/phobos/commit/c1832981e3818a151ee25805d47d472633a218ad
Merge pull request #5646 from WalterBright/bigint-cast
Comment 14 ponce 2018年01月05日 13:43:47 UTC
Great! D is now a bit easier to explain.


AltStyle によって変換されたページ (->オリジナル) /