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