]> granicus.if.org Git - clang/commitdiff
Disable VLA diagnostic in C++1y mode, and add some tests.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 20 Apr 2013 23:28:26 +0000 (23:28 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 20 Apr 2013 23:28:26 +0000 (23:28 +0000)
Still to do here:
  - we have a collection of syntactic accepts-invalids to diagnose
  - support non-PODs in VLAs, including dynamic initialization /
    destruction
  - runtime checks (and throw std::bad_array_length) for bad bound
  - support VLA capture by reference in lambdas
  - properly support VLAs in range-based for (don't recompute bound)

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179962 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaStmt.cpp
lib/Sema/SemaType.cpp
test/SemaCXX/cxx1y-array-runtime-bound.cpp [new file with mode: 0644]
test/SemaCXX/cxx98-compat-pedantic.cpp

index e6e67b454b0cd2eaf6abb9ef315fd5e9e4629454..0bdd041db95c7bf933af47efc551f4efa9890a3b 100644 (file)
@@ -78,6 +78,9 @@ def ext_vla : Extension<"variable length arrays are a C99 feature">,
   InGroup<VLAExtension>;
 def warn_vla_used : Warning<"variable length array used">,
   InGroup<VLA>, DefaultIgnore;
+def warn_cxx11_compat_array_of_runtime_bound : Warning<
+  "arrays of runtime bound are incompatible with C++ standards before C++1y">,
+  InGroup<CXXPre1yCompatPedantic>, DefaultIgnore;
 def err_vla_non_pod : Error<"variable length array of non-POD element type %0">;
 def err_vla_in_sfinae : Error<
   "variable length array cannot be formed during template argument deduction">;
index 88237b08b2bb5c49cd39bcab0db87dbde1756afe..c9408e23b043897289d45697a5c8bff504b0eae8 100644 (file)
@@ -1978,6 +1978,8 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
                                                  RangeLoc));
       else if (const VariableArrayType *VAT =
                dyn_cast<VariableArrayType>(UnqAT))
+        // FIXME: Need to build an OpaqueValueExpr for this rather than
+        // recomputing it!
         BoundExpr = VAT->getSizeExpr();
       else {
         // Can't be a DependentSizedArrayType or an IncompleteArrayType since
index 7169eeab9b9368a8b286ed0835b10551e3b67c07..699265c8b4611394acc1710b57d3a0758f41207b 100644 (file)
@@ -1572,6 +1572,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
   if (!getLangOpts().C99) {
     if (T->isVariableArrayType()) {
       // Prohibit the use of non-POD types in VLAs.
+      // FIXME: C++1y allows this.
       QualType BaseT = Context.getBaseElementType(T);
       if (!T->isDependentType() &&
           !BaseT.isPODType(Context) &&
@@ -1587,7 +1588,9 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
       }
       // Just extwarn about VLAs.
       else
-        Diag(Loc, diag::ext_vla);
+        Diag(Loc, getLangOpts().CPlusPlus1y
+                      ? diag::warn_cxx11_compat_array_of_runtime_bound
+                      : diag::ext_vla);
     } else if (ASM != ArrayType::Normal || Quals != 0)
       Diag(Loc,
            getLangOpts().CPlusPlus? diag::err_c99_array_usage_cxx
diff --git a/test/SemaCXX/cxx1y-array-runtime-bound.cpp b/test/SemaCXX/cxx1y-array-runtime-bound.cpp
new file mode 100644 (file)
index 0000000..323393d
--- /dev/null
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -std=c++1y %s -verify -pedantic-errors
+
+// FIXME: many diagnostics here say 'variably modified type'.
+//        catch this case and say 'array of runtime bound' instead.
+
+namespace std { struct type_info; }
+
+struct S {
+  int arr[__SIZE_MAX__ / 32];
+};
+S s[32]; // expected-error {{array is too large}}
+
+int n;
+int a[n]; // expected-error {{not allowed at file scope}}
+
+struct T {
+  int a[n]; // expected-error {{fields must have a constant size}}
+  static int b[n]; // expected-error {{not allowed at file scope}}
+};
+
+int g(int n, int a[n]);
+
+template<typename T> struct X {};
+template<int N, int[N]> struct Y {};
+template<int[n]> struct Z {}; // expected-error {{of variably modified type}}
+
+int f(int n) {
+  int arb[n]; // expected-note 3{{here}}
+  [arb] {} (); // expected-error {{cannot be captured}}
+
+  // FIXME: an array of runtime bound can be captured by reference.
+  [&arb] { // expected-error {{cannot be captured}}
+    // Capturing the array implicitly captures the bound, if we need it
+    // in a range-based for loop.
+    for (auto &n : arb) { } // expected-error {{cannot be captured}}
+  } ();
+
+  X<int[n]> x; // expected-error {{variably modified type}}
+
+  int arb_neg[-1]; // expected-error {{negative size}}
+  int arb_of_array[n][2];
+  int arr[3] = { 1, 2, 3, 4 }; // expected-error {{excess elements}}
+  char foo[4] = "fool"; // expected-error {{initializer-string for char array is too long}}
+
+  static int not_auto1[n]; // expected-error {{can not have 'static'}}
+  extern int not_auto2[n]; // expected-error {{can not have 'extern'}}
+  // FIXME: say 'thread_local' not 'static'.
+  thread_local int not_auto1[n]; // expected-error {{can not have 'static'}}
+
+  // FIXME: these should all be invalid.
+  auto &&ti1 = typeid(arb);
+  auto &&ti2 = typeid(int[n]);
+  auto &&so1 = sizeof(arb);
+  auto &&so2 = sizeof(int[n]);
+  auto *p = &arb;
+  decltype(arb) arb2;
+  int (*arbp)[n] = 0;
+  const int (&arbr)[n] = arbr; // expected-warning {{not yet bound}}
+  typedef int arbty[n];
+  int array_of_arb[2][n];
+
+  struct Dyn { Dyn() {} Dyn(int) {} ~Dyn() {} };
+
+  // FIXME: these should be valid.
+  int arb_dynamic[n] = { 1, 2, 3, 4 }; // expected-error {{may not be initialized}}
+  Dyn dyn[n]; // expected-error {{non-POD}}
+  Dyn dyn_init[n] = { 1, 2, 3, 4 }; // expected-error {{non-POD}}
+}
index 3bcf7c435d8237f7c7a565fdf287487be92585e7..208ea4ce923864cebb254170c8b77d97cc5483a9 100644 (file)
@@ -44,3 +44,8 @@ int k = 0b1001;
 #ifdef CXX1Y
 // expected-warning@-2 {{binary integer literals are incompatible with C++ standards before C++1y}}
 #endif
+
+void f(int n) { int a[n]; }
+#ifdef CXX1Y
+// expected-warning@-2 {{arrays of runtime bound are incompatible with C++ standards before C++1y}}
+#endif