Home | History | Annotate | Download | only in SemaCXX
      1 // RUN: %clang_cc1 -verify %s
      2 
      3 int foo() {
      4   int x[2]; // expected-note 4 {{array 'x' declared here}}
      5   int y[2]; // expected-note 2 {{array 'y' declared here}}
      6   int z[1]; // expected-note {{array 'z' declared here}}
      7   int w[1][1]; // expected-note {{array 'w' declared here}}
      8   int v[1][1][1]; // expected-note {{array 'v' declared here}}
      9   int *p = &y[2]; // no-warning
     10   (void) sizeof(x[2]); // no-warning
     11   y[2] = 2; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
     12   z[1] = 'x'; // expected-warning {{array index 1 is past the end of the array (which contains 1 element)}}
     13   w[0][2] = 0; // expected-warning {{array index 2 is past the end of the array (which contains 1 element)}}
     14   v[0][0][2] = 0; // expected-warning {{array index 2 is past the end of the array (which contains 1 element)}}
     15   return x[2] +  // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
     16          y[-1] + // expected-warning {{array index -1 is before the beginning of the array}}
     17          x[sizeof(x)] +  // expected-warning {{array index 8 is past the end of the array (which contains 2 elements)}}
     18          x[sizeof(x) / sizeof(x[0])] +  // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
     19          x[sizeof(x) / sizeof(x[0]) - 1] + // no-warning
     20          x[sizeof(x[2])]; // expected-warning {{array index 4 is past the end of the array (which contains 2 elements)}}
     21 }
     22 
     23 // This code example tests that -Warray-bounds works with arrays that
     24 // are template parameters.
     25 template <char *sz> class Qux {
     26   bool test() { return sz[0] == 'a'; }
     27 };
     28 
     29 void f1(int a[1]) {
     30   int val = a[3]; // no warning for function argumnet
     31 }
     32 
     33 void f2(const int (&a)[2]) { // expected-note {{declared here}}
     34   int val = a[3];  // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}}
     35 }
     36 
     37 void test() {
     38   struct {
     39     int a[0];
     40   } s2;
     41   s2.a[3] = 0; // no warning for 0-sized array
     42 
     43   union {
     44     short a[2]; // expected-note 4 {{declared here}}
     45     char c[4];
     46   } u;
     47   u.a[3] = 1; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}}
     48   u.c[3] = 1; // no warning
     49   short *p = &u.a[2]; // no warning
     50   p = &u.a[3]; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}}
     51   *(&u.a[2]) = 1; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
     52   *(&u.a[3]) = 1; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}}
     53   *(&u.c[3]) = 1; // no warning
     54 
     55   const int const_subscript = 3;
     56   int array[2]; // expected-note {{declared here}}
     57   array[const_subscript] = 0;  // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}}
     58 
     59   int *ptr;
     60   ptr[3] = 0; // no warning for pointer references
     61   int array2[] = { 0, 1, 2 }; // expected-note 2 {{declared here}}
     62 
     63   array2[3] = 0; // expected-warning {{array index 3 is past the end of the array (which contains 3 elements)}}
     64   array2[2+2] = 0; // expected-warning {{array index 4 is past the end of the array (which contains 3 elements)}}
     65 
     66   const char *str1 = "foo";
     67   char c1 = str1[5]; // no warning for pointers
     68 
     69   const char str2[] = "foo"; // expected-note {{declared here}}
     70   char c2 = str2[5]; // expected-warning {{array index 5 is past the end of the array (which contains 4 elements)}}
     71 
     72   int (*array_ptr)[2];
     73   (*array_ptr)[3] = 1; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}}
     74 }
     75 
     76 template <int I> struct S {
     77   char arr[I]; // expected-note 3 {{declared here}}
     78 };
     79 template <int I> void f() {
     80   S<3> s;
     81   s.arr[4] = 0; // expected-warning 2 {{array index 4 is past the end of the array (which contains 3 elements)}}
     82   s.arr[I] = 0; // expected-warning {{array index 5 is past the end of the array (which contains 3 elements)}}
     83 }
     84 
     85 void test_templates() {
     86   f<5>(); // expected-note {{in instantiation}}
     87 }
     88 
     89 #define SIZE 10
     90 #define ARR_IN_MACRO(flag, arr, idx) flag ? arr[idx] : 1
     91 
     92 int test_no_warn_macro_unreachable() {
     93   int arr[SIZE]; // expected-note {{array 'arr' declared here}}
     94   return ARR_IN_MACRO(0, arr, SIZE) + // no-warning
     95          ARR_IN_MACRO(1, arr, SIZE); // expected-warning{{array index 10 is past the end of the array (which contains 10 elements)}}
     96 }
     97 
     98 // This exhibited an assertion failure for a 32-bit build of Clang.
     99 int test_pr9240() {
    100   short array[100]; // expected-note {{array 'array' declared here}}
    101   return array[(unsigned long long) 100]; // expected-warning {{array index 100 is past the end of the array (which contains 100 elements)}}
    102 }
    103 
    104 // PR 9284 - a template parameter can cause an array bounds access to be
    105 // infeasible.
    106 template <bool extendArray>
    107 void pr9284() {
    108     int arr[3 + (extendArray ? 1 : 0)];
    109 
    110     if (extendArray)
    111         arr[3] = 42; // no-warning
    112 }
    113 
    114 template <bool extendArray>
    115 void pr9284b() {
    116     int arr[3 + (extendArray ? 1 : 0)]; // expected-note {{array 'arr' declared here}}
    117 
    118     if (!extendArray)
    119         arr[3] = 42; // expected-warning{{array index 3 is past the end of the array (which contains 3 elements)}}
    120 }
    121 
    122 void test_pr9284() {
    123     pr9284<true>();
    124     pr9284<false>();
    125     pr9284b<true>();
    126     pr9284b<false>(); // expected-note{{in instantiation of function template specialization 'pr9284b<false>' requested here}}
    127 }
    128 
    129 int test_pr9296() {
    130     int array[2];
    131     return array[true]; // no-warning
    132 }
    133 
    134 int test_sizeof_as_condition(int flag) {
    135   int arr[2] = { 0, 0 }; // expected-note {{array 'arr' declared here}}
    136   if (flag)
    137     return sizeof(char) != sizeof(char) ? arr[2] : arr[1];
    138   return sizeof(char) == sizeof(char) ? arr[2] : arr[1]; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
    139 }
    140 
    141 void test_switch() {
    142   switch (4) {
    143     case 1: {
    144       int arr[2];
    145       arr[2] = 1; // no-warning
    146       break;
    147     }
    148     case 4: {
    149       int arr[2]; // expected-note {{array 'arr' declared here}}
    150       arr[2] = 1; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
    151       break;
    152     }
    153     default: {
    154       int arr[2];
    155       arr[2] = 1; // no-warning
    156       break;
    157     }
    158   }
    159 }
    160 
    161 // Test nested switch statements.
    162 enum enumA { enumA_A, enumA_B, enumA_C, enumA_D, enumA_E };
    163 enum enumB { enumB_X, enumB_Y, enumB_Z };
    164 static enum enumB myVal = enumB_X;
    165 void test_nested_switch() {
    166   switch (enumA_E) { // expected-warning {{no case matching constant}}
    167     switch (myVal) { // expected-warning {{enumeration values 'enumB_X' and 'enumB_Z' not handled in switch}}
    168       case enumB_Y: ;
    169     }
    170   }
    171 }
    172 
    173 // Test that if all the values of an enum covered, that the 'default' branch
    174 // is unreachable.
    175 enum Values { A, B, C, D };
    176 void test_all_enums_covered(enum Values v) {
    177   int x[2];
    178   switch (v) {
    179   case A: return;
    180   case B: return;
    181   case C: return;
    182   case D: return;
    183   }
    184   x[2] = 0; // no-warning
    185 }
    186 
    187 namespace tailpad {
    188   struct foo {
    189     char c1[1]; // expected-note {{declared here}}
    190     int x;
    191     char c2[1];
    192   };
    193 
    194   class baz {
    195    public:
    196     char c1[1]; // expected-note {{declared here}}
    197     int x;
    198     char c2[1];
    199   };
    200 
    201   char bar(struct foo *F, baz *B) {
    202     return F->c1[3] + // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}}
    203            F->c2[3] + // no warning, foo could have tail padding allocated.
    204            B->c1[3] + // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}}
    205            B->c2[3]; // no warning, baz could have tail padding allocated.
    206   }
    207 }
    208 
    209 namespace metaprogramming {
    210 #define ONE 1
    211   struct foo { char c[ONE]; }; // expected-note {{declared here}}
    212   template <int N> struct bar { char c[N]; }; // expected-note {{declared here}}
    213 
    214   char test(foo *F, bar<1> *B) {
    215     return F->c[3] + // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}}
    216            B->c[3]; // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}}
    217   }
    218 }
    219 
    220 void bar(int x) {}
    221 int test_more() {
    222   int foo[5]; // expected-note 5 {{array 'foo' declared here}}
    223   bar(foo[5]); // expected-warning {{array index 5 is past the end of the array (which contains 5 elements)}}
    224   ++foo[5]; // expected-warning {{array index 5 is past the end of the array (which contains 5 elements)}}
    225   if (foo[6]) // expected-warning {{array index 6 is past the end of the array (which contains 5 elements)}}
    226     return --foo[6]; // expected-warning {{array index 6 is past the end of the array (which contains 5 elements)}}
    227   else
    228     return foo[5]; // expected-warning {{array index 5 is past the end of the array (which contains 5 elements)}}
    229 }
    230 
    231 void test_pr10771() {
    232     double foo[4096];  // expected-note {{array 'foo' declared here}}
    233 
    234     ((char*)foo)[sizeof(foo) - 1] = '\0';  // no-warning
    235     *(((char*)foo) + sizeof(foo) - 1) = '\0';  // no-warning
    236 
    237     ((char*)foo)[sizeof(foo)] = '\0';  // expected-warning {{array index 32768 is past the end of the array (which contains 32768 elements)}}
    238 
    239     // TODO: This should probably warn, too.
    240     *(((char*)foo) + sizeof(foo)) = '\0';  // no-warning
    241 }
    242 
    243 int test_pr11007_aux(const char * restrict, ...);
    244 
    245 // Test checking with varargs.
    246 void test_pr11007() {
    247   double a[5]; // expected-note {{array 'a' declared here}}
    248   test_pr11007_aux("foo", a[1000]); // expected-warning {{array index 1000 is past the end of the array}}
    249 }
    250 
    251 void test_rdar10916006(void)
    252 {
    253 	int a[128]; // expected-note {{array 'a' declared here}}
    254 	a[(unsigned char)'\xA1'] = 1; // expected-warning {{array index 161 is past the end of the array}}
    255 }
    256