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] Support initialization by compound literal in designated initializers


Hi!

Linux kernel not only uses:
typedef struct { } spinlock_t;
spinlock_t x = (spinlock_t) { };
but
struct foo { spinlock_t x; } x = { .x = (spinlock_t) { } };
type of constructs.
The same problem, (spinlock_t) { } is a macro expansion.
The following patch:
a) makes the extension work for aggregate/struct initializers (previously
   only the whole object could be initialized that way)
b) defers emitting __compound_literal.XY variables, so that if the
   extension "static storage object initialized by compound literal"
   is used, compound literals aren't emitted unless they are actuall used
   (I first thought about using TREE_ASM_REFERENCED for this, but
   this would get tricky if the compound literal was only referenced
   by something defered until wrapup_global_declarations)
c) puts const qualified compound literals into const section and not data
   section (and in some limited cases merge them, though more code would be
   needed to merge them for any complit size)
Bootstrapped on i386-redhat-linux, no regressions.
Ok to commit?

2002-01-02  Jakub Jelinek  <jakub@redhat.com>

	* c-decl.c (build_compound_literal): Set TREE_READONLY
	flag for constant qualified compound literals.
	Defer static compound literal emition.
	* c-tree.h (defer_complit): New function.
	* c-objc-common.c (expand_deferred_complits, deferred_complits,
	defer_complit): New.
	(c_objc_common_init): Initialize deferred_complits.
	(c_objc_common_finish_file): Call expand_deferred_complits.
	* c-typeck.c (digest_init): Clear TREE_USED for compound literal
	decl if it will not be used.
	(output_init_element): Allow initializing static storage duration
	objects with compound literals.

	* gcc.dg/gnu89-init-1.c: Added new tests.

--- gcc/c-decl.c.jj	Thu Dec 27 13:54:34 2001
+++ gcc/c-decl.c	Wed Jan  2 16:52:42 2002
@@ -3855,6 +3855,7 @@ build_compound_literal (type, init)
   DECL_CONTEXT (decl) = current_function_decl;
   TREE_USED (decl) = 1;
   TREE_TYPE (decl) = type;
+  TREE_READONLY (decl) = TREE_READONLY (type);
   store_init_value (decl, init);
 
   if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
@@ -3877,12 +3878,17 @@ build_compound_literal (type, init)
   if (TREE_STATIC (decl))
     {
       /* This decl needs a name for the assembler output.  We also need
-	 a unique suffix to be added to the name, for which DECL_CONTEXT
-	 must be set.  */
-      DECL_NAME (decl) = get_identifier ("__compound_literal");
-      DECL_CONTEXT (decl) = complit;
+	 a unique suffix to be added to the name.  */
+      char *name;
+      static int compound_literal_labelno;
+
+      ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal",
+			       compound_literal_labelno);
+      compound_literal_labelno++;
+      DECL_NAME (decl) = get_identifier (name);
+      DECL_DEFER_OUTPUT (decl) = 1;
       rest_of_decl_compilation (decl, NULL, 1, 0);
-      DECL_CONTEXT (decl) = NULL_TREE;
+      defer_complit (decl);
     }
 
   return complit;
--- gcc/c-tree.h.jj	Tue Dec 18 01:28:02 2001
+++ gcc/c-tree.h	Wed Jan  2 16:03:53 2002
@@ -175,6 +175,7 @@ extern const char *c_objc_common_init		P
 extern int c_missing_noreturn_ok_p		PARAMS ((tree));
 extern void c_objc_common_finish_file		PARAMS ((void));
 extern int defer_fn				PARAMS ((tree));
+extern int defer_complit			PARAMS ((tree));
 
 #define c_build_type_variant(TYPE, CONST_P, VOLATILE_P)		  \
   c_build_qualified_type (TYPE,				  \
--- gcc/c-objc-common.c.jj	Tue Dec 18 01:28:02 2001
+++ gcc/c-objc-common.c	Wed Jan  2 17:02:47 2002
@@ -37,10 +37,11 @@ Software Foundation, 59 Temple Place - S
 static int c_tree_printer PARAMS ((output_buffer *));
 static tree inline_forbidden_p PARAMS ((tree *, int *, void *));
 static void expand_deferred_fns PARAMS ((void));
+static void expand_deferred_complits PARAMS ((void));
 static tree start_cdtor	PARAMS ((int));
 static void finish_cdtor PARAMS ((tree));
 
-static varray_type deferred_fns;
+static varray_type deferred_fns, deferred_complits;
 
 int
 c_missing_noreturn_ok_p (decl)
@@ -237,6 +238,9 @@ c_objc_common_init (filename)
   VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns");
   ggc_add_tree_varray_root (&deferred_fns, 1);
 
+  VARRAY_TREE_INIT (deferred_complits, 16, "deferred_complits");
+  ggc_add_tree_varray_root (&deferred_complits, 1);
+
   return filename;
 }
 
