]>
Commit | Line | Data |
---|---|---|
f4fe5584 PS |
1 | --- gcc/c-typeck.c (revision 110241) |
2 | +++ gcc/c-typeck.c (working copy) | |
3 | @@ -8101,12 +8101,35 @@ build_binary_op (enum tree_code code, tr | |
4 | if (shorten && none_complex) | |
5 | { | |
6 | int unsigned0, unsigned1; | |
7 | - tree arg0 = get_narrower (op0, &unsigned0); | |
8 | - tree arg1 = get_narrower (op1, &unsigned1); | |
9 | - /* UNS is 1 if the operation to be done is an unsigned one. */ | |
10 | - int uns = TYPE_UNSIGNED (result_type); | |
11 | + tree arg0, arg1; | |
12 | + int uns; | |
13 | tree type; | |
14 | ||
15 | + /* Cast OP0 and OP1 to RESULT_TYPE. Doing so prevents | |
16 | + excessive narrowing when we call get_narrower below. For | |
17 | + example, suppose that OP0 is of unsigned int extended | |
18 | + from signed char and that RESULT_TYPE is long long int. | |
19 | + If we explicitly cast OP0 to RESULT_TYPE, OP0 would look | |
20 | + like | |
21 | + | |
22 | + (long long int) (unsigned int) signed_char | |
23 | + | |
24 | + which get_narrower would narrow down to | |
25 | + | |
26 | + (unsigned int) signed char | |
27 | + | |
28 | + If we do not cast OP0 first, get_narrower would return | |
29 | + signed_char, which is inconsistent with the case of the | |
30 | + explicit cast. */ | |
31 | + op0 = convert (result_type, op0); | |
32 | + op1 = convert (result_type, op1); | |
33 | + | |
34 | + arg0 = get_narrower (op0, &unsigned0); | |
35 | + arg1 = get_narrower (op1, &unsigned1); | |
36 | + | |
37 | + /* UNS is 1 if the operation to be done is an unsigned one. */ | |
38 | + uns = TYPE_UNSIGNED (result_type); | |
39 | + | |
40 | final_type = result_type; | |
41 | ||
42 | /* Handle the case that OP0 (or OP1) does not *contain* a conversion | |
43 | Index: testsuite/gcc.c-torture/execute/pr19606.c | |
44 | =================================================================== | |
45 | --- /dev/null 2005-09-01 09:08:28.063949816 -0700 | |
46 | +++ gcc/testsuite/gcc.c-torture/execute/pr19606.c 2006-01-15 14:41:56.490361111 -0800 | |
47 | @@ -0,0 +1,33 @@ | |
48 | +/* PR c/19606 | |
49 | + The C front end used to shorten the type of a division even when | |
50 | + the signedness changes. Make sure that won't happen. */ | |
51 | + | |
52 | +signed char a = -4; | |
53 | + | |
54 | +int | |
55 | +foo (void) | |
56 | +{ | |
57 | + return ((unsigned int) (signed int) a) / 2LL; | |
58 | +} | |
59 | + | |
60 | +int | |
61 | +bar (void) | |
62 | +{ | |
63 | + return ((unsigned int) (signed int) a) % 5LL; | |
64 | +} | |
65 | + | |
66 | +int | |
67 | +main (void) | |
68 | +{ | |
69 | + int r; | |
70 | + | |
71 | + r = foo (); | |
72 | + if (r != ((unsigned int) (signed int) (signed char) -4) / 2LL) | |
73 | + abort (); | |
74 | + | |
75 | + r = bar (); | |
76 | + if (r != ((unsigned int) (signed int) (signed char) -4) % 5LL) | |
77 | + abort (); | |
78 | + | |
79 | + exit (0); | |
80 | +} | |
81 |