rsmith updated this revision to Diff 298702.
rsmith marked 2 inline comments as done.
rsmith added a comment.

- Update User's Manual to more accurately describe GNU mode and


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D89523/new/

https://reviews.llvm.org/D89523

Files:
  clang/docs/UsersManual.rst
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/CXX/basic/basic.types/p10.cpp
  clang/test/CXX/drs/dr3xx.cpp
  clang/test/CodeGen/vla.c
  clang/test/Misc/warning-flags.c
  clang/test/PCH/cxx-constexpr.cpp
  clang/test/Profile/misexpect-switch-default.c
  clang/test/Profile/misexpect-switch-nonconst.c
  clang/test/Profile/misexpect-switch-only-default-case.c
  clang/test/Profile/misexpect-switch.c
  clang/test/Sema/builtin-assume.c
  clang/test/Sema/builtins.c
  clang/test/Sema/complex-int.c
  clang/test/Sema/const-eval-64.c
  clang/test/Sema/const-eval.c
  clang/test/Sema/darwin-align-cast.c
  clang/test/Sema/decl-in-prototype.c
  clang/test/Sema/gnu-flags.c
  clang/test/Sema/i-c-e.c
  clang/test/Sema/offsetof-64.c
  clang/test/Sema/struct-decl.c
  clang/test/Sema/typedef-variable-type.c
  clang/test/Sema/vla.c
  clang/test/SemaCXX/anonymous-struct.cpp
  clang/test/SemaCXX/constant-expression.cpp
  clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp
  clang/test/SemaCXX/i-c-e-cxx.cpp
  clang/test/SemaObjC/gcc-cast-ext.m

Index: clang/test/SemaObjC/gcc-cast-ext.m
===================================================================
--- clang/test/SemaObjC/gcc-cast-ext.m
+++ clang/test/SemaObjC/gcc-cast-ext.m
@@ -11,7 +11,7 @@
 
 // GCC allows pointer expressions in integer constant expressions.
 struct {
-  char control[((int)(char *)2)];
+  char control[((int)(char *)2)]; // expected-warning {{extension}}
 } xx;
 
 @implementation PBXDocBookmark // expected-warning {{method definition for 'autorelease' not found}}\
Index: clang/test/SemaCXX/i-c-e-cxx.cpp
===================================================================
--- clang/test/SemaCXX/i-c-e-cxx.cpp
+++ clang/test/SemaCXX/i-c-e-cxx.cpp
@@ -80,7 +80,7 @@
 #endif
 
 int PR8836test[(__typeof(sizeof(int)))&reinterpret_cast<const volatile char&>((((PR8836*)0)->a))];
-// expected-warning@-1 {{folded to constant array as an extension}}
+// expected-warning@-1 0-1{{C99 feature}} expected-warning@-1 {{folded to constant array as an extension}}
 // expected-note@-2 {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}}
 
 const int nonconst = 1.0;
@@ -89,7 +89,7 @@
 #endif
 int arr[nonconst];
 #if __cplusplus <= 199711L
-// expected-warning@-2 {{folded to constant array as an extension}}
+// expected-warning@-2 0-1{{C99 feature}} expected-warning@-2 {{folded to constant array as an extension}}
 // expected-note@-3 {{initializer of 'nonconst' is not a constant expression}}
 #endif
 
Index: clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp
===================================================================
--- clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp
+++ clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp
@@ -120,7 +120,7 @@
   extern "C" int strncmp(const char *, const char *, decltype(sizeof(0))) noexcept;
 
   // Check we recognized both as builtins.
-  typedef int arr[strcmp("bar", "foo") + 4 * strncmp("foo", "bar", 4)];
+  typedef int arr[strcmp("bar", "foo") + 4 * strncmp("foo", "bar", 4)]; // expected-warning {{variable length array}}
   typedef int arr[3];
 }
 
Index: clang/test/SemaCXX/constant-expression.cpp
===================================================================
--- clang/test/SemaCXX/constant-expression.cpp
+++ clang/test/SemaCXX/constant-expression.cpp
@@ -110,7 +110,7 @@
 const int recurse2 = recurse1; // expected-note {{here}}
 const int recurse1 = 1;
 int array1[recurse1]; // ok
-int array2[recurse2]; // expected-warning {{variable length array}} expected-warning {{integer constant expression}} expected-note {{initializer of 'recurse2' is not a constant expression}}
+int array2[recurse2]; // expected-warning 2{{variable length array}} expected-note {{initializer of 'recurse2' is not a constant expression}}
 
 namespace FloatConvert {
   typedef int a[(int)42.3];
Index: clang/test/SemaCXX/anonymous-struct.cpp
===================================================================
--- clang/test/SemaCXX/anonymous-struct.cpp
+++ clang/test/SemaCXX/anonymous-struct.cpp
@@ -131,6 +131,9 @@
   typedef struct { // expected-error {{unsupported}}
     enum X {};
     int arr[&f<X> ? 1 : 2];
+#if __cplusplus < 201103L
+    // expected-warning@-2 {{folded to constant}}
+#endif
   } C; // expected-note {{by this typedef}}
 }
 