@@ -252,6 +256,18 @@ defer_fn (fn)
   return 1;
 }
 
+/* Register a compound literal decl, so that it is emitted only
+   at the end of the compilation.  */
+
+int
+defer_complit (decl)
+     tree decl;
+{
+  VARRAY_PUSH_TREE (deferred_complits, decl);
+
+  return 1;
+}
+
 /* Expand deferred functions for C and ObjC.  */
 
 static void
@@ -276,6 +292,33 @@ expand_deferred_fns ()
   VARRAY_FREE (deferred_fns);
 }
 
+/* Expand deferred compound literals.  */
+
+static void
+expand_deferred_complits ()
+{
+  unsigned int i;
+  int flag_merge_constants_save = flag_merge_constants;
+
+  /* All constant qualified compound literals can be merged.  */
+  if (flag_merge_constants)
+    flag_merge_constants = 2;
+
+  for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_complits); i++)
+    {
+      tree decl = VARRAY_TREE (deferred_complits, i);
+
+      if (TREE_USED (decl))
+	{
+	  DECL_DEFER_OUTPUT (decl) = 0;
+	  rest_of_decl_compilation (decl, NULL, 1, 1);
+	}
+    }
+
+  VARRAY_FREE (deferred_complits);
+  flag_merge_constants = flag_merge_constants_save;
+}
+
 static tree
 start_cdtor (method_type)
      int method_type;
@@ -325,6 +368,7 @@ finish_cdtor (body)
 void
 c_objc_common_finish_file ()
 {
+  expand_deferred_complits ();
   expand_deferred_fns ();
 
   if (static_ctors)
--- gcc/c-typeck.c.jj	Mon Dec 31 11:52:13 2001
+++ gcc/c-typeck.c	Wed Jan  2 16:24:33 2002
@@ -4816,6 +4816,9 @@ digest_init (type, init, require_constan
 	     the brace enclosed list they contain).  */
 	  tree decl = COMPOUND_LITERAL_EXPR_DECL (inside_init);
 	  inside_init = DECL_INITIAL (decl);
+	  /* Say that this compound literal is no longer used and thus
+	     doesn't need to be output.  */
+	  TREE_USED (decl) = 0;
 	}
 
       if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST
@@ -6275,6 +6278,19 @@ output_init_element (value, type, field,
 			 TYPE_MAIN_VARIANT (type))))
     value = default_conversion (value);
 
+  if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR
+      && require_constant_value && !flag_isoc99 && pending)
+    {
+      /* 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 (value);
+      value = DECL_INITIAL (decl);
+      /* Say that this compound literal is no longer used and thus
+	 doesn't need to be output.  */
+      TREE_USED (decl) = 0;
+    }
+
   if (value == error_mark_node)
     constructor_erroneous = 1;
   else if (!TREE_CONSTANT (value))
--- gcc/testsuite/gcc.dg/gnu89-init-1.c.jj	Thu Dec 27 16:54:41 2001
+++ gcc/testsuite/gcc.dg/gnu89-init-1.c	Wed Jan  2 16:46:12 2002
@@ -8,6 +8,8 @@ extern void exit (int);
 
 struct A { int i; int j; int k[4]; };
 struct B { };
+struct C { int i; };
+struct D { int i; struct C j; };
 
 /* As a GNU extension, we allow initialization of objects with static storage
    duration by compound literals.  It is handled as if the object
@@ -22,6 +24,10 @@ int c[] = (int []) { [2] = 6, 7, 8 };
 int d[] = (int [3]) { 1 };
 int e[2] = (int []) { 1, 2 };
 int f[2] = (int [2]) { 1 };
+struct C g[3] = { [2] = (struct C) { 13 }, [1] = (const struct C) { 12 } };
+struct D h = { .j = (struct C) { 15 }, .i = 14 };
+struct D i[2] = { [1].j = (const struct C) { 17 },
+		  [0] = { 0, (struct C) { 16 } } };
 
 int main (void)
 {
@@ -43,5 +49,11 @@ int main (void)
     abort ();
   if (sizeof (f) != 2 * sizeof (int))
     abort ();
+  if (g[0].i || g[1].i != 12 || g[2].i != 13)
+    abort ();
+  if (h.i != 14 || h.j.i != 15)
+    abort ();
+  if (i[0].i || i[0].j.i != 16 || i[1].i || i[1].j.i != 17)
+    abort ();
   exit (0);
 }

	Jakub


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