This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Support initialization by compound literal in designated initializers
- From: Jakub Jelinek <jakub at redhat dot com>
- To: rth at redhat dot com, jsm28 at cam dot ac dot uk
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Wed, 2 Jan 2002 18:36:05 +0100
- Subject: [PATCH] Support initialization by compound literal in designated initializers
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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