Index: clang/test/Sema/vla.c
===================================================================
--- clang/test/Sema/vla.c
+++ clang/test/Sema/vla.c
@@ -53,7 +53,7 @@
 int (*pr2044c(void))[pr2044b]; // expected-error {{variably modified type}}
 
 const int f5_ci = 1;
-void f5() { char a[][f5_ci] = {""}; } // expected-warning {{variable length array folded to constant array as an extension}}
+void f5() { char a[][f5_ci] = {""}; } // expected-error {{variable-sized object may not be initialized}}
 
 // PR5185
 void pr5185(int a[*]);
@@ -89,3 +89,14 @@
   // Not illegal in C, program _might_ be well formed if size == 3.
   int (*p4)[2][size][3][4][5] = array;
 }
+
+void pr44406() {
+  goto L; // expected-error {{cannot jump}}
+  int z[(int)(1.0 * 2)]; // expected-note {{bypasses initialization of variable length array}}
+L:;
+}
+
+const int pr44406_a = 32;
+typedef struct {
+  char c[pr44406_a]; // expected-warning {{folded to constant array as an extension}}
+} pr44406_s;
Index: clang/test/Sema/typedef-variable-type.c
===================================================================
--- clang/test/Sema/typedef-variable-type.c
+++ clang/test/Sema/typedef-variable-type.c
@@ -1,8 +1,8 @@
 // RUN: %clang_cc1 %s -verify -fsyntax-only -pedantic -Wno-typedef-redefinition -std=c99
 
 // Make sure we accept a single typedef
-typedef int (*a)[!.0]; // expected-warning{{size of static array must be an integer constant expression}}
+typedef int (*a)[!.0]; // expected-warning{{folded to constant array}}
 
 // And make sure we accept identical redefinitions in system headers
 // (The test uses -Wno-typedef-redefinition to simulate this.)
-typedef int (*a)[!.0]; // expected-warning{{size of static array must be an integer constant expression}}
+typedef int (*a)[!.0]; // expected-warning{{folded to constant array}}
Index: clang/test/Sema/struct-decl.c
===================================================================
--- clang/test/Sema/struct-decl.c
+++ clang/test/Sema/struct-decl.c
@@ -5,8 +5,8 @@
 };
 
 struct foo {
-  char name[(int)&((struct bar *)0)->n];
-  char name2[(int)&((struct bar *)0)->n - 1]; //expected-error{{'name2' declared as an array with a negative size}}
+  char name[(int)&((struct bar *)0)->n]; // expected-warning {{folded to constant}}
+  char name2[(int)&((struct bar *)0)->n - 1]; // expected-error {{array size is negative}}
 };
 
 // PR3430
Index: clang/test/Sema/offsetof-64.c
===================================================================
--- clang/test/Sema/offsetof-64.c
+++ clang/test/Sema/offsetof-64.c
@@ -5,15 +5,15 @@
 const unsigned long Size = (1l << 60);
 
 struct Chunk1 {
-  char padding[Size];
-  char more_padding[1][Size];
+  char padding[Size]; // expected-warning {{folded to constant}}
+  char more_padding[1][Size]; // expected-warning {{folded to constant}}
   char data;
 };
 
 int test1 = __builtin_offsetof(struct Chunk1, data);
 
 struct Chunk2 {
-  char padding[Size][Size][Size];  // expected-error 2{{array is too large}}
+  char padding[Size][Size][Size];  // expected-error {{array is too large}}
   char data;
 };
 
Index: clang/test/Sema/i-c-e.c
===================================================================
--- clang/test/Sema/i-c-e.c
+++ clang/test/Sema/i-c-e.c
@@ -12,7 +12,7 @@
 char v[sizeof(__builtin_constant_p(0)) == sizeof(int) ? 1 : -1];
 
 int implicitConversion = 1.0;
-char floatArith[(int)(1.0+2.0)]; // expected-warning {{must be an integer constant expression}}
+char floatArith[(int)(1.0+2.0)]; // expected-warning {{variable length array folded to constant array as an extension}}
 
 // __builtin_constant_p as the condition of ?: allows arbitrary foldable
 // constants to be transmogrified into i-c-e's.
@@ -57,7 +57,7 @@
 int comma1[0?1,2:3];
 int comma2[1||(1,2)]; // expected-warning {{use of logical '||' with constant operand}} \
                       // expected-note {{use '|' for a bitwise operation}}
-int comma3[(1,2)]; // expected-warning {{size of static array must be an integer constant expression}}
+int comma3[(1,2)]; // expected-warning {{variable length array folded to constant array as an extension}}
 
 // Pointer + __builtin_constant_p
 char pbcp[__builtin_constant_p(4) ? (intptr_t)&expr : 0]; // expected-error {{variable length array declaration not allowed at file scope}}
Index: clang/test/Sema/gnu-flags.c
===================================================================
--- clang/test/Sema/gnu-flags.c
+++ clang/test/Sema/gnu-flags.c
@@ -124,7 +124,9 @@
 	fic = (int)(0.75 * 1000 * 1000)
 };
 static const int size = 100;
