-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chapter 11 extra credit tests, fix undefined behavior in one test, ad…
…d invalid_labels to list of test subdirectories
- Loading branch information
Showing
15 changed files
with
252 additions
and
45 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,8 +7,8 @@ int incr_i(void){ | |
if (i == 1) { | ||
i++; | ||
++i; | ||
return 0; | ||
} | ||
return 0; | ||
} | ||
|
||
int decr_j(void) { | ||
|
15 changes: 15 additions & 0 deletions
15
tests/chapter_11/invalid_labels/extra_credit/switch_duplicate_cases_2.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
int switch_statement(int i) { | ||
switch((long) i) { | ||
case 100l: return 0; | ||
/* Even though 100l and 100 have different types, they have the same | ||
* value once converted to the type of the switch expression (long) | ||
* so they conflict | ||
*/ | ||
case 100: return 0; | ||
default: return 1; | ||
} | ||
} | ||
|
||
int main(void) { | ||
return switch_statement(100); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// Test bit shift operations on long integers; the main focus is making sure | ||
// we type check them correctly | ||
int main(void) { | ||
|
||
long l = 137438953472l; // 2^37 | ||
int shiftcount = 2; | ||
|
||
if (l >> shiftcount != 34359738368l /* 2 ^ 35 */) { | ||
return 1; | ||
} | ||
|
||
if (l << shiftcount != 549755813888 /* 2 ^ 39 */) { | ||
return 2; | ||
} | ||
|
||
// test w/ immediate right operand too | ||
if (l << 2 != 549755813888 /* 2 ^ 39 */) { | ||
return 3; | ||
} | ||
|
||
// use long as right shift operand | ||
// NOTE: we shouldn't perform usual arithmetic conversions here | ||
// (result has same type as left operand) but we won't be able to fully | ||
// validate that until chapter 12 | ||
long long_shiftcount = 3l; | ||
|
||
// declare some variables near i; we'll make sure they aren't clobbered by | ||
// bit shift operations | ||
int i_neighbor1 = 0; | ||
int i = -2147483645; // -2^31 + 3 | ||
int i_neighbor2 = 0; | ||
|
||
// should be -2^28 | ||
if (i >> long_shiftcount != -268435456) { | ||
return 4; | ||
} | ||
|
||
i = -1; | ||
if (i >> 10l != -1) { | ||
return 5; | ||
} | ||
|
||
// make sure we didn't shift any bits into i's neighbors | ||
if (i_neighbor1) { | ||
return 6; | ||
} | ||
|
||
if (i_neighbor2) { | ||
return 7; | ||
} | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,72 @@ | ||
/* Test bitwise &, |, and ^ operations on long integers. | ||
* Make sure we: | ||
* - promote both operands to a common type; | ||
* - actually perform quadword (not longword) operations | ||
* - use appropriate rewrite rules where one operand is an | ||
* immediate that can't fit in a signed 32-bit integer | ||
*/ | ||
int main(void) { | ||
/* A long integer where the upper 32 bits are 0 and lower 32 bits are 1 */ | ||
long lower_32_bits_set = 4294967295; // 2^32 - 1 | ||
|
||
/* A long integer where upper 32 bits are 1 and lower 32 bits are 0 */ | ||
long upper_32_bits_set = -1 - lower_32_bits_set; | ||
|
||
/* Casting a long to an int and back is equivalent to either: | ||
* - setting all upper bits to 1, if bit 32 is 1 (meaning the truncated int is negative) | ||
* or, | ||
* - setting all uppers bits to 0, if bit 32 is 0 (meaning the truncated int is positive) | ||
* Additionally, i & -1 == i for any signed integer i, whether i is a long or an int. | ||
* The loop below validates that these properties holds for a sample of | ||
* roughly 100,000,000 longs. | ||
*/ | ||
for (long l = 17179869184; l > 2147483648; l = l - 150) { | ||
|
||
int i = (int) l; | ||
if (i >= 0) { | ||
/* use bitwise "and" to zero out upper bits */ | ||
if ((l & lower_32_bits_set) != i) | ||
return 1; | ||
} else { | ||
/* use bitwise "or" to set upper bits */ | ||
if ((l | upper_32_bits_set) != i) | ||
return 2; | ||
} | ||
|
||
/* every bit is set in -1, so l & -1 == l */ | ||
if ((l & -1) != l) | ||
return 3; | ||
} | ||
return 0; // success | ||
// basic tests to make sure we're performing quadword operations | ||
long l1 = 71777214294589695l; // 0x00ff00ff00ff00ff | ||
long l2 = -4294967296; // -2^32; upper 32 bits are 1, lower 32 bits are 0 | ||
|
||
if ((l1 & l2) != 71777214277877760l /* 0x00ff00ff00000000 */) { | ||
return 1; | ||
} | ||
|
||
if ((l1 | l2) != -4278255361 /* 0xffffffff00ff00ff */) { | ||
return 2; | ||
} | ||
|
||
if ((l1 ^ l2) != -71777218556133121 /* 0x0ff00ff0000ff00ff */) { | ||
return 3; | ||
} | ||
|
||
/* Rewrite rules: andq $IMM, m64 doesn't work if $IMM can't fit | ||
* in signed 32-bit int. Ditto for orq and xorq */ | ||
if ((-1l & 34359738368l) != 34359738368l) { // 34359738368 == 2^35 | ||
return 4; | ||
} | ||
|
||
if ((0l | 34359738368l) != 34359738368l) { | ||
return 5; | ||
} | ||
|
||
// 137438953472 == 2^37; | ||
if ((34359738368l ^ 137438953472l) != 171798691840l) { | ||
return 6; | ||
} | ||
|
||
/* Typechecking: promote both operands to common type */ | ||
long l = 4611686018427387903l; // 0x3fffffffffffffff | ||
// if we try to use i in longword bitwise op without sign-extending it | ||
// first, we may try to read neighboring values l and i2 | ||
int i = -1073741824; // 0b1100....0, or 0xc0000000 | ||
int i2 = -1; | ||
|
||
// 1. sign-extend i to 64 bits; upper 32 bits are all 1s | ||
// 2. take bitwise AND of sign-extended value with l | ||
// 3. result is 3fffffffc0000000; upper bits match l, lower bits match i | ||
if ((i & l) != 4611686017353646080l) { | ||
return 7; | ||
} | ||
|
||
// i is sign-extended so upper bytes are 1s; lower bytes of l are 1s | ||
if ((l | i) != -1) { | ||
return 8; | ||
} | ||
|
||
// 0x3fffffffffffffff ^ 0xffffffffc0000000 = 0xc00000003fffffff | ||
if ((l ^ i) != -4611686017353646081) { | ||
return 9; | ||
} | ||
|
||
// 1. sign extend i2; value is still -1 | ||
// 2. XOR result w/ 0x3fffffffffffffff (as a constant this time) | ||
// 3. result is the same as taking bitwise complement of 0x3fffffffffffffff | ||
if ((i2 ^ 4611686018427387903l) != ~4611686018427387903l) { | ||
return 10; | ||
} | ||
|
||
return 0; // success | ||
} |
38 changes: 37 additions & 1 deletion
38
tests/chapter_11/valid/extra_credit/compound_assign_to_int.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,47 @@ | ||
int main(void) { | ||
int i = -20; | ||
int b = 2147483647; | ||
int c = -5000000; | ||
|
||
/* This statement is evaluated as follows: | ||
* 1. sign-extend i to a long with value -20 | ||
* 2. add this long to 2147483648, resulting in the long 2147483628, | ||
* 3. convert this to an int with value 2147483628 (this value | ||
* can be represented as an int) | ||
*/ | ||
i += 2147483648l; | ||
return (i == 2147483628); | ||
|
||
// make sure we got the right answer and didn't clobber b | ||
if (i != 2147483628) { | ||
return 1; | ||
} | ||
if (b != 2147483647) { | ||
return 2; | ||
} | ||
|
||
// b /= -2^35 + 1 | ||
// if we try to perform int (rather than long) | ||
// division, we'll interpret this value as 1 and | ||
// b's value won't change. | ||
b /= -34359738367l; | ||
if (b) { // b's value should be 0 | ||
return 3; | ||
} | ||
|
||
// make sure we didn't clobber i or c | ||
if (i != 2147483628) { | ||
return 4; | ||
} | ||
if (c != -5000000) { | ||
return 5; | ||
} | ||
|
||
// this result will be outside the range of int; we'll | ||
// convert it to int in the usual implementation-defined way | ||
c *= 10000l; | ||
if (c != 1539607552) { | ||
return 6; | ||
} | ||
|
||
return 0; | ||
} |
11 changes: 7 additions & 4 deletions
11
tests/chapter_11/valid/extra_credit/compound_assign_to_long.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,10 @@ | ||
int main(void) { | ||
long l = -1; | ||
long l = -34359738368l; // -2^35 | ||
int i = -10; | ||
/* We should convert i to a long, then add it to l */ | ||
l += i; | ||
return (l == -11); | ||
/* We should convert i to a long, then subtract from l */ | ||
l -= i; | ||
if (l != -34359738358l) { | ||
return 1; | ||
} | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// make sure we support prefix and postfix ++/-- on long variables | ||
int main(void) { | ||
long x = -9223372036854775807l; | ||
|
||
// postfix ++ | ||
if (x++ != -9223372036854775807l) { | ||
return 1; | ||
} | ||
if (x != -9223372036854775806l) { | ||
return 2; | ||
} | ||
|
||
// prefix -- | ||
if (--x != -9223372036854775807l) { | ||
return 3; | ||
} | ||
if (x != -9223372036854775807l) { | ||
return 4; | ||
} | ||
|
||
return 0; // success | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,8 @@ | ||
/* Make sure we use arithmetic rather than logical right shift */ | ||
/* Make sure we use arithmetic rather than logical right shift. | ||
* NOTE: right bitshift of negative value is implementation-defined; | ||
* we follow GCC and use sign extension | ||
* (see https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html) | ||
* */ | ||
int main(void) { | ||
return -5 >> 30; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,5 +3,6 @@ | |
#endif | ||
|
||
int main(void) { | ||
// & has lower precedence than == | ||
return 5 & 7 == 5; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#ifdef SUPPRESS_WARNINGS | ||
#pragma GCC diagnostic ignored "-Wparentheses" | ||
#endif | ||
|
||
int main(void) { | ||
// | has lower precedence than != | ||
return 5 | 7 != 5; | ||
} |
Oops, something went wrong.