[clang] 552c6c2 - PR44406: Follow behavior of array bound constant folding in more recent versions of GCC.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 16 14:34:45 PDT 2020


Author: Richard Smith
Date: 2020-10-16T14:34:35-07:00
New Revision: 552c6c2328723a248c2b4d2765f75d49129dff20

URL: https://github.com/llvm/llvm-project/commit/552c6c2328723a248c2b4d2765f75d49129dff20
DIFF: https://github.com/llvm/llvm-project/commit/552c6c2328723a248c2b4d2765f75d49129dff20.diff

LOG: PR44406: Follow behavior of array bound constant folding in more recent versions of GCC.

Old GCC used to aggressively fold VLAs to constant-bound arrays at block
scope in GNU mode. That's non-conforming, and more modern versions of
GCC only do this at file scope. Update Clang to do the same.

Also promote the warning for this from off-by-default to on-by-default
in all cases; more recent versions of GCC likewise warn on this by
default.

This is still slightly more permissive than GCC, as pointed out in
PR44406, as we still fold VLAs to constant arrays in structs, but that
seems justifiable given that we don't support VLA-in-struct (and don't
intend to ever support it), but GCC does.

Differential Revision: https://reviews.llvm.org/D89523

Added: 
    

Modified: 
    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/rounding-math.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

Removed: 
    


################################################################################
diff  --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index 473fbb6d8d04..9726a25f7f63 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -2502,10 +2502,6 @@ Differences between all ``c*`` and ``gnu*`` 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``
    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 ``*94`` modes:
 
@@ -2594,10 +2590,12 @@ Intentionally unsupported GCC extensions
    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 
diff icult to implement reliably.
 

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b3b3bc723863..90a48ad7e93c 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -137,8 +137,9 @@ def err_vla_decl_has_static_storage : Error<
   "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 @@ def warn_flag_enum_constant_out_of_range : Warning<
   "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<

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 8542c20ec069..5a38a9585d30 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -5932,9 +5932,14 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
   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 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
   }
 
   // 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 @@ FixInvalidVariablyModifiedTypeLoc(TypeLoc SrcTL, TypeLoc DstTL) {
   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 @@ Sema::CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *NewTD) {
                                                       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 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
       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 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
                                                     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 {

diff  --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 5eb05bfcaee3..390b457792fe 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -2273,13 +2273,9 @@ static ExprResult checkArraySize(Sema &S, Expr *&ArraySize,
     }
   } 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;

diff  --git a/clang/test/CXX/basic/basic.types/p10.cpp b/clang/test/CXX/basic/basic.types/p10.cpp
index 31ef6b62cead..124a489dfebe 100644
--- a/clang/test/CXX/basic/basic.types/p10.cpp
+++ b/clang/test/CXX/basic/basic.types/p10.cpp
@@ -139,6 +139,7 @@ constexpr int f(ArrBad) { return 0; } // expected-error {{1st parameter type 'Ar
 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 at +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}}
 

diff  --git a/clang/test/CXX/drs/dr3xx.cpp b/clang/test/CXX/drs/dr3xx.cpp
index f297d5e930d0..be3169ceab76 100644
--- a/clang/test/CXX/drs/dr3xx.cpp
+++ b/clang/test/CXX/drs/dr3xx.cpp
@@ -898,8 +898,8 @@ namespace dr367 { // dr367: yes
   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 at -4 {{variable length array}} expected-error at -4 {{constant expression}}
-  // expected-error at -3 {{variable length array}} expected-error at -3 {{constant expression}}
+  // expected-error at -4 2{{variable length array}}
+  // expected-error at -3 2{{variable length array}}
 #endif
 }
 

diff  --git a/clang/test/CodeGen/vla.c b/clang/test/CodeGen/vla.c
index 3142050149aa..ab7dac67d8d2 100644
--- a/clang/test/CodeGen/vla.c
+++ b/clang/test/CodeGen/vla.c
@@ -210,3 +210,15 @@ void test9(int n, int a[static n]) { }
 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;
+}

diff  --git a/clang/test/Misc/warning-flags.c b/clang/test/Misc/warning-flags.c
index e4f9069b88c8..54e36e1e0884 100644
--- a/clang/test/Misc/warning-flags.c
+++ b/clang/test/Misc/warning-flags.c
@@ -91,4 +91,4 @@ CHECK-NEXT:   warn_weak_import
 
 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

