Skip to content

Commit e33e52c

Browse files
committed
Completely rewrote signed/unsigned int/long parsing code, based on Chapter 12
1 parent 940a757 commit e33e52c

File tree

5 files changed

+388
-52
lines changed

5 files changed

+388
-52
lines changed

examples/convert_by_assignment.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/* Test that we correctly perform conversions "as if by assignment", including:
2+
* - function arguments
3+
* - return statements
4+
* - actual assignment expressions
5+
* - initializers for automatic variables
6+
*/
7+
8+
#ifdef SUPPRESS_WARNINGS
9+
#ifdef __clang__
10+
#pragma clang diagnostic ignored "-Wconstant-conversion"
11+
#else
12+
#pragma GCC diagnostic ignored "-Woverflow"
13+
#endif
14+
#endif
15+
16+
int check_int(int converted, int expected) {
17+
return (converted == expected);
18+
}
19+
20+
int check_long(long converted, long expected) {
21+
return (converted == expected);
22+
}
23+
24+
int check_ulong(unsigned long converted, unsigned long expected) {
25+
return (converted == expected);
26+
}
27+
28+
long return_extended_uint(unsigned int u) {
29+
return u;
30+
}
31+
32+
unsigned long return_extended_int(int i) {
33+
return i;
34+
}
35+
36+
int return_truncated_ulong(unsigned long ul) {
37+
return ul;
38+
}
39+
40+
int extend_on_assignment(unsigned int ui, long expected) {
41+
long result = ui; // implicit conversion causes zero-extension
42+
return result == expected;
43+
}
44+
45+
int main(void) {
46+
// function arguments
47+
48+
/* truncate 2^63 + 5 to 5 */
49+
if (!check_int(9223372036854775813ul, 5)) {
50+
return 1;
51+
}
52+
53+
/* zero-extend 2^31+10, preserve its value */
54+
if (!check_long(2147483658u, 2147483658l)) {
55+
return 2;
56+
}
57+
58+
/* sign-extend -1 to ULONG_MAX */
59+
if (!check_ulong(-1, 18446744073709551615UL)) {
60+
return 3;
61+
}
62+
63+
// return values
64+
65+
/* zero-extend 2^31+10, preserve its value */
66+
if (return_extended_uint(2147483658u) != 2147483658l) {
67+
return 4;
68+
}
69+
70+
/* sign-extend -1 to ULONG_MAX */
71+
if (return_extended_int(-1) != 18446744073709551615UL) {
72+
return 5;
73+
}
74+
75+
/* truncate 2^50 + 2^31 + 100 to int, -2^31 + 100
76+
* then sign-extend, preserving its value
77+
*/
78+
long l = return_truncated_ulong(1125902054326372ul);
79+
if (l != -2147483548l) {
80+
return 6;
81+
}
82+
83+
// assignment expressions
84+
if (!extend_on_assignment(2147483658u, 2147483658l)){
85+
return 7;
86+
}
87+
88+
// local initializers
89+
int i = 4294967196u; // unsigned int 2^32 - 100, will be converted to -100
90+
if (i != -100) {
91+
return 8;
92+
}
93+
94+
95+
return 0;
96+
}

examples/truncate.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/* Test truncating wider to narrow types */
2+
int ulong_to_int(unsigned long ul, int expected) {
3+
int result = (int) ul;
4+
return (result == expected);
5+
}
6+
7+
int ulong_to_uint(unsigned long ul, unsigned expected) {
8+
return ((unsigned int) ul == expected);
9+
}
10+
11+
int long_to_uint(long l, unsigned int expected) {
12+
return (unsigned int) l == expected;
13+
}
14+
15+
int main(void) {
16+
/* truncate long */
17+
18+
/* 100 is in the range of unsigned int,
19+
* so truncating it to an unsigned int
20+
* will preserve its value
21+
*/
22+
if (!long_to_uint(100l, 100u)) {
23+
return 1;
24+
}
25+
26+
/* -9223372036854774574 (i.e. -2^63 + 1234) is outside the range of unsigned int,
27+
* so add 2^32 to bring it within range */
28+
if (!long_to_uint(-9223372036854774574l, 1234u)) {
29+
return 2;
30+
}
31+
32+
/* truncate unsigned long */
33+
34+
/* 100 can be cast to an int or unsigned int without changing its value */
35+
if (!ulong_to_int(100ul, 100)) {
36+
return 3;
37+
}
38+
39+
if (!ulong_to_uint(100ul, 100u)) {
40+
return 4;
41+
}
42+
43+
/* 4294967200 (i.e. 2^32 - 96) can be cast to an unsigned int without changing its value,
44+
* but must be reduced modulo 2^32 to cast to a signed int
45+
*/
46+
if (!ulong_to_uint(4294967200ul, 4294967200u)) {
47+
return 5;
48+
}
49+
50+
if (!ulong_to_int(4294967200ul, -96)) {
51+
return 6;
52+
}
53+
54+
/* 1152921506754330624 (i.e. 2^60 + 2^31) must be reduced modulo 2^32
55+
* to represent as a signed or unsigned int
56+
*/
57+
58+
if (!ulong_to_uint(1152921506754330624ul, 2147483648u)) { // reduce to 2^31
59+
return 7;
60+
}
61+
62+
if (!ulong_to_int(1152921506754330624ul, -2147483648)){ // reduce to -2^31
63+
return 8;
64+
}
65+
66+
/* truncate unsigned long constant that can't
67+
* be expressed in 32 bits, to test rewrite rule
68+
*/
69+
unsigned int ui = (unsigned int)17179869189ul; // 2^34 + 5
70+
if (ui != 5)
71+
return 9;
72+
73+
return 0;
74+
}

src/com/plasstech/lang/c/parser/Constant.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ public static Constant<Long> of(long value) {
1414
return new Constant<Long>(value, Type.LONG);
1515
}
1616

17-
public static Constant<UnsignedInteger> ofUnsignedInt(int value) {
18-
return new Constant<UnsignedInteger>(UnsignedInteger.fromIntBits(value), Type.UNSIGNED_INT);
17+
public static Constant<UnsignedInteger> ofUnsignedInt(String value) {
18+
return new Constant<UnsignedInteger>(UnsignedInteger.valueOf(value), Type.UNSIGNED_INT);
1919
}
2020

21-
public static Constant<UnsignedLong> ofUnsignedLong(long value) {
22-
return new Constant<UnsignedLong>(UnsignedLong.fromLongBits(value), Type.UNSIGNED_LONG);
21+
public static Constant<UnsignedLong> ofUnsignedLong(String value) {
22+
return new Constant<UnsignedLong>(UnsignedLong.valueOf(value), Type.UNSIGNED_LONG);
2323
}
2424

2525
@Override

0 commit comments

Comments
 (0)