From 5017c39da23644228b7f44f84f4c0051947dfeb6 Mon Sep 17 00:00:00 2001
From: Iain Sandoe <iain@sandoe.co.uk>
Date: Tue, 24 Dec 2019 15:37:13 +0000
Subject: [PATCH] [C] Allow const vars to be used in array sizes [PR93082].

This allows us to consume some MacOS headers that expect this clang
extension to be present.

	PR target/93082

gcc/c-family/ChangeLog:

	* c.opt (flag_allow_const_var_array_size): New.

gcc/c/ChangeLog:

	* c-decl.cc (grokdeclarator): Allow const vars to be used
	as array sizes.

gcc/ChangeLog:

	* config/darwin.cc (darwin_override_options): Default
	flag_allow_const_var_array_size on.

gcc/testsuite/ChangeLog:

	* c-c++-common/pr58346-3.c: Disable const var array size
	extension on Darwin.
	* gcc.dg/vla-init-2.c: Likewise.
	* gcc.dg/vla-init-4.c: Likewise.
	* gcc.dg/vla-init-5.c: Likewise.
	* gcc.misc-tests/gcov-pr85350.c: Likewise.

Signed-off-by: Iain Sandoe <iain@sandoe.co.uk>

t
---
 gcc/c-family/c.opt                          |  4 ++++
 gcc/c/c-decl.cc                             | 22 +++++++++++++++++++++
 gcc/config/darwin.cc                        |  4 ++++
 gcc/testsuite/c-c++-common/pr58346-3.c      |  1 +
 gcc/testsuite/gcc.dg/vla-init-2.c           |  1 +
 gcc/testsuite/gcc.dg/vla-init-4.c           |  1 +
 gcc/testsuite/gcc.dg/vla-init-5.c           |  1 +
 gcc/testsuite/gcc.misc-tests/gcov-pr85350.c |  1 +
 8 files changed, 35 insertions(+)

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 75b6531860e..abe758bba24 100644
--- gcc/c-family/c.opt
+++ gcc/c-family/c.opt
@@ -1806,6 +1806,10 @@ static-libmpxwrappers
 Driver WarnRemoved
 Removed in GCC 9.  This switch has no effect.
 
+fallow-const-var-array-size
+C ObjC C++ ObjC++ LTO Var(flag_allow_const_var_array_size) Init(0)
+Allow arrays sizes to be const-qualified vars in C and Objective-C.
+
 fcilkplus
 C ObjC C++ ObjC++ LTO Undocumented Ignore
 Removed in GCC 8.  This switch has no effect.
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index c778c7febfa..b3da099a2d0 100644
--- gcc/c/c-decl.cc
+++ gcc/c/c-decl.cc
@@ -7358,6 +7358,25 @@ grokdeclarator (const struct c_declarator *declarator,
 		  }
 
 		size = c_fully_fold (size, false, &size_maybe_const);
+		bool size_const_var = false;
+		if (flag_allow_const_var_array_size)
+		  {
+		    tree maybe_const_size = TREE_CODE (size) == NOP_EXPR
+					    ? TREE_OPERAND (size, 0) : size;
+		    size_const_var
+		      = (TREE_CODE (maybe_const_size) == VAR_DECL
+			 && TREE_READONLY (maybe_const_size)
+			 && !TREE_THIS_VOLATILE (maybe_const_size));
+		    if (size_const_var
+			&& size_maybe_const
+			&& DECL_INITIAL (maybe_const_size))
+		      {
+			size = DECL_INITIAL (maybe_const_size);
+			size = c_fully_fold (size, false, &size_maybe_const);
+			size_int_const = (TREE_CODE (size) == INTEGER_CST
+					  && !TREE_OVERFLOW (size));
+		      }
+		  }
 
 		if (pedantic && size_maybe_const && integer_zerop (size))
 		  {
@@ -7399,6 +7418,9 @@ grokdeclarator (const struct c_declarator *declarator,
 			  this_size_varies = size_varies = true;
 			warn_variable_length_array (name, size);
 		      }
+		    if (flag_allow_const_var_array_size && size_const_var)
+		      pedwarn (input_location, OPT_Wpedantic,
+			       "variably modified %qE at file scope", name);
 		  }
 		else if ((decl_context == NORMAL || decl_context == FIELD)
 			 && current_scope == file_scope)
