diff options
author | Richard Henderson <rth@redhat.com> | 2005-10-11 15:52:04 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2005-10-11 15:52:04 -0700 |
commit | 0257e3837eb84c9f288c39cfbb3caa41badf9e3b (patch) | |
tree | 6b4c903cc38542479c96457d3c7e5f32641dfc61 /gcc | |
parent | a4176272bf595ac4110d38e07970bdde42d6d4dd (diff) | |
download | gcc-0257e3837eb84c9f288c39cfbb3caa41badf9e3b.zip gcc-0257e3837eb84c9f288c39cfbb3caa41badf9e3b.tar.gz gcc-0257e3837eb84c9f288c39cfbb3caa41badf9e3b.tar.bz2 |
re PR c/24255 (__transparent_union__ mishandled)
PR c/24255
* c-typeck.c (convert_for_assignment): Use build_constructor_single
to initialize a transparent union instead of a nop_expr.
From-SVN: r105270
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/c-typeck.c | 22 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/transparent-union-5.c | 37 |
3 files changed, 54 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 88834b6..9d7fc4e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2005-10-11 Richard Henderson <rth@redhat.com> + PR c/24255 + * c-typeck.c (convert_for_assignment): Use build_constructor_single + to initialize a transparent union instead of a nop_expr. + +2005-10-11 Richard Henderson <rth@redhat.com> + * Makefile.in (tree-ssa-dce.o): Depend on SCEV_H. * tree-ssa-dce.c: Include tree-scalar-evolution.h. (tree_ssa_dce_loop): Call scev_reset. diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 8a90476..cf9798a 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -3799,13 +3799,11 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, else if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type) && (errtype == ic_argpass || errtype == ic_argpass_nonproto)) { - tree memb_types; - tree marginal_memb_type = 0; + tree memb, marginal_memb = NULL_TREE; - for (memb_types = TYPE_FIELDS (type); memb_types; - memb_types = TREE_CHAIN (memb_types)) + for (memb = TYPE_FIELDS (type); memb ; memb = TREE_CHAIN (memb)) { - tree memb_type = TREE_TYPE (memb_types); + tree memb_type = TREE_TYPE (memb); if (comptypes (TYPE_MAIN_VARIANT (memb_type), TYPE_MAIN_VARIANT (rhstype))) @@ -3837,8 +3835,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, break; /* Keep looking for a better type, but remember this one. */ - if (!marginal_memb_type) - marginal_memb_type = memb_type; + if (!marginal_memb) + marginal_memb = memb; } } @@ -3852,13 +3850,13 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, } } - if (memb_types || marginal_memb_type) + if (memb || marginal_memb) { - if (!memb_types) + if (!memb) { /* We have only a marginally acceptable member type; it needs a warning. */ - tree ttl = TREE_TYPE (marginal_memb_type); + tree ttl = TREE_TYPE (TREE_TYPE (marginal_memb)); tree ttr = TREE_TYPE (rhstype); /* Const and volatile mean something different for function @@ -3893,12 +3891,14 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, "from pointer target type"), G_("return discards qualifiers from " "pointer target type")); + + memb = marginal_memb; } if (pedantic && (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl))) pedwarn ("ISO C prohibits argument conversion to union type"); - return build1 (NOP_EXPR, type, rhs); + return build_constructor_single (type, memb, rhs); } } diff --git a/gcc/testsuite/gcc.dg/transparent-union-5.c b/gcc/testsuite/gcc.dg/transparent-union-5.c new file mode 100644 index 0000000..47e245e --- /dev/null +++ b/gcc/testsuite/gcc.dg/transparent-union-5.c @@ -0,0 +1,37 @@ +/* PR 24255 */ +/* { dg-do run } */ +/* { dg-options "-O" } */ + +extern void abort (void); + +union wait { int w_status; }; + +typedef union +{ + union wait *uptr; + int *iptr; +} WAIT_STATUS __attribute__ ((__transparent_union__)); + +int status; +union wait wstatus; + +void __attribute__((noinline)) +test1 (WAIT_STATUS s) +{ + if (s.iptr != &status) + abort (); +} + +void __attribute__((noinline)) +test2 (WAIT_STATUS s) +{ + if (s.uptr != &wstatus) + abort (); +} + +int main() +{ + test1 (&status); + test2 (&wstatus); + return 0; +} |