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