Implement support for variable length arrays in C++. VLAs are limited
in several important ways:

  - VLAs of non-POD types are not permitted.
  - VLAs cannot be used in conjunction with C++ templates.

These restrictions are intended to keep VLAs out of the parts of the
C++ type system where they cause the most trouble. Fixes PR5678 and
<rdar://problem/8013618>.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104443 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CodeGenCXX/c99-variable-length-array.cpp b/test/CodeGenCXX/c99-variable-length-array.cpp
new file mode 100644
index 0000000..66c14ff
--- /dev/null
+++ b/test/CodeGenCXX/c99-variable-length-array.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+struct X {
+  X();
+  ~X();
+};
+
+struct Y {
+  Y();
+  ~Y();
+};
+
+// CHECK: define void @_Z1fiPPKc(
+void f(int argc, const char* argv[]) {
+  // CHECK: call void @_ZN1XC1Ev
+  X x;
+  // CHECK: call i8* @llvm.stacksave(
+  const char *argv2[argc];
+  // CHECK: call void @_ZN1YC1Ev
+  Y y;
+  for (int i = 0; i != argc; ++i)
+    argv2[i] = argv[i];
+
+  // CHECK: call void @_ZN1YD1Ev
+  // CHECK: call void @llvm.stackrestore
+  // CHECK: call void @_ZN1XD1Ev
+  // CHECK: ret void
+}
diff --git a/test/Sema/c89.c b/test/Sema/c89.c
index 8a9e622..038f7e5 100644
--- a/test/Sema/c89.c
+++ b/test/Sema/c89.c
@@ -61,7 +61,7 @@
 void foo(void) {}
 
 /* PR2759 */
-void test10 (int x[*]); /* expected-warning {{use of C99-specific array features}} */
+void test10 (int x[*]); /* expected-warning {{variable length arrays are a C99 feature, accepted as an extension}} */
 void test11 (int x[static 4]); /* expected-warning {{use of C99-specific array features}} */
 
 void test12 (int x[const 4]) { /* expected-warning {{use of C99-specific array features}} */
diff --git a/test/SemaCXX/c99-variable-length-array.cpp b/test/SemaCXX/c99-variable-length-array.cpp
new file mode 100644
index 0000000..a792951
--- /dev/null
+++ b/test/SemaCXX/c99-variable-length-array.cpp
@@ -0,0 +1,80 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+struct NonPOD {
+  NonPOD();
+};
+
+struct NonPOD2 {
+  NonPOD np;
+};
+
+struct POD {
+  int x;
+  int y;
+};
+
+// We allow VLAs of POD types, only.
+void vla(int N) {
+  int array1[N];
+  POD array2[N];
+  NonPOD array3[N]; // expected-error{{variable length array of non-POD element type 'NonPOD'}}
+  NonPOD2 array4[N][3]; // expected-error{{variable length array of non-POD element type 'NonPOD2'}}
+}
+
+// We disallow VLAs in templates
+template<typename T>
+void vla_in_template(int N, T t) {
+  int array1[N]; // expected-error{{variable length array cannot be used in a template definition}}
+}
+
+struct HasConstantValue {
+  static const unsigned int value = 2;
+};
+
+struct HasNonConstantValue {
+  static unsigned int value;
+};
+
+template<typename T>
+void vla_in_template(T t) {
+  int array2[T::value]; // expected-error{{variable length array cannot be used in a template instantiation}}
+}
+
+template void vla_in_template<HasConstantValue>(HasConstantValue);
+template void vla_in_template<HasNonConstantValue>(HasNonConstantValue); // expected-note{{instantiation of}}
+
+template<typename T> struct X0 { };
+
+// Cannot use any variably-modified type with a template parameter or
+// argument.
+void inst_with_vla(int N) {
+  int array[N];
+  X0<__typeof__(array)> x0a; // expected-error{{variably modified type 'typeof (array)' (aka 'int [N]') cannot be used as a template argument}}
+}
+
+template<typename T>
+struct X1 {
+  template<int (&Array)[T::value]> // expected-error{{variable length array cannot be used in a template instantiation}}
+  struct Inner {
+    
+  };
+};
+
+X1<HasConstantValue> x1a;
+X1<HasNonConstantValue> x1b; // expected-note{{in instantiation of}}
+
+// Template argument deduction does not allow deducing a size from a VLA.
+template<typename T, unsigned N>
+void accept_array(T (&array)[N]); // expected-note{{candidate template ignored: failed template argument deduction}}
+
+void test_accept_array(int N) {
+  int array[N];
+  accept_array(array); // expected-error{{no matching function for call to 'accept_array'}}
+}
+
+// Variably-modified types cannot be used in local classes.
+void local_classes(int N) {
+  struct X {
+    int size;
+    int array[N]; // expected-error{{fields must have a constant size: 'variable length array in structure' extension will never be supported}}
+  };
+}
diff --git a/test/SemaCXX/c99.cpp b/test/SemaCXX/c99.cpp
index f4c3639..b0bd45d 100644
--- a/test/SemaCXX/c99.cpp
+++ b/test/SemaCXX/c99.cpp
@@ -1,8 +1,3 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
-
-void f0(int i) {
-  char array[i]; // expected-error{{variable length arrays}}
-}
-
 void f1(int i[static 5]) { // expected-error{{C99}}
 }
diff --git a/test/SemaCXX/offsetof.cpp b/test/SemaCXX/offsetof.cpp
index 47c3f22..639d7fa 100644
--- a/test/SemaCXX/offsetof.cpp
+++ b/test/SemaCXX/offsetof.cpp
@@ -26,7 +26,7 @@
 // Constant and non-constant offsetof expressions
 void test_ice(int i) {
   int array0[__builtin_offsetof(HasArray, array[5])];
-  int array1[__builtin_offsetof(HasArray, array[i])]; // expected-error{{variable length arrays are not permitted in C++}}
+  int array1[__builtin_offsetof(HasArray, array[i])];
 }
 
 // Bitfields
diff --git a/test/SemaObjCXX/vla.mm b/test/SemaObjCXX/vla.mm
index 9c6fc54..d6da1c0 100644
--- a/test/SemaObjCXX/vla.mm
+++ b/test/SemaObjCXX/vla.mm
@@ -6,7 +6,7 @@
 @end
 
 void test(Data *d) {
-  char buffer[[d length]]; // expected-error{{variable length arrays are not permitted in C++}}
+  char buffer[[d length]];
   [d getData:buffer];
 }
 
diff --git a/test/SemaTemplate/instantiate-declref-ice.cpp b/test/SemaTemplate/instantiate-declref-ice.cpp
index e88b494..0f3c08b 100644
--- a/test/SemaTemplate/instantiate-declref-ice.cpp
+++ b/test/SemaTemplate/instantiate-declref-ice.cpp
@@ -31,5 +31,4 @@
 template<typename T>
 const unsigned X1<T>::value = sizeof(T);
 
-int array3[X1<int>::value == sizeof(int)? 1 : -1]; // expected-error{{variable length arrays are not permitted in C++}} \
-// expected-error{{variable length array declaration not allowed at file scope}}
+int array3[X1<int>::value == sizeof(int)? 1 : -1]; // expected-error{{variable length array declaration not allowed at file scope}}