This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Allow compound literals in static storage duration object initializers


On Mon, Dec 10, 2001 at 04:14:19PM +0000, Joseph S. Myers wrote:
> On Mon, 10 Dec 2001, I wrote:
> 
> > You're the expert on initializers in GCC, not me; you'd need to handle a
> > COMPOUND_LITERAL_EXPR specially for objects of static storage duration in
> > the appropriate place, and look at the DECL_INITIAL of the
> > COMPOUND_LITERAL_EXPR_DECL.  (Plus add a testcase and docs.)
> 
> All if !flag_isoc99 only, of course - I don't think we should perpetuate
> this in gnu99 mode.

Here is the patch.
Note that I don't agree with !flag_isoc99, I'd think !pedantic
would be more appropriate (or !pedantic and not -std=c99).
Because if projects using GNU extensions now rush for two sets of macros,
one for static initializers and one for non-static, they will loose the
helpful type checking. E.g. if someone mistakenly uses a different
initializer, with this extension he'll get an error:
struct A { int i; int j; };
struct B { int i; int j; };
#define AINIT (struct A) { 1, 2 }
#define BINIT (struct B) { 3, 4 }
struct B x = AINIT;

while if
#define AINIT { 1, 2 }
#define BINIT { 3, 4 }
he'll get no error.

There is one unclear thing about the extension though:
int d[] = (int [3]) { 1 };
with old gcc this would be identical to
int d[] = { 1 };
(ie. d would have size sizeof(int)).
I don't think anybody is using this, so I'm looking for suggestions
how to handle this:
a) handle it the same way as older gcc, which is kind of surprising
   behaviour (this done in patch below)
b) issue an error if compound literal's array type is not unknown
   size and the size is different to the size of bracket enclosed
   list
c) handle it so that object gets size of the compound literal array type

2001-12-12  Jakub Jelinek  <jakub@redhat.com>

	* c-typeck.c (digest_init): Allow initializing
	static storage duration objects with compound literals.
	* doc/extend.texi (Compound literals): Document the extension.

	* testsuite/gcc.dg/gnu89-init-1.c: New test.

--- gcc/c-typeck.c.jj	Wed Dec 12 11:54:25 2001
+++ gcc/c-typeck.c	Wed Dec 12 12:13:45 2001
@@ -4780,8 +4780,19 @@ digest_init (type, init, require_constan
     {
       if (code == POINTER_TYPE)
 	inside_init = default_function_array_conversion (inside_init);
-      else if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST
-	       && TREE_CODE (inside_init) != CONSTRUCTOR)
+
+      if (require_constant && !flag_isoc99
+	  && TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
+	{
+	  /* As an extension, allow initializing objects with static storage
+	     duration with compound literals (which are then treated just as
+	     the brace enclosed list they contain).  */
+	  tree decl = COMPOUND_LITERAL_EXPR_DECL (inside_init);
+	  inside_init = DECL_INITIAL (decl);
+	}
+
+      if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST
+	  && TREE_CODE (inside_init) != CONSTRUCTOR)
 	{
 	  error_init ("array initialized from non-constant array expression");
 	  return error_mark_node;
--- gcc/doc/extend.texi.jj	Mon Dec 10 19:14:32 2001
+++ gcc/doc/extend.texi	Wed Dec 12 12:44:38 2001
@@ -1649,6 +1649,30 @@ Compound literals for scalar types and u
 also allowed, but then the compound literal is equivalent
 to a cast.
 
+As a GNU extension, GCC allows initialization of objects with static storage
+duration by compound literals (which is not possible in ISO C99, because
+the initializer is not a constant).
+It is handled as if the object was initialized only with the bracket
+enclosed list if compound literal's and object types match.
+The initializer list of the compound literal must be constant.
+If the object being initialized has array type of unknown size, the size is
+determined by compound literal's initializer list, not by the size of the
+compound literal.
+
+@example
+static struct foo x = (struct foo) @{1, 'a', 'b'@};
+static int y[] = (int []) @{1, 2, 3@};
+static int z[] = (int [3]) @{1@};
+@end example
+
+@noindent
+The above lines are equivalent to the following:
+@example
+static struct foo x = @{1, 'a', 'b'@};
+static int y[] = @{1, 2, 3@};
+static int z[] = @{1@};
+@end example
+
 @node Designated Inits
 @section Designated Initializers
 @cindex initializers with labeled elements
--- gcc/testsuite/gcc.dg/gnu89-init-1.c.jj	Wed Dec 12 11:56:23 2001
+++ gcc/testsuite/gcc.dg/gnu89-init-1.c	Wed Dec 12 12:32:36 2001
@@ -0,0 +1,37 @@
+/* Test for GNU extensions to compound literals */
+/* Origin: Jakub Jelinek <jakub@redhat.com> */
+/* { dg-do run } */
+/* { dg-options "-std=gnu89" } */
+
+extern void abort (void);
+extern void exit (int);
+
+struct A { int i; int j; int k[4]; };
+struct B { };
+
+/* As a GNU extension, we allow initialization of objects with static storage
+   duration by compound literals.  It is handled as if the object
+   was initialized only with the bracket enclosed list if compound literal's
+   and object types match.  If the object being initialized has array type
+   of unknown size, the size is determined by compound literal's initializer
+   list, not by size of the compound literal.  */
+
+struct A a = (struct A) { .j = 6, .k[2] = 12 };
+struct B b = (struct B) { };
+int c[] = (int []) { [2] = 6, 7, 8 };
+int d[] = (int [3]) { 1 };
+
+int main (void)
+{
+  if (a.i || a.j != 6 || a.k[0] || a.k[1] || a.k[2] != 12 || a.k[3])
+    abort ();
+  if (c[0] || c[1] || c[2] != 6 || c[3] != 7 || c[4] != 8)
+    abort ();
+  if (sizeof (c) != 5 * sizeof (int))
+    abort ();
+  if (d[0] != 1)
+    abort ();
+  if (sizeof (d) != sizeof (int))
+    abort ();
+  exit (0);
+}


	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]