-void foo(void) { int data[size]; }
+int data[size];
+
+void foo(void) { int data[size]; } // OK, always a VLA
 
 #if ALL || REDECLAREDENUM
 // expected-note@+4 {{previous definition is here}}
Index: clang/test/Sema/decl-in-prototype.c
===================================================================
--- clang/test/Sema/decl-in-prototype.c
+++ clang/test/Sema/decl-in-prototype.c
@@ -49,7 +49,7 @@
 // function.
 enum { BB = 0 };
 void enum_in_fun_in_fun(void (*fp)(enum { AA, BB } e)) { // expected-warning {{will not be visible}}
-  SA(1, AA == 5);
+  SA(1, AA == 5); // expected-error {{variable-sized object may not be initialized}}
   SA(2, BB == 0);
 }
 
Index: clang/test/Sema/darwin-align-cast.c
===================================================================
--- clang/test/Sema/darwin-align-cast.c
+++ clang/test/Sema/darwin-align-cast.c
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -fsyntax-only -Wno-pointer-to-int-cast -verify %s
-// expected-no-diagnostics
 typedef long unsigned int __darwin_size_t;
 typedef long __darwin_ssize_t;
 typedef __darwin_size_t size_t;
@@ -18,6 +17,7 @@
 
 ssize_t sendFileDescriptor(int fd, void *data, size_t nbytes, int sendfd) {
   union {
+    // expected-warning@+1 {{folded to constant array}}
     char control[(((__darwin_size_t)((char *)(sizeof(struct cmsghdr)) + (sizeof(__darwin_size_t) - 1)) &~ (sizeof(__darwin_size_t) - 1)) + ((__darwin_size_t)((char *)(sizeof(int)) + (sizeof(__darwin_size_t) - 1)) &~ (sizeof(__darwin_size_t) - 1)))];
   } control_un;
   return 0;
Index: clang/test/Sema/const-eval.c
===================================================================
--- clang/test/Sema/const-eval.c
+++ clang/test/Sema/const-eval.c
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-linux %s -Wno-tautological-pointer-compare -Wno-pointer-to-int-cast
 
-#define EVAL_EXPR(testno, expr) int test##testno = sizeof(struct{char qq[expr];});
+#define EVAL_EXPR(testno, expr) enum { test##testno = (expr) }; struct check_positive##testno { int a[test##testno]; };
 int x;
 EVAL_EXPR(1, (_Bool)&x)
 EVAL_EXPR(2, (int)(1.0+(double)4))
@@ -14,12 +14,12 @@
 EVAL_EXPR(9, !!&x)
 EVAL_EXPR(10, ((void)1, 12))
 void g0(void);
-EVAL_EXPR(11, (g0(), 12)) // expected-error {{must have a constant size}}
+EVAL_EXPR(11, (g0(), 12)) // expected-error {{not an integer constant expression}}
 EVAL_EXPR(12, 1.0&&2.0)
-EVAL_EXPR(13, x || 3.0) // expected-error {{must have a constant size}}
+EVAL_EXPR(13, x || 3.0) // expected-error {{not an integer constant expression}}
 
 unsigned int l_19 = 1;
-EVAL_EXPR(14, (1 ^ l_19) && 1); // expected-error {{fields must have a constant size}}
+EVAL_EXPR(14, (1 ^ l_19) && 1); // expected-error {{not an integer constant expression}}
 
 void f()
 {
@@ -36,7 +36,7 @@
 EVAL_EXPR(18, ((int)((void*)10 + 10)) == 20 ? 1 : -1);
 
 struct s {
-  int a[(int)-1.0f]; // expected-error {{'a' declared as an array with a negative size}}
+  int a[(int)-1.0f]; // expected-error {{array size is negative}}
 };
 
 EVAL_EXPR(19, ((int)&*(char*)10 == 10 ? 1 : -1));
@@ -47,9 +47,9 @@
 
 EVAL_EXPR(22, (__real__ (2i+3)) == 3 ? 1 : -1);
 
-int g23[(int)(1.0 / 1.0)] = { 1 };
-int g24[(int)(1.0 / 1.0)] = { 1 , 2 }; // expected-warning {{excess elements in array initializer}}
-int g25[(int)(1.0 + 1.0)], g26 = sizeof(g25);
+int g23[(int)(1.0 / 1.0)] = { 1 }; // expected-warning {{folded to constant array}}
+int g24[(int)(1.0 / 1.0)] = { 1 , 2 }; // expected-warning {{folded to constant array}} expected-warning {{excess elements in array initializer}}
+int g25[(int)(1.0 + 1.0)], g26 = sizeof(g25); // expected-warning {{folded to constant array}}
 
 EVAL_EXPR(26, (_Complex double)0 ? -1 : 1)
 EVAL_EXPR(27, (_Complex int)0 ? -1 : 1)
@@ -116,17 +116,17 @@
 // PR12043
 float varfloat;
 const float constfloat = 0;
-EVAL_EXPR(43, varfloat && constfloat) // expected-error {{must have a constant size}}
+EVAL_EXPR(43, varfloat && constfloat) // expected-error {{not an integer constant expression}}
 
 // <rdar://problem/10962435>
 EVAL_EXPR(45, ((char*)-1) + 1 == 0 ? 1 : -1)
 EVAL_EXPR(46, ((char*)-1) + 1 < (char*) -1 ? 1 : -1)
 EVAL_EXPR(47, &x < &x + 1 ? 1 : -1)
 EVAL_EXPR(48, &x != &x - 1 ? 1 : -1)
-EVAL_EXPR(49, &x < &x - 100 ? 1 : -1) // expected-error {{must have a constant size}}
+EVAL_EXPR(49, &x < &x - 100 ? 1 : -1) // expected-error {{not an integer constant expression}}
 
 extern struct Test50S Test50;
-EVAL_EXPR(50, &Test50 < (struct Test50S*)((unsigned long)&Test50 + 10)) // expected-error {{must have a constant size}}
+EVAL_EXPR(50, &Test50 < (struct Test50S*)((unsigned long)&Test50 + 10)) // expected-error {{not an integer constant expression}}
 
 // <rdar://problem/11874571>
 EVAL_EXPR(51, 0 != (float)1e99)
@@ -136,7 +136,7 @@
 
 void PR24622();
 struct PR24622 {} pr24622;
-EVAL_EXPR(52, &pr24622 == (void *)&PR24622); // expected-error {{must have a constant size}}
+EVAL_EXPR(52, &pr24622 == (void *)&PR24622); // expected-error {{not an integer constant expression}}
 
 // We evaluate these by providing 2s' complement semantics in constant
 // expressions, like we do for integers.
Index: clang/test/Sema/const-eval-64.c
===================================================================
--- clang/test/Sema/const-eval-64.c
+++ clang/test/Sema/const-eval-64.c
@@ -1,8 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-linux %s
-// expected-no-diagnostics
 
 #define EVAL_EXPR(testno, expr) int test##testno = sizeof(struct{char qq[expr];});
 
 // <rdar://problem/10962435>
-EVAL_EXPR(1, ((char*)-1LL) + 1 == 0 ? 1 : -1)
-EVAL_EXPR(2, ((char*)-1LL) + 1 < (char*) -1 ? 1 : -1)
+EVAL_EXPR(1, ((char*)-1LL) + 1 == 0 ? 1 : -1) // expected-warning {{folded}}
+EVAL_EXPR(2, ((char*)-1LL) + 1 < (char*) -1 ? 1 : -1) // expected-warning {{folded}}
Index: clang/test/Sema/complex-int.c
===================================================================
--- clang/test/Sema/complex-int.c
+++ clang/test/Sema/complex-int.c
@@ -60,14 +60,16 @@
   (*x)++;
 }
 
-int i1[(2+3i)*(5+7i) == 29i-11 ? 1 : -1];
-int i2[(29i-11)/(5+7i) == 2+3i ? 1 : -1];
-int i3[-(2+3i) == +(-3i-2) ? 1 : -1];
-int i4[~(2+3i) == 2-3i ? 1 : -1];
-int i5[(3i == -(-3i) ? ((void)3, 1i - 1) : 0) == 1i - 1 ? 1 : -1];
+// None of these array bounds is an ICE due to the use of literals of
+// non-integer type. But we can constant-fold all of them.
+int i1[(2+3i)*(5+7i) == 29i-11 ? 1 : -1]; // expected-warning {{fold}}
+int i2[(29i-11)/(5+7i) == 2+3i ? 1 : -1]; // expected-warning {{fold}}
+int i3[-(2+3i) == +(-3i-2) ? 1 : -1]; // expected-warning {{fold}}
+int i4[~(2+3i) == 2-3i ? 1 : -1]; // expected-warning {{fold}}
+int i5[(3i == -(-3i) ? ((void)3, 1i - 1) : 0) == 1i - 1 ? 1 : -1]; // expected-warning {{fold}}
 
-int f1[(2.0+3.0i)*(5.0+7.0i) == 29.0i-11.0 ? 1 : -1];
-int f2[(29.0i-11.0)/(5.0+7.0i) == 2.0+3.0i ? 1 : -1];
-int f3[-(2.0+3.0i) == +(-3.0i-2.0) ? 1 : -1];
-int f4[~(2.0+3.0i) == 2.0-3.0i ? 1 : -1];
-int f5[(3.0i == -(-3.0i) ? ((void)3.0, __extension__ (1.0i - 1.0)) : 0) == 1.0i - 1.0 ? 1 : -1];
+int f1[(2.0+3.0i)*(5.0+7.0i) == 29.0i-11.0 ? 1 : -1]; // expected-warning {{fold}}
+int f2[(29.0i-11.0)/(5.0+7.0i) == 2.0+3.0i ? 1 : -1]; // expected-warning {{fold}}
+int f3[-(2.0+3.0i) == +(-3.0i-2.0) ? 1 : -1]; // expected-warning {{fold}}
+int f4[~(2.0+3.0i) == 2.0-3.0i ? 1 : -1]; // expected-warning {{fold}}
+int f5[(3.0i == -(-3.0i) ? ((void)3.0, __extension__ (1.0i - 1.0)) : 0) == 1.0i - 1.0 ? 1 : -1]; // expected-warning {{fold}}
Index: clang/test/Sema/builtins.c
===================================================================
--- clang/test/Sema/builtins.c
+++ clang/test/Sema/builtins.c
@@ -141,7 +141,7 @@
 size_t strlen(const char *);
 
 void test17() {
-#define ASSERT(...) { int arr[(__VA_ARGS__) ? 1 : -1]; }
+#define ASSERT(...) { enum { folded = (__VA_ARGS__) }; int arr[folded ? 1 : -1]; }
 #define T(...) ASSERT(__builtin_constant_p(__VA_ARGS__))
 #define F(...) ASSERT(!__builtin_constant_p(__VA_ARGS__))
 
@@ -179,12 +179,12 @@
   ASSERT(!OPT("abcd"));
   // In these cases, the strlen is non-constant, but the __builtin_constant_p
   // is 0: the array size is not an ICE but is foldable.
-  ASSERT(!OPT(test17_c));        // expected-warning {{folded}}
-  ASSERT(!OPT(&test17_c[0]));    // expected-warning {{folded}}
-  ASSERT(!OPT((char*)test17_c)); // expected-warning {{folded}}
-  ASSERT(!OPT(test17_d));        // expected-warning {{folded}}
-  ASSERT(!OPT(&test17_d[0]));    // expected-warning {{folded}}
-  ASSERT(!OPT((char*)test17_d)); // expected-warning {{folded}}
+  ASSERT(!OPT(test17_c));        // expected-warning {{folding}}
+  ASSERT(!OPT(&test17_c[0]));    // expected-warning {{folding}}
+  ASSERT(!OPT((char*)test17_c)); // expected-warning {{folding}}
+  ASSERT(!OPT(test17_d));        // expected-warning {{folding}}
+  ASSERT(!OPT(&test17_d[0]));    // expected-warning {{folding}}
+  ASSERT(!OPT((char*)test17_d)); // expected-warning {{folding}}
 
 #undef OPT
 #undef T
Index: clang/test/Sema/builtin-assume.c
===================================================================
--- clang/test/Sema/builtin-assume.c
+++ clang/test/Sema/builtin-assume.c
@@ -23,7 +23,7 @@
   __builtin_assume(ispure(i) > 2);
   __builtin_assume(ispure(++i) > 2); //expected-warning {{the argument to '__builtin_assume' has side effects that will be discarded}}
   
-  int test = sizeof(struct{char qq[(__builtin_assume(i != 5), 7)];});
+  int test = sizeof(struct{char qq[(__builtin_assume(i != 5), 7)];}); // expected-warning {{variable length array}}
 #endif
   return a[i];
 }
Index: clang/test/Profile/misexpect-switch.c
===================================================================
--- clang/test/Profile/misexpect-switch.c
+++ clang/test/Profile/misexpect-switch.c
@@ -10,7 +10,7 @@
 
 const int inner_loop = 1000;
 const int outer_loop = 20;
-const int arry_size = 25;
+enum { arry_size = 25 };
 
 int arry[arry_size] = {0};
 
Index: clang/test/Profile/misexpect-switch-only-default-case.c
===================================================================
--- clang/test/Profile/misexpect-switch-only-default-case.c
+++ clang/test/Profile/misexpect-switch-only-default-case.c
@@ -11,7 +11,7 @@
 
 const int inner_loop = 1000;
 const int outer_loop = 20;
-const int arry_size = 25;
+enum { arry_size = 25 };
 
 int arry[arry_size] = {0};
 
Index: clang/test/Profile/misexpect-switch-nonconst.c
===================================================================
--- clang/test/Profile/misexpect-switch-nonconst.c
+++ clang/test/Profile/misexpect-switch-nonconst.c
@@ -11,7 +11,7 @@
 
 const int inner_loop = 1000;
 const int outer_loop = 20;
-const int arry_size = 25;
+enum { arry_size = 25 };
 
 int arry[arry_size] = {0};
 
Index: clang/test/Profile/misexpect-switch-default.c
===================================================================
--- clang/test/Profile/misexpect-switch-default.c
+++ clang/test/Profile/misexpect-switch-default.c
@@ -10,7 +10,7 @@
 
 const int inner_loop = 1000;
 const int outer_loop = 20;
-const int arry_size = 25;
+enum { arry_size = 25 };
 
 int arry[arry_size] = {0};
 
Index: clang/test/PCH/cxx-constexpr.cpp
===================================================================
--- clang/test/PCH/cxx-constexpr.cpp
+++ clang/test/PCH/cxx-constexpr.cpp
@@ -16,7 +16,7 @@
 #else
 
 const int a = 5;
-typedef int T[b]; // expected-error {{variable length array}} expected-error {{must be an integer constant expression}} expected-note {{initializer of 'b'}}
+typedef int T[b]; // expected-error 2{{variable length array}} expected-note {{initializer of 'b'}}
 // expected-note@14 {{here}}
 typedef int T[5];
 
Index: clang/test/Misc/warning-flags.c
===================================================================
--- clang/test/Misc/warning-flags.c
+++ clang/test/Misc/warning-flags.c
@@ -91,4 +91,4 @@
 
 The list of warnings in -Wpedantic should NEVER grow.
 
-CHECK: Number in -Wpedantic (not covered by other -W flags): 27
+CHECK: Number in -Wpedantic (not covered by other -W flags): 26
Index: clang/test/CodeGen/vla.c
===================================================================
--- clang/test/CodeGen/vla.c
+++ clang/test/CodeGen/vla.c
@@ -210,3 +210,15 @@
 void test10(int a[static 0]) {}
 // NULL-INVALID: define void @test10(i32* nonnull align 4 %a)
 // NULL-VALID: define void @test10(i32* align 4 %a)
+
+const int constant = 32;
+// CHECK: define {{.*}}pr44406(
+int pr44406() {
+  int n = 0;
+  // Do not fold this VLA to an array of constant bound; that would miscompile
+  // this testcase.
+  char c[1][(constant - constant) + 3];
+  // CHECK: store i32 1,
+  sizeof(c[n = 1]);
+  return n;
+}
Index: clang/test/CXX/drs/dr3xx.cpp
===================================================================
--- clang/test/CXX/drs/dr3xx.cpp
+++ clang/test/CXX/drs/dr3xx.cpp
@@ -898,8 +898,8 @@
   int c[true ? *new int : 4]; // expected-error 2{{variable length array}} expected-note {{read of uninitialized}}
   int d[true ? 4 : *new int];
 #if __cplusplus < 201103L
-  // expected-error@-4 {{variable length array}} expected-error@-4 {{constant expression}}
-  // expected-error@-3 {{variable length array}} expected-error@-3 {{constant expression}}
+  // expected-error@-4 2{{variable length array}}
+  // expected-error@-3 2{{variable length array}}
 #endif
 }
 
