xref: /llvm-project/clang/test/SemaCXX/c99-variable-length-array.cpp (revision ab870f3030fc288cd101905d730ef3425da5ac16)
1 // RUN: %clang_cc1 -fsyntax-only -verify -Wvla-extension %s
2 struct NonPOD {
3   NonPOD();
4 };
5 
6 struct NonPOD2 {
7   NonPOD np;
8 };
9 
10 struct POD {
11   int x;
12   int y;
13 };
14 
15 // expected-note@* 1+{{read of non-const variable}}
16 // expected-note@* 1+{{declared here}}
17 
18 // We allow VLAs of POD types, only.
19 void vla(int N) {
20   int array1[N]; // expected-warning{{variable length arrays are a C99 feature}}
21   POD array2[N]; // expected-warning{{variable length arrays are a C99 feature}}
22   NonPOD array3[N]; // expected-warning{{variable length arrays are a C99 feature}}
23   NonPOD2 array4[N][3]; // expected-warning{{variable length arrays are a C99 feature}}
24 }
25 
26 /// Warn about VLAs in templates.
27 template<typename T>
28 void vla_in_template(int N, T t) {
29   int array1[N]; // expected-warning{{variable length arrays are a C99 feature}}
30 }
31 
32 struct HasConstantValue {
33   static const unsigned int value = 2;
34 };
35 
36 struct HasNonConstantValue {
37   static unsigned int value;
38 };
39 
40 template<typename T>
41 void vla_in_template(T t) {
42   int array2[T::value]; // expected-warning{{variable length arrays are a C99 feature}}
43 }
44 
45 template void vla_in_template<HasConstantValue>(HasConstantValue);
46 template void vla_in_template<HasNonConstantValue>(HasNonConstantValue); // expected-note{{instantiation of}}
47 
48 template<typename T> struct X0 { };
49 
50 // Cannot use any variably-modified type with a template parameter or
51 // argument.
52 void inst_with_vla(int N) {
53   int array[N]; // expected-warning{{variable length arrays are a C99 feature}}
54   X0<__typeof__(array)> x0a; // expected-error{{variably modified type 'typeof (array)' (aka 'int [N]') cannot be used as a template argument}}
55 }
56 
57 template<typename T>
58 struct X1 {
59   template<int (&Array)[T::value]> // expected-error{{non-type template parameter of variably modified type 'int (&)[HasNonConstantValue::value]'}}  \
60   // expected-warning{{variable length arrays are a C99 feature}}
61   struct Inner {
62 
63   };
64 };
65 
66 X1<HasConstantValue> x1a;
67 X1<HasNonConstantValue> x1b; // expected-note{{in instantiation of}}
68 
69 // Template argument deduction does not allow deducing a size from a VLA.
70 // FIXME: This diagnostic should make it clear that the two 'N's are different entities!
71 template<typename T, unsigned N>
72 void accept_array(T (&array)[N]); // expected-note{{candidate template ignored: could not match 'T [N]' against 'int [N]'}}
73 
74 void test_accept_array(int N) {
75   int array[N]; // expected-warning{{variable length arrays are a C99 feature}}
76   accept_array(array); // expected-error{{no matching function for call to 'accept_array'}}
77 }
78 
79 // Variably-modified types cannot be used in local classes.
80 void local_classes(int N) {
81   struct X {
82     int size;
83     int array[N]; // expected-error{{fields must have a constant size: 'variable length array in structure' extension will never be supported}} \
84                   // expected-error{{reference to local variable 'N' declared in enclosing function 'local_classes'}} \
85                   // expected-warning{{variable length arrays are a C99 feature}}
86   };
87 }
88 
89 namespace PR7206 {
90   void f(int x) {
91     struct edge_info {
92       float left;
93       float right;
94     };
95     struct edge_info edgeInfo[x]; // expected-warning{{variable length arrays are a C99 feature}}
96   }
97 }
98 
99 namespace rdar8020206 {
100   template<typename T>
101   void f(int i) {
102     const unsigned value = i;
103     int array[value * i]; // expected-warning 2{{variable length arrays are a C99 feature}} expected-note 2{{initializer of 'value' is not a constant}}
104   }
105 
106   template void f<int>(int); // expected-note{{instantiation of}}
107 }
108 
109 namespace rdar8021385 {
110   typedef int my_int;
111   struct A { typedef int my_int; };
112   template<typename T>
113   struct B {
114     typedef typename T::my_int my_int;
115     void f0() {
116       int M = 4;
117       my_int a[M]; // expected-warning{{variable length arrays are a C99 feature}}
118     }
119   };
120   B<A> a;
121 }
122 
123 namespace PR8209 {
124   void f(int n) {
125     typedef int vla_type[n]; // expected-warning{{variable length arrays are a C99 feature}}
126     (void)new vla_type; // expected-error{{variably}}
127   }
128 }
129 
130 namespace rdar8733881 { // rdar://8733881
131 
132 static const int k_cVal3 = (int)(1000*0.2f);
133   int f() {
134     // Ok, fold to a constant size array as an extension.
135     char rgch[k_cVal3] = {0};
136   }
137 }
138 
139 namespace PR11744 {
140   template<typename T> int f(int n) {
141     T arr[3][n]; // expected-warning 3 {{variable length arrays are a C99 feature}}
142     return 3;
143   }
144   int test = f<int>(0); // expected-note {{instantiation of}}
145 }
146 
147 namespace pr18633 {
148   struct A1 {
149     static const int sz;
150     static const int sz2;
151   };
152   const int A1::sz2 = 11;
153   template<typename T>
154   void func () {
155     int arr[A1::sz]; // expected-warning{{variable length arrays are a C99 feature}} expected-note {{initializer of 'sz' is unknown}}
156   }
157   template<typename T>
158   void func2 () {
159     int arr[A1::sz2];
160   }
161   const int A1::sz = 12;
162   void func2() {
163     func<int>();
164     func2<int>();
165   }
166 }
167