xref: /llvm-project/clang/test/SemaCXX/c99-variable-length-array.cpp (revision 4b636a70d93d6518f11fbba2ffea1c1ee4182b76)
1 // RUN: %clang_cc1 -fsyntax-only -verify -Wvla %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 // We allow VLAs of POD types, only.
16 void vla(int N) {
17   int array1[N]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
18   POD array2[N]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
19   NonPOD array3[N]; // expected-error{{variable length array of non-POD element type 'NonPOD'}}
20   NonPOD2 array4[N][3]; // expected-error{{variable length array of non-POD element type 'NonPOD2'}}
21 }
22 
23 // We disallow VLAs in templates
24 template<typename T>
25 void vla_in_template(int N, T t) {
26   int array1[N]; // expected-error{{variable length array cannot be used in a template definition}}
27 }
28 
29 struct HasConstantValue {
30   static const unsigned int value = 2;
31 };
32 
33 struct HasNonConstantValue {
34   static unsigned int value;
35 };
36 
37 template<typename T>
38 void vla_in_template(T t) {
39   int array2[T::value]; // expected-error{{variable length array cannot be used in a template instantiation}}
40 }
41 
42 template void vla_in_template<HasConstantValue>(HasConstantValue);
43 template void vla_in_template<HasNonConstantValue>(HasNonConstantValue); // expected-note{{instantiation of}}
44 
45 template<typename T> struct X0 { };
46 
47 // Cannot use any variably-modified type with a template parameter or
48 // argument.
49 void inst_with_vla(int N) {
50   int array[N]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
51   X0<__typeof__(array)> x0a; // expected-error{{variably modified type 'typeof (array)' (aka 'int [N]') cannot be used as a template argument}}
52 }
53 
54 template<typename T>
55 struct X1 {
56   template<int (&Array)[T::value]> // expected-error{{variable length array cannot be used in a template instantiation}}
57   struct Inner {
58 
59   };
60 };
61 
62 X1<HasConstantValue> x1a;
63 X1<HasNonConstantValue> x1b; // expected-note{{in instantiation of}}
64 
65 // Template argument deduction does not allow deducing a size from a VLA.
66 template<typename T, unsigned N>
67 void accept_array(T (&array)[N]); // expected-note{{candidate template ignored: failed template argument deduction}}
68 
69 void test_accept_array(int N) {
70   int array[N]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
71   accept_array(array); // expected-error{{no matching function for call to 'accept_array'}}
72 }
73 
74 // Variably-modified types cannot be used in local classes.
75 void local_classes(int N) {
76   struct X {
77     int size;
78     int array[N]; // expected-error{{fields must have a constant size: 'variable length array in structure' extension will never be supported}} \
79                   // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
80   };
81 }
82 
83 namespace PR7206 {
84   void f(int x) {
85     struct edge_info {
86       float left;
87       float right;
88     };
89     struct edge_info edgeInfo[x]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
90   }
91 }
92