From 11160b5817b5ff284e34a2810ac39d871aa0d93b Mon Sep 17 00:00:00 2001 From: "J\"orn Rennecke" Date: Thu, 9 Feb 2006 20:54:12 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 6 ++++++ gcc/config/sh/sh.c | 32 ++++++++++++++++------------- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/expr/stdarg2.C | 30 +++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/g++.dg/expr/stdarg2.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 763e081d178..bec237477ad 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2006-02-09 J"orn Rennecke + + 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 PR inline-asm/16194 diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 056b32b2c42..237da2619e7 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 59778df2f87..f53188f5c9f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2006-02-09 J"orn Rennecke + + PR target/26141 + * g++.dg/expr/stdarg2.C: New test. + 2006-02-09 J"orn Rennecke PR inline-asm/16194 diff --git a/gcc/testsuite/g++.dg/expr/stdarg2.C b/gcc/testsuite/g++.dg/expr/stdarg2.C new file mode 100644 index 00000000000..cf2eabcb161 --- /dev/null +++ b/gcc/testsuite/g++.dg/expr/stdarg2.C @@ -0,0 +1,30 @@ +// PR target/26141 + +#include + +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); +}