Index: clang/test/CXX/basic/basic.types/p10.cpp
===================================================================
--- clang/test/CXX/basic/basic.types/p10.cpp
+++ clang/test/CXX/basic/basic.types/p10.cpp
@@ -139,6 +139,7 @@
 constexpr int arb(int n) {
   int a[n]; // expected-error {{variable of non-literal type 'int [n]' cannot be defined in a constexpr function}}
 }
+// expected-warning@+1 {{variable length array folded to constant array as an extension}}
 constexpr long Overflow[ // expected-error {{constexpr variable cannot have non-literal type 'long const[(1 << 30) << 2]'}}
     (1 << 30) << 2]{};   // expected-warning {{requires 34 bits to represent}}
 
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -2273,13 +2273,9 @@
     }
   } Diagnoser(VLADiag, VLAIsError);
 
-  // FIXME: GCC does *not* allow folding here in general; see PR44406.
-  // For GCC compatibility, we should remove this folding and leave it to
-  // TryFixVariablyModifiedType to convert VLAs to constant array types.
   ExprResult R = S.VerifyIntegerConstantExpression(
       ArraySize, &SizeVal, Diagnoser,
-      (S.LangOpts.GNUMode || S.LangOpts.OpenCL) ? Sema::AllowFold
-                                                : Sema::NoFold);
+      S.LangOpts.OpenCL ? Sema::AllowFold : Sema::NoFold);
   if (Diagnoser.IsVLA)
     return ExprResult();
   return R;
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -5932,9 +5932,14 @@
   const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T);
   if (!VLATy)
     return QualType();
