summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/typeck2.c4
-rw-r--r--gcc/expr.c9
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/union2.C36
6 files changed, 59 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 243cff9fc14..1bdfbce58fe 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,7 @@
+Wed Oct 13 22:01:35 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * expr.c (store_constructor): Clear union if constructor is empty.
+
Wed Oct 13 15:19:04 1999 Jim Wilson <wilson@cygnus.com>
* config/rs6000/sysv4.h (CC1_SPEC): Fix errors from Jan 19 change.
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9c421a8d92d..3593ce4bc0b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,7 @@
+Wed Oct 13 22:01:35 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * typeck2.c (process_init_constructor): Handle empty constructors.
+
1999-10-13 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (lang_mark_tree): Mark NAMESPACE_LEVEL.
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 4b37e48976e..cb089d41ec1 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -921,7 +921,9 @@ process_init_constructor (type, init, elts)
members = expr_tree_cons (field, next1, members);
}
}
- else if (TREE_CODE (type) == UNION_TYPE)
+ else if (TREE_CODE (type) == UNION_TYPE
+ /* If the initializer was empty, use default zero initialization. */
+ && tail)
{
register tree field = TYPE_FIELDS (type);
diff --git a/gcc/expr.c b/gcc/expr.c
index 79e651fc7f6..e2460203045 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -4073,7 +4073,14 @@ store_constructor (exp, target, align, cleared)
/* Inform later passes that the whole union value is dead. */
if (TREE_CODE (type) == UNION_TYPE
|| TREE_CODE (type) == QUAL_UNION_TYPE)
- emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
+ {
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
+
+ /* If the constructor is empty, clear the union. */
+ if (! CONSTRUCTOR_ELTS (exp) && ! cleared)
+ clear_storage (target, expr_size (exp),
+ TYPE_ALIGN (type) / BITS_PER_UNIT);
+ }
/* If we are building a static constructor into a register,
set the initial value as zero so we can fold the value into
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 47563490a0b..e6db32ab03f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+Wed Oct 13 22:01:35 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * g++.old-deja/g++.other/union2.C: New test.
+
1999-10-13 Nathan Sidwell <nathan@acm.org>
* g++.old-deja/g++.other/vaarg2.C: New test.
diff --git a/gcc/testsuite/g++.old-deja/g++.other/union2.C b/gcc/testsuite/g++.old-deja/g++.other/union2.C
new file mode 100644
index 00000000000..32dd26c97a5
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/union2.C
@@ -0,0 +1,36 @@
+// Bug: g++ crashed on empty intializers for unions.
+// Bug: gcc and g++ didn't zero unions with empty initializers.
+// Submitted by J"orn Rennecke <amylaar@cygnus.co.uk>
+
+typedef union u
+{
+ union u *up;
+ void *vp;
+} u;
+
+static u v = {};
+
+void bar (u);
+void baz (u);
+
+void foo()
+{
+ u w = {};
+ u x = { &v };
+ baz (x);
+ bar (w);
+}
+
+void baz (u w) { }
+
+void bar (u w)
+{
+ if (w.up)
+ exit (1);
+}
+
+int main ()
+{
+ foo ();
+ return 0;
+}