This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
patch applied to sh.c: fix more struct layout failures
- From: Joern RENNECKE <joern dot rennecke at st dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 19 Aug 2005 13:34:21 +0100
- Subject: patch applied to sh.c: fix more struct layout failures
2005-08-19 J"orn Rennecke <joern.rennecke@st.com>
* sh.c (find_sole_member): New function.
(sh_gimplify_va_arg_expr): Use it. Allow RECORD_TYPE mode mismatch
if the record's alignment is larger than the size of its only member.
Index: config/sh/sh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.c,v
retrieving revision 1.343
diff -p -r1.343 sh.c
*** config/sh/sh.c 18 Aug 2005 16:41:51 -0000 1.343
--- config/sh/sh.c 19 Aug 2005 12:25:07 -0000
*************** sh_va_start (tree valist, rtx nextarg)
*** 6632,6637 ****
--- 6632,6658 ----
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
+ /* TYPE is a RECORD_TYPE. If there is only a single non-zero-sized
+ member, return it. */
+ static tree
+ find_sole_member (tree type)
+ {
+ tree field, member = NULL_TREE;
+
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+ if (!DECL_SIZE (field))
+ return NULL_TREE;
+ if (integer_zerop (DECL_SIZE (field)))
+ continue;
+ if (member)
+ return NULL_TREE;
+ member = field;
+ }
+ return member;
+ }
/* Implement `va_arg'. */
static tree
*************** sh_gimplify_va_arg_expr (tree valist, tr
*** 6657,6662 ****
--- 6678,6684 ----
tree next_o, next_o_limit, next_fp, next_fp_limit, next_stack;
int pass_as_float;
tree lab_false;
+ tree member;
f_next_o = TYPE_FIELDS (va_list_type_node);
f_next_o_limit = TREE_CHAIN (f_next_o);
*************** sh_gimplify_va_arg_expr (tree valist, tr
*** 6679,6700 ****
like their member. This is relevant if the latter has a REAL_TYPE
or COMPLEX_TYPE type. */
while (TREE_CODE (type) == RECORD_TYPE
! && TYPE_FIELDS (type)
! && TREE_CODE (TYPE_FIELDS (type)) == FIELD_DECL
! && (TREE_CODE (TREE_TYPE (TYPE_FIELDS (type))) == REAL_TYPE
! || TREE_CODE (TREE_TYPE (TYPE_FIELDS (type))) == COMPLEX_TYPE
! || TREE_CODE (TREE_TYPE (TYPE_FIELDS (type))) == RECORD_TYPE)
! && TREE_CHAIN (TYPE_FIELDS (type)) == NULL_TREE)
{
! tree field_type = TREE_TYPE (TYPE_FIELDS (type));
if (TYPE_MODE (type) == TYPE_MODE (field_type))
type = field_type;
else
{
! gcc_assert (TYPE_ALIGN (type)
! < GET_MODE_ALIGNMENT (TYPE_MODE (field_type)));
! break;
}
}
--- 6701,6722 ----
like their member. This is relevant if the latter has a REAL_TYPE
or COMPLEX_TYPE type. */
while (TREE_CODE (type) == RECORD_TYPE
! && (member = find_sole_member (type))
! && (TREE_CODE (TREE_TYPE (member)) == REAL_TYPE
! || TREE_CODE (TREE_TYPE (member)) == COMPLEX_TYPE
! || TREE_CODE (TREE_TYPE (member)) == RECORD_TYPE))
{
! tree field_type = TREE_TYPE (member);
if (TYPE_MODE (type) == TYPE_MODE (field_type))
type = field_type;
else
{
! gcc_assert ((TYPE_ALIGN (type)
! < GET_MODE_ALIGNMENT (TYPE_MODE (field_type)))
! || (TYPE_ALIGN (type)
! > GET_MODE_BITSIZE (TYPE_MODE (field_type))));
! break;
}
}