re PR target/26141 (va_arg causes cc1plus ICE in gimplify_addr_expr)

PR target/26141

gcc:
	* sh.c (sh_gimplify_va_arg_expr): Don't change the result type when
	computing the effective result type.

gcc/testsuite:
	* g++.dg/expr/stdarg2.C: New test.

From-SVN: r110811
This commit is contained in:
J"orn Rennecke 2006-02-09 20:54:12 +00:00 committed by Joern Rennecke
parent 91b4415af4
commit 11160b5817
4 changed files with 59 additions and 14 deletions

View File

@ -1,3 +1,9 @@
2006-02-09 J"orn Rennecke <joern.rennecke@st.com>
PR target/26141
* sh.c (sh_gimplify_va_arg_expr): Don't change the result type when
computing the effective result type.
2006-02-09 J"orn Rennecke <joern.rennecke@st.com>
PR inline-asm/16194

View File

@ -6738,6 +6738,7 @@ sh_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p,
tree tmp, pptr_type_node;
tree addr, lab_over = NULL, result = NULL;
int pass_by_ref = targetm.calls.must_pass_in_stack (TYPE_MODE (type), type);
tree eff_type;
if (pass_by_ref)
type = build_pointer_type (type);
@ -6775,21 +6776,22 @@ sh_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p,
/* Structures with a single member with a distinct mode are passed
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))
eff_type = type;
while (TREE_CODE (eff_type) == RECORD_TYPE
&& (member = find_sole_member (eff_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;
if (TYPE_MODE (eff_type) == TYPE_MODE (field_type))
eff_type = field_type;
else
{
gcc_assert ((TYPE_ALIGN (type)
gcc_assert ((TYPE_ALIGN (eff_type)
< GET_MODE_ALIGNMENT (TYPE_MODE (field_type)))
|| (TYPE_ALIGN (type)
|| (TYPE_ALIGN (eff_type)
> GET_MODE_BITSIZE (TYPE_MODE (field_type))));
break;
}
@ -6797,14 +6799,14 @@ sh_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p,
if (TARGET_SH4)
{
pass_as_float = ((TREE_CODE (type) == REAL_TYPE && size <= 8)
|| (TREE_CODE (type) == COMPLEX_TYPE
&& TREE_CODE (TREE_TYPE (type)) == REAL_TYPE
pass_as_float = ((TREE_CODE (eff_type) == REAL_TYPE && size <= 8)
|| (TREE_CODE (eff_type) == COMPLEX_TYPE
&& TREE_CODE (TREE_TYPE (eff_type)) == REAL_TYPE
&& size <= 16));
}
else
{
pass_as_float = (TREE_CODE (type) == REAL_TYPE && size == 4);
pass_as_float = (TREE_CODE (eff_type) == REAL_TYPE && size == 4);
}
addr = create_tmp_var (pptr_type_node, NULL);
@ -6817,7 +6819,7 @@ sh_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p,
{
tree next_fp_tmp = create_tmp_var (TREE_TYPE (f_next_fp), NULL);
tree cmp;
bool is_double = size == 8 && TREE_CODE (type) == REAL_TYPE;
bool is_double = size == 8 && TREE_CODE (eff_type) == REAL_TYPE;
tmp = build1 (ADDR_EXPR, pptr_type_node, next_fp);
tmp = build2 (MODIFY_EXPR, void_type_node, addr, tmp);
@ -6836,7 +6838,8 @@ sh_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p,
if (!is_double)
gimplify_and_add (cmp, pre_p);
if (TYPE_ALIGN (type) > BITS_PER_WORD || (is_double || size == 16))
if (TYPE_ALIGN (eff_type) > BITS_PER_WORD
|| (is_double || size == 16))
{
tmp = fold_convert (ptr_type_node, size_int (UNITS_PER_WORD));
tmp = build2 (BIT_AND_EXPR, ptr_type_node, next_fp_tmp, tmp);
@ -6848,9 +6851,10 @@ sh_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p,
gimplify_and_add (cmp, pre_p);
#ifdef FUNCTION_ARG_SCmode_WART
if (TYPE_MODE (type) == SCmode && TARGET_SH4 && TARGET_LITTLE_ENDIAN)
if (TYPE_MODE (eff_type) == SCmode
&& TARGET_SH4 && TARGET_LITTLE_ENDIAN)
{
tree subtype = TREE_TYPE (type);
tree subtype = TREE_TYPE (eff_type);
tree real, imag;
imag

View File

@ -1,3 +1,8 @@
2006-02-09 J"orn Rennecke <joern.rennecke@st.com>
PR target/26141
* g++.dg/expr/stdarg2.C: New test.
2006-02-09 J"orn Rennecke <joern.rennecke@st.com>
PR inline-asm/16194

View File

@ -0,0 +1,30 @@
// PR target/26141
#include <stdarg.h>
struct S
{
double a;
};
void
foo (int z, ...)
{
struct S arg;
va_list ap;
arg = va_arg (ap, struct S);
}
struct T
{
__complex__ float a;
};
void
bar (int z, ...)
{
struct T arg;
va_list ap;
arg = va_arg (ap, struct T);
}