diff --git a/gcc/config/darwin.cc b/gcc/config/darwin.cc
index be2daed4f66..56247e579bc 100644
--- gcc/config/darwin.cc
+++ gcc/config/darwin.cc
@@ -3592,6 +3592,10 @@ darwin_override_options (void)
 
   /* The c_dialect...() macros are not available to us here.  */
   darwin_running_cxx = (strstr (lang_hooks.name, "C++") != 0);
+
+  /* Allow the clang extension to permit const vars used in array sizes.  */
+  if (!OPTION_SET_P (flag_allow_const_var_array_size))
+    flag_allow_const_var_array_size = true;
 }
 
 #if DARWIN_PPC
diff --git a/gcc/testsuite/c-c++-common/pr58346-3.c b/gcc/testsuite/c-c++-common/pr58346-3.c
index 41627ed953c..b3d35ce0d31 100644
--- gcc/testsuite/c-c++-common/pr58346-3.c
+++ gcc/testsuite/c-c++-common/pr58346-3.c
@@ -1,5 +1,6 @@
 /* PR c/58346 */
 /* { dg-do compile } */
+/* { dg-additional-options "-fno-allow-const-var-array-size" { target *-*-darwin* } } */
 
 void
 foo (void)
diff --git a/gcc/testsuite/gcc.dg/vla-init-2.c b/gcc/testsuite/gcc.dg/vla-init-2.c
index f23630a3657..b6e6f6eaece 100644
--- gcc/testsuite/gcc.dg/vla-init-2.c
+++ gcc/testsuite/gcc.dg/vla-init-2.c
@@ -4,6 +4,7 @@
    testcase.  */
 /* { dg-do compile } */
 /* { dg-options "" } */
+/* { dg-additional-options "-fno-allow-const-var-array-size" { target *-*-darwin* } } */
 
 const int i = 1;
 void foo() { char a[][i] = {""}; } /* { dg-error "variable-sized object may not be initialized" } */
diff --git a/gcc/testsuite/gcc.dg/vla-init-4.c b/gcc/testsuite/gcc.dg/vla-init-4.c
index 06351d04e03..43d5d8cbfc8 100644
--- gcc/testsuite/gcc.dg/vla-init-4.c
+++ gcc/testsuite/gcc.dg/vla-init-4.c
@@ -2,6 +2,7 @@
 /* Origin: Joseph Myers <jsm@polyomino.org.uk> */
 /* { dg-do compile } */
 /* { dg-options "" } */
+/* { dg-additional-options "-fno-allow-const-var-array-size" { target *-*-darwin* } } */
 
 const int i = 1;
 void foo() { char *p = (char [i]){ "" }; } /* { dg-error "compound literal has variable size" } */
diff --git a/gcc/testsuite/gcc.dg/vla-init-5.c b/gcc/testsuite/gcc.dg/vla-init-5.c
index aa9f4910ac9..500854d83a3 100644
--- gcc/testsuite/gcc.dg/vla-init-5.c
+++ gcc/testsuite/gcc.dg/vla-init-5.c
@@ -2,6 +2,7 @@
 /* Origin: Joseph Myers <jsm@polyomino.org.uk> */
 /* { dg-do compile } */
 /* { dg-options "" } */
+/* { dg-additional-options "-fno-allow-const-var-array-size" { target *-*-darwin* } } */
 
 const int i = 1;
 void foo() { void *p = (char [][i]){ "" }; } /* { dg-error "compound literal has variable size" } */
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-pr85350.c b/gcc/testsuite/gcc.misc-tests/gcov-pr85350.c
index 0383b81fdfb..57d4d6a90a7 100644
--- gcc/testsuite/gcc.misc-tests/gcov-pr85350.c
+++ gcc/testsuite/gcc.misc-tests/gcov-pr85350.c
@@ -1,5 +1,6 @@
 /* { dg-options "-fprofile-arcs -ftest-coverage" } */
 /* { dg-do run { target native } } */
+/* { dg-additional-options "-fno-allow-const-var-array-size" { target *-*-darwin* } } */
 
 int main (void)
 {