-  // FIXME: We should probably handle this case
-  if (VLATy->getElementType()->isVariablyModifiedType())
-    return QualType();
+
+  QualType ElemTy = VLATy->getElementType();
+  if (ElemTy->isVariablyModifiedType()) {
+    ElemTy = TryToFixInvalidVariablyModifiedType(ElemTy, Context,
+                                                 SizeIsNegative, Oversized);
+    if (ElemTy.isNull())
+      return QualType();
+  }
 
   Expr::EvalResult Result;
   if (!VLATy->getSizeExpr() ||
@@ -5950,16 +5955,18 @@
   }
 
   // Check whether the array is too large to be addressed.
-  unsigned ActiveSizeBits
-    = ConstantArrayType::getNumAddressingBits(Context, VLATy->getElementType(),
-                                              Res);
+  unsigned ActiveSizeBits =
+      (!ElemTy->isDependentType() && !ElemTy->isVariablyModifiedType() &&
+       !ElemTy->isIncompleteType() && !ElemTy->isUndeducedType())
+          ? ConstantArrayType::getNumAddressingBits(Context, ElemTy, Res)
+          : Res.getActiveBits();
   if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
     Oversized = Res;
     return QualType();
   }
 
-  return Context.getConstantArrayType(
-      VLATy->getElementType(), Res, VLATy->getSizeExpr(), ArrayType::Normal, 0);
+  return Context.getConstantArrayType(ElemTy, Res, VLATy->getSizeExpr(),
+                                      ArrayType::Normal, 0);
 }
 
 static void