diff  --git a/clang/test/PCH/cxx-constexpr.cpp b/clang/test/PCH/cxx-constexpr.cpp
index cce3fd851217..6ec1c8467e07 100644
--- a/clang/test/PCH/cxx-constexpr.cpp
+++ b/clang/test/PCH/cxx-constexpr.cpp
@@ -16,7 +16,7 @@ const int b = a;
 #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 at 14 {{here}}
 typedef int T[5];
 

diff  --git a/clang/test/Profile/misexpect-switch-default.c b/clang/test/Profile/misexpect-switch-default.c
index 3d1079d79f96..900c0a5df31f 100644
--- a/clang/test/Profile/misexpect-switch-default.c
+++ b/clang/test/Profile/misexpect-switch-default.c
@@ -10,7 +10,7 @@ void init_arry();
 
 const int inner_loop = 1000;
 const int outer_loop = 20;
-const int arry_size = 25;
+enum { arry_size = 25 };
 
 int arry[arry_size] = {0};
 

diff  --git a/clang/test/Profile/misexpect-switch-nonconst.c b/clang/test/Profile/misexpect-switch-nonconst.c
index fb719c5a2d1d..1573df538ac2 100644
--- a/clang/test/Profile/misexpect-switch-nonconst.c
+++ b/clang/test/Profile/misexpect-switch-nonconst.c
@@ -11,7 +11,7 @@ void init_arry();
 
 const int inner_loop = 1000;
 const int outer_loop = 20;
-const int arry_size = 25;
+enum { arry_size = 25 };
 
 int arry[arry_size] = {0};
 

diff  --git a/clang/test/Profile/misexpect-switch-only-default-case.c b/clang/test/Profile/misexpect-switch-only-default-case.c
index 3886472e2b45..d6c68f07d092 100644
--- a/clang/test/Profile/misexpect-switch-only-default-case.c
+++ b/clang/test/Profile/misexpect-switch-only-default-case.c
@@ -11,7 +11,7 @@ void init_arry();
 
 const int inner_loop = 1000;
 const int outer_loop = 20;
-const int arry_size = 25;
+enum { arry_size = 25 };
 
 int arry[arry_size] = {0};
 

diff  --git a/clang/test/Profile/misexpect-switch.c b/clang/test/Profile/misexpect-switch.c
index a7f01bcc9986..c4fa5f90d440 100644
--- a/clang/test/Profile/misexpect-switch.c
+++ b/clang/test/Profile/misexpect-switch.c
@@ -10,7 +10,7 @@ void init_arry();
 
 const int inner_loop = 1000;
 const int outer_loop = 20;
-const int arry_size = 25;
+enum { arry_size = 25 };
 
 int arry[arry_size] = {0};
 

diff  --git a/clang/test/Sema/builtin-assume.c b/clang/test/Sema/builtin-assume.c
index 43b31375f200..932fb5c973eb 100644
--- a/clang/test/Sema/builtin-assume.c
+++ b/clang/test/Sema/builtin-assume.c
@@ -23,7 +23,7 @@ int foo(int *a, int i) {
   __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];
 }

diff  --git a/clang/test/Sema/builtins.c b/clang/test/Sema/builtins.c
index e4093edb5f00..e534f4727252 100644
--- a/clang/test/Sema/builtins.c
+++ b/clang/test/Sema/builtins.c
@@ -141,7 +141,7 @@ typedef __typeof(sizeof(int)) size_t;
 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 @@ void test17() {
   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

diff  --git a/clang/test/Sema/complex-int.c b/clang/test/Sema/complex-int.c
index f73b338c4010..4f7093256db5 100644
--- a/clang/test/Sema/complex-int.c
+++ b/clang/test/Sema/complex-int.c
@@ -60,14 +60,16 @@ void test5(_Complex int *x) {
   (*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}}

diff  --git a/clang/test/Sema/const-eval-64.c b/clang/test/Sema/const-eval-64.c
index 1290bf4dd85d..f198b8bf5d14 100644
--- a/clang/test/Sema/const-eval-64.c
+++ b/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}}

