boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

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 }