@@ -5985,7 +5992,13 @@
   ArrayTypeLoc DstATL = DstTL.castAs<ArrayTypeLoc>();
   TypeLoc SrcElemTL = SrcATL.getElementLoc();
   TypeLoc DstElemTL = DstATL.getElementLoc();
-  DstElemTL.initializeFullCopy(SrcElemTL);
+  if (VariableArrayTypeLoc SrcElemATL =
+          SrcElemTL.getAs<VariableArrayTypeLoc>()) {
+    ConstantArrayTypeLoc DstElemATL = DstElemTL.castAs<ConstantArrayTypeLoc>();
+    FixInvalidVariablyModifiedTypeLoc(SrcElemATL, DstElemATL);
+  } else {
+    DstElemTL.initializeFullCopy(SrcElemTL);
+  }
   DstATL.setLBracketLoc(SrcATL.getLBracketLoc());
   DstATL.setSizeExpr(SrcATL.getSizeExpr());
   DstATL.setRBracketLoc(SrcATL.getRBracketLoc());
@@ -6115,7 +6128,7 @@
                                                       SizeIsNegative,
                                                       Oversized);
       if (FixedTInfo) {
-        Diag(NewTD->getLocation(), diag::warn_illegal_constant_array_size);
+        Diag(NewTD->getLocation(), diag::ext_vla_folded_to_constant);
         NewTD->setTypeSourceInfo(FixedTInfo);
       } else {
         if (SizeIsNegative)
@@ -7984,7 +7997,7 @@
       return;
     }
 