diff  --git a/clang/test/Sema/const-eval.c b/clang/test/Sema/const-eval.c
index bbcbb0e25237..c3cecc06cfcd 100644
--- a/clang/test/Sema/const-eval.c
+++ b/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(8, (_Bool)"asdf")
 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 @@ int g17[(3?:1) - 2];
 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(21, (__imag__ 2i) == 2 ? 1 : -1);
 
 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 @@ EVAL_EXPR(42, __builtin_constant_p(pr11391.f = 1))
 // 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 PR21945() { int i = (({}), 0l); }
 
 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.

diff  --git a/clang/test/Sema/darwin-align-cast.c b/clang/test/Sema/darwin-align-cast.c
index 3a1824901277..114a1d9672c2 100644
--- a/clang/test/Sema/darwin-align-cast.c
+++ b/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 @@ i386/_param.h:#define __DARWIN_ALIGN(p) ((__darwin_size_t)((char *)(p)
 
 ssize_t sendFileDescriptor(int fd, void *data, size_t nbytes, int sendfd) {
   union {
+    // expected-warning at +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;

diff  --git a/clang/test/Sema/decl-in-prototype.c b/clang/test/Sema/decl-in-prototype.c
index 64caea6a38a8..83e35a673390 100644
--- a/clang/test/Sema/decl-in-prototype.c
+++ b/clang/test/Sema/decl-in-prototype.c
@@ -49,7 +49,7 @@ void f(struct q *, struct __attribute__((aligned(4))) q *); // expected-warning
 // 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);
 }
 

diff  --git a/clang/test/Sema/gnu-flags.c b/clang/test/Sema/gnu-flags.c
index e7588b7b371e..e53e5fdf11df 100644
--- a/clang/test/Sema/gnu-flags.c
+++ b/clang/test/Sema/gnu-flags.c
@@ -124,7 +124,9 @@ enum {
 	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 at +4 {{previous definition is here}}

diff  --git a/clang/test/Sema/i-c-e.c b/clang/test/Sema/i-c-e.c
index e2d921b8ffd6..120f4b5f4889 100644
--- a/clang/test/Sema/i-c-e.c
+++ b/clang/test/Sema/i-c-e.c
@@ -12,7 +12,7 @@ char w[__builtin_constant_p(expr) ? expr : 1];
 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 @@ char z[__builtin_constant_p(4) ? 1 : -1];
 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}}

diff  --git a/clang/test/Sema/offsetof-64.c b/clang/test/Sema/offsetof-64.c
index 4a80dee2fc2f..8ffc3af98588 100644
--- a/clang/test/Sema/offsetof-64.c
+++ b/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;
 };
 

diff  --git a/clang/test/Sema/rounding-math.c b/clang/test/Sema/rounding-math.c
index 3cb5d034b143..89951b1726db 100644
--- a/clang/test/Sema/rounding-math.c
+++ b/clang/test/Sema/rounding-math.c
@@ -1,6 +1,7 @@
-// RUN: %clang_cc1 -triple x86_64-linux -verify=norounding %s
-// RUN: %clang_cc1 -triple x86_64-linux -std=c17 -verify=rounding-std %s -frounding-math
-// RUN: %clang_cc1 -triple x86_64-linux -std=gnu17 -verify=rounding-gnu %s -frounding-math
+// RUN: %clang_cc1 -triple x86_64-linux -std=c17 -verify=expected,norounding %s
+// RUN: %clang_cc1 -triple x86_64-linux -std=gnu17 -verify=expected,norounding %s
+// RUN: %clang_cc1 -triple x86_64-linux -std=c17 -verify=expected,rounding %s -frounding-math
+// RUN: %clang_cc1 -triple x86_64-linux -std=gnu17 -verify=expected,rounding %s -frounding-math
 
 #define fold(x) (__builtin_constant_p(x) ? (x) : (x))
 
@@ -24,8 +25,11 @@ void bitfield(struct Bitfield *b) {
 }
 
 void vlas() {
-  // Under -frounding-math, this is a VLA.
-  // FIXME: Due to PR44406, in GNU mode we constant-fold the initializer resulting in a non-VLA.
-  typedef int vla[(int)(-3 * (1.0 / 3.0))]; // norounding-error {{negative size}} rounding-gnu-error {{negative size}}
-  struct X { vla v; }; // rounding-std-error {{fields must have a constant size}}
+  // This is always a VLA due to its syntactic form.
+  typedef int vla1[(int)(-3 * (1.0 / 3.0))];
+  struct X1 { vla1 v; }; // expected-error {{fields must have a constant size}}
+
+  // This is always folded to a constant.
+  typedef int vla2[fold((int)(-3 * (1.0 / 3.0)))]; // expected-error {{negative size}}
+  struct X2 { vla2 v; };
 }

