118-const-expr.c (5201B)
1 /* Integer constant expressions (C99 §6.6). The four contexts that 2 * demand one: array bounds, enum initializers, case labels, and 3 * static/file-scope initializers. The accepted operand surface: 4 * 5 * integer / character literals, enum constants 6 * sizeof T / sizeof expr (non-VLA — operand not evaluated) 7 * unary + - ~ ! 8 * binary + - * / % << >> & | ^ 9 * compare < <= > >= == != 10 * logical && || 11 * ternary ?: 12 * cast to integer type 13 * parenthesization 14 * 15 * Floats, function calls, address-of, non-const identifiers, VLAs: 16 * out of scope. 17 */ 18 19 enum { 20 A = 1, 21 B = A + 1, /* arithmetic on enum-const */ 22 C = B << 2, /* shift */ 23 D = sizeof(int), /* sizeof in enum init */ 24 E = (1 < 2) ? 100 : 200, /* comparison + ternary */ 25 F = ~0, /* unary bnot */ 26 G = 'a', /* char constant promotes to int */ 27 H = (A && B) + (F || A), /* short-circuit logical: 1+1 = 2 */ 28 I = 1 + ~0, /* mixed unary + binary */ 29 }; 30 31 /* Array bounds at file scope. */ 32 int g_arr_sizeof[sizeof(int)]; /* 4 */ 33 int g_arr_arith[2 + 3 * 4]; /* 14 */ 34 int g_arr_shift[1 << 3]; /* 8 */ 35 int g_arr_enum[B + 1]; /* 3 */ 36 int g_arr_paren[(1 + 2) * (3 + 1)]; /* 12 */ 37 38 /* File-scope scalar initializers — must be constant expressions. */ 39 int g_init_arith = 1 + 2 * 3; /* 7 */ 40 int g_init_shift = (1 << 4) | 1; /* 17 */ 41 int g_init_sizeof = sizeof(long); /* 8 */ 42 int g_init_ternary = (5 > 3) ? 42 : 0; /* 42 */ 43 int g_init_enum = B * 10 + C; /* 2*10 + 8 = 28 */ 44 int g_init_cast = (int)(unsigned char)257; /* 257 & 0xff = 1 */ 45 int g_init_neg = -100 + 50; /* -50 */ 46 int g_init_char = 'A'; /* 65 */ 47 48 int test_enum_values(void) { 49 if (A != 1) return 1; 50 if (B != 2) return 2; 51 if (C != 8) return 3; 52 if (D != 4) return 4; 53 if (E != 100) return 5; 54 if (F != -1) return 6; 55 if (G != 97) return 7; 56 if (H != 2) return 8; 57 if (I != 0) return 9; 58 return 0; 59 } 60 61 int test_global_array_bounds(void) { 62 if (sizeof(g_arr_sizeof) != sizeof(int) * 4) return 1; 63 if (sizeof(g_arr_arith) != sizeof(int) * 14) return 2; 64 if (sizeof(g_arr_shift) != sizeof(int) * 8) return 3; 65 if (sizeof(g_arr_enum) != sizeof(int) * 3) return 4; 66 if (sizeof(g_arr_paren) != sizeof(int) * 12) return 5; 67 return 0; 68 } 69 70 int test_global_inits(void) { 71 if (g_init_arith != 7) return 1; 72 if (g_init_shift != 17) return 2; 73 if (g_init_sizeof != 8) return 3; 74 if (g_init_ternary != 42) return 4; 75 if (g_init_enum != 28) return 5; 76 if (g_init_cast != 1) return 6; 77 if (g_init_neg !=-50) return 7; 78 if (g_init_char != 65) return 8; 79 return 0; 80 } 81 82 int test_local_array_bounds(void) { 83 /* Block-scope arrays use the same const-expr grammar. */ 84 int a[2 + 3]; /* 5 */ 85 int b[sizeof(int) * 2]; /* 8 */ 86 int c[B + C]; /* 2 + 8 = 10 */ 87 if (sizeof(a) != sizeof(int) * 5) return 1; 88 if (sizeof(b) != sizeof(int) * 8) return 2; 89 if (sizeof(c) != sizeof(int) * 10) return 3; 90 return 0; 91 } 92 93 int test_static_local_init(void) { 94 /* Block-scope static needs a constant expression too. */ 95 static int s_arith = 100 - 1; 96 static int s_sizeof = sizeof(int *); 97 static int s_enum = C * D; /* 8 * 4 = 32 */ 98 static int s_logic = (1 || 0) && (2 < 3); /* 1 */ 99 if (s_arith != 99) return 1; 100 if (s_sizeof != 8) return 2; 101 if (s_enum != 32) return 3; 102 if (s_logic != 1) return 4; 103 return 0; 104 } 105 106 int test_case_labels(void) { 107 int r = 0; 108 int i; 109 for (i = 0; i < 5; i = i + 1) { 110 switch (i) { 111 case 0: r = r + 1; break; 112 case A: r = r + 2; break; /* 1: enum-const */ 113 case 1 + 1: r = r + 4; break; /* 2: arith */ 114 case sizeof(int)-1: r = r + 8; break; /* 3: sizeof+arith */ 115 case B << 1: r = r + 16; break; /* 4: shift */ 116 default: r = r + 64; break; 117 } 118 } 119 return r == (1 + 2 + 4 + 8 + 16) ? 0 : 1; 120 } 121 122 int test_char_in_const_expr(void) { 123 /* Character constant participates in const arithmetic. */ 124 static int diff = 'z' - 'a'; /* 25 */ 125 int x = 'a'; 126 switch (x) { 127 case 'a': break; 128 default: return 1; 129 } 130 if (diff != 25) return 2; 131 return 0; 132 } 133 134 int main(int argc, char **argv) { 135 int r; 136 if ((r = test_enum_values())) return 1 * 10 + r; 137 if ((r = test_global_array_bounds()))return 2 * 10 + r; 138 if ((r = test_global_inits())) return 3 * 10 + r; 139 if ((r = test_local_array_bounds())) return 4 * 10 + r; 140 if ((r = test_static_local_init())) return 5 * 10 + r; 141 if ((r = test_case_labels())) return 6 * 10 + r; 142 if ((r = test_char_in_const_expr())) return 7 * 10 + r; 143 return 0; 144 }