-    Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size);
+    Diag(NewVD->getLocation(), diag::ext_vla_folded_to_constant);
     NewVD->setType(FixedT);
     NewVD->setTypeSourceInfo(FixedTInfo);
   }
@@ -16675,7 +16688,7 @@
                                                     SizeIsNegative,
                                                     Oversized);
     if (FixedTInfo) {
-      Diag(Loc, diag::warn_illegal_constant_array_size);
+      Diag(Loc, diag::ext_vla_folded_to_constant);
       TInfo = FixedTInfo;
       T = FixedTInfo->getType();
     } else {
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -137,8 +137,9 @@
   "variable length array declaration cannot have 'static' storage duration">;
 def err_vla_decl_has_extern_linkage : Error<
   "variable length array declaration cannot have 'extern' linkage">;
-def ext_vla_folded_to_constant : Extension<
-  "variable length array folded to constant array as an extension">, InGroup<GNUFoldingConstant>;
+def ext_vla_folded_to_constant : ExtWarn<
+  "variable length array folded to constant array as an extension">,
+  InGroup<GNUFoldingConstant>;
 def err_vla_unsupported : Error<
   "variable length arrays are not supported for the current target">;
 def note_vla_unsupported : Note<
@@ -5474,8 +5475,6 @@
   "enumeration value %0 is out of range of flags in enumeration type %1">,
   InGroup<FlagEnum>;
 
-def warn_illegal_constant_array_size : Extension<
-  "size of static array must be an integer constant expression">;
 def err_vm_decl_in_file_scope : Error<
   "variably modified type declaration not allowed at file scope">;
 def err_vm_decl_has_extern_linkage : Error<
Index: clang/docs/UsersManual.rst
===================================================================
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -2479,8 +2479,8 @@
 ------------------------------------------
 
 clang supports the -std option, which changes what language mode clang uses.
-The supported modes for C are c89, gnu89, c99, gnu99, c11, gnu11, c17, gnu17,
-c2x, gnu2x, and various aliases for those modes. If no -std option is
+The supported modes for C are c89, gnu89, c94, c99, gnu99, c11, gnu11, c17,
+gnu17, c2x, gnu2x, and various aliases for those modes. If no -std option is
 specified, clang defaults to gnu17 mode. Many C99 and C11 features are
 supported in earlier modes as a conforming extension, with a warning. Use
 ``-pedantic-errors`` to request an error if a feature from a later standard
@@ -2489,34 +2489,36 @@
 Differences between all ``c*`` and ``gnu*`` modes:
 
 -  ``c*`` modes define "``__STRICT_ANSI__``".
--  Target-specific defines not prefixed by underscores, like "linux",
+-  Target-specific defines not prefixed by underscores, like ``linux``,
    are defined in ``gnu*`` modes.
--  Trigraphs default to being off in ``gnu*`` modes; they can be enabled by
-   the -trigraphs option.
--  The parser recognizes "asm" and "typeof" as keywords in ``gnu*`` modes;
-   the variants "``__asm__``" and "``__typeof__``" are recognized in all
+-  Trigraphs default to being off in ``gnu*`` modes; they can be enabled
+   by the ``-trigraphs`` option.
+-  The parser recognizes ``asm`` and ``typeof`` as keywords in ``gnu*`` modes;
+   the variants ``__asm__`` and ``__typeof__`` are recognized in all modes.
+-  The parser recognizes ``inline`` as a keyword in ``gnu*`` mode, in
+   addition to recognizing it in the ``*99`` and later modes for which it is
+   part of the ISO C standard. The variant ``__inline__`` is recognized in all
    modes.
 -  The Apple "blocks" extension is recognized by default in ``gnu*`` modes
-   on some platforms; it can be enabled in any mode with the "-fblocks"
+   on some platforms; it can be enabled in any mode with the ``-fblocks``
    option.
--  Arrays that are VLA's according to the standard, but which can be
-   constant folded by the frontend are treated as fixed size arrays.
-   This occurs for things like "int X[(1, 2)];", which is technically a
-   VLA. ``c*`` modes are strictly compliant and treat these as VLAs.
 
-Differences between ``*89`` and ``*99`` modes:
+Differences between ``*89`` and ``*94`` modes:
 
--  The ``*99`` modes default to implementing "inline" as specified in C99,
-   while the ``*89`` modes implement the GNU version. This can be
-   overridden for individual functions with the ``__gnu_inline__``
-   attribute.
 -  Digraphs are not recognized in c89 mode.
--  The scope of names defined inside a "for", "if", "switch", "while",
-   or "do" statement is different. (example: "``if ((struct x {int
-   x;}*)0) {}``".)
+
+Differences between ``*94`` and ``*99`` modes:
+
+-  The ``*99`` modes default to implementing ``inline`` / ``__inline__``
+   as specified in C99, while the ``*89`` modes implement the GNU version.
+   This can be overridden for individual functions with the ``__gnu_inline__``
+   attribute.
+-  The scope of names defined inside a ``for``, ``if``, ``switch``, ``while``,
+  or ``do`` statement is different. (example: ``if ((struct x {int x;}*)0)
+  {}``.)
 -  ``__STDC_VERSION__`` is not defined in ``*89`` modes.
--  "inline" is not recognized as a keyword in c89 mode.
--  "restrict" is not recognized as a keyword in ``*89`` modes.
+-  ``inline`` is not recognized as a keyword in ``c89`` mode.
+-  ``restrict`` is not recognized as a keyword in ``*89`` modes.
 -  Commas are allowed in integer constant expressions in ``*99`` modes.
 -  Arrays which are not lvalues are not implicitly promoted to pointers
    in ``*89`` modes.
@@ -2538,9 +2540,7 @@
 extensions are not implemented yet:
 
 -  clang does not support decimal floating point types (``_Decimal32`` and
-   friends) or fixed-point types (``_Fract`` and friends); nobody has
-   expressed interest in these features yet, so it's hard to say when
-   they will be implemented.
+   friends) yet.
 -  clang does not support nested functions; this is a complex feature
    which is infrequently used, so it is unlikely to be implemented
    anytime soon. In C++11 it can be emulated by assigning lambda
@@ -2590,10 +2590,12 @@
    the extension appears to be rarely used. Note that clang *does*
    support flexible array members (arrays with a zero or unspecified
    size at the end of a structure).
--  clang does not have an equivalent to gcc's "fold"; this means that
-   clang doesn't accept some constructs gcc might accept in contexts
-   where a constant expression is required, like "x-x" where x is a
-   variable.
+-  GCC accepts many expression forms that are not valid integer constant
+   expressions in bit-field widths, enumerator constants, case labels,
+   and in array bounds at global scope. Clang also accepts additional
+   expression forms in these contexts, but constructs that GCC accepts due to
+   simplifications GCC performs while parsing, such as ``x - x`` (where ``x`` is a
+   variable) will likely never be accepted by Clang.
 -  clang does not support ``__builtin_apply`` and friends; this extension
    is extremely obscure and difficult to implement reliably.
 
@@ -2634,8 +2636,11 @@
 =====================
 
 clang fully implements all of standard C++98 except for exported
-templates (which were removed in C++11), and all of standard C++11
-and the current draft standard for C++1y.
+templates (which were removed in C++11), all of standard C++11,
+C++14, and C++17, and most of C++20.
+
+See the `C++ support in Clang <https://clang.llvm.org/cxx_status.html>` page
+for detailed information on C++ feature support across Clang versions.
 
 Controlling implementation limits
 ---------------------------------
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D89523: P... Richard Smith - zygoloid via Phabricator via cfe-commits
    • [PATCH] D895... Eli Friedman via Phabricator via cfe-commits
    • [PATCH] D895... Eli Friedman via Phabricator via cfe-commits
    • [PATCH] D895... Richard Smith - zygoloid via Phabricator via cfe-commits
    • [PATCH] D895... Richard Smith - zygoloid via Phabricator via cfe-commits
    • [PATCH] D895... Richard Smith - zygoloid via Phabricator via cfe-commits
    • [PATCH] D895... Richard Smith - zygoloid via Phabricator via cfe-commits
    • [PATCH] D895... Eli Friedman via Phabricator via cfe-commits
    • [PATCH] D895... Richard Smith - zygoloid via Phabricator via cfe-commits

Reply via email to