diff  --git a/clang/test/Sema/struct-decl.c b/clang/test/Sema/struct-decl.c
index ee3e79182eaa..a119e59eab93 100644
--- a/clang/test/Sema/struct-decl.c
+++ b/clang/test/Sema/struct-decl.c
@@ -5,8 +5,8 @@ struct bar {
 };
 
 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

diff  --git a/clang/test/Sema/typedef-variable-type.c b/clang/test/Sema/typedef-variable-type.c
index 8a7ee8b911c0..da1c241eea3d 100644
--- a/clang/test/Sema/typedef-variable-type.c
+++ b/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}}

diff  --git a/clang/test/Sema/vla.c b/clang/test/Sema/vla.c
index 8d83100b9d68..f49e8bbf5f7b 100644
--- a/clang/test/Sema/vla.c
+++ b/clang/test/Sema/vla.c
@@ -53,7 +53,7 @@ int pr2044b;
 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 @@ void VLAPtrAssign(int size) {
   // 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;

diff  --git a/clang/test/SemaCXX/anonymous-struct.cpp b/clang/test/SemaCXX/anonymous-struct.cpp
index f85b00bc8bce..1b6207d19e44 100644
--- a/clang/test/SemaCXX/anonymous-struct.cpp
+++ b/clang/test/SemaCXX/anonymous-struct.cpp
@@ -131,6 +131,9 @@ namespace ValidButUnsupported {
   typedef struct { // expected-error {{unsupported}}
     enum X {};
     int arr[&f<X> ? 1 : 2];
+#if __cplusplus < 201103L
+    // expected-warning at -2 {{folded to constant}}
+#endif
   } C; // expected-note {{by this typedef}}
 }
 

diff  --git a/clang/test/SemaCXX/constant-expression.cpp b/clang/test/SemaCXX/constant-expression.cpp
index 82f9657d84f6..2bec62f46b66 100644
--- a/clang/test/SemaCXX/constant-expression.cpp
+++ b/clang/test/SemaCXX/constant-expression.cpp
@@ -110,7 +110,7 @@ extern const int recurse1;
 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];

diff  --git a/clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp b/clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp
index 82ed724e1bd9..6cbc6b69e82f 100644
--- a/clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp
+++ b/clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp
@@ -120,7 +120,7 @@ namespace Builtins {
   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];
 }
 

diff  --git a/clang/test/SemaCXX/i-c-e-cxx.cpp b/clang/test/SemaCXX/i-c-e-cxx.cpp
index 2bfb67ffdf5b..a09ff5ac8d9f 100644
--- a/clang/test/SemaCXX/i-c-e-cxx.cpp
+++ b/clang/test/SemaCXX/i-c-e-cxx.cpp
@@ -80,7 +80,7 @@ struct PR8836 { char _; long long a; };
 #endif
 
 int PR8836test[(__typeof(sizeof(int)))&reinterpret_cast<const volatile char&>((((PR8836*)0)->a))];
-// expected-warning at -1 {{folded to constant array as an extension}}
+// expected-warning at -1 0-1{{C99 feature}} expected-warning at -1 {{folded to constant array as an extension}}
 // expected-note at -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 @@ const int nonconst = 1.0;
 #endif
 int arr[nonconst];
 #if __cplusplus <= 199711L
-// expected-warning at -2 {{folded to constant array as an extension}}
+// expected-warning at -2 0-1{{C99 feature}} expected-warning at -2 {{folded to constant array as an extension}}
 // expected-note at -3 {{initializer of 'nonconst' is not a constant expression}}
 #endif
 

diff  --git a/clang/test/SemaObjC/gcc-cast-ext.m b/clang/test/SemaObjC/gcc-cast-ext.m
index 9e9186070ffe..2eb707065d9f 100644
--- a/clang/test/SemaObjC/gcc-cast-ext.m
+++ b/clang/test/SemaObjC/gcc-cast-ext.m
@@ -11,7 +11,7 @@ @interface PBXDocBookmark
 
 // 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}}\


        


More information about the cfe-commits mailing list