1 2 /* This test case was originally written by Nicholas Nethercote. */ 3 4 // This test demonstrates some cases that the piggybacking algorithm 5 // doesn't handle but conceivably might, with more modifications. 6 // The instrumentation based algorithm handles them ok, though. 7 8 #include <assert.h> 9 #include <stdlib.h> 10 #include <stdio.h> 11 12 int x = 0; 13 14 typedef long long Long; 15 16 __attribute__((noinline)) int t1(void); 17 __attribute__((noinline)) int t2(void); 18 __attribute__((noinline)) int t3(void); 19 20 int main(void) 21 { 22 assert(4 == sizeof(int)); 23 assert(8 == sizeof(Long)); 24 25 x += t1(); 26 x += t2(); 27 x += t3(); 28 29 return x & 255; 30 } 31 32 __attribute__((noinline)) int t1(void) 33 { 34 // 64-bit undefined double. 35 double* ptr_to_undef_double = malloc(sizeof(double)); 36 double undef_double = *ptr_to_undef_double; 37 fprintf(stderr, "\nUndef 1 of 3 (64-bit FP)\n"); 38 return (undef_double < (double)123.45 ? 12 : 23); 39 } 40 41 __attribute__((noinline)) int t2(void) 42 { 43 // 32-bit undefined float. 44 float* ptr_to_undef_float = malloc(sizeof(float)); 45 float undef_float = *ptr_to_undef_float; 46 fprintf(stderr, "\nUndef 2 of 3 (32-bit FP)\n"); 47 return (undef_float < (float)234.56 ? 13 : 24); 48 } 49 50 __attribute__((noinline)) int t3(void) 51 { 52 // Stack, 32-bit, recently modified. 53 // Problem here is that we don't chase backwards through loads and 54 // stores. Ie. the variable is stored after it's been modified, then 55 // loaded again, so we don't see the unmodified version. 56 int modified_undef_stack_int; 57 modified_undef_stack_int++; 58 fprintf(stderr, "\nUndef 3 of 3 (int)\n"); 59 return (modified_undef_stack_int == 0x1234 ? 11 : 22); 60 } 61