Hi,
In GCC 4.7.2 in function.c, inside assign_parm_find_data_types there
is distinction between passed and nominal mode.
nominal_type = TREE_TYPE (parm);
passed_type = DECL_ARG_TYPE (parm);
Next data->passed_pointer is set to true if passed_type should pass by
reference.
Consider synthetic code:
double g ();
typedef union {
struct {
unsigned s:1, e:8, f:23;
} u;
float f;
} s;
f(x, n)
float x;
{
((s *)&x)->u.e -= n;
x = g((double)x, -n);
}
In this case, for argument x, nominal_type is <real_type float> and
passed_type is <real_type double>.
Now suppose some private backend, where single floats are passed in
registers and doubles in memory.
In this case data->passed_pointer will be set to true. But really it
is passed in memory. So next inside assign_parms, DECL_RTL field will
be set to register, and later inside expand_expr_addr_expr_1, this
will assert on gcc_assert (MEM_P (result));
Just rewriting f as:
f(float x, int n)
{
((s *)&x)->u.e -= n;
x = g((double)x, -n);
}
corrects things -- now both nominal_type and passed_type are float.
But I really want to be able to compile old-style definitions also.
So question is -- why assign_parm_find_data_types prefers passed_type
to nominal_type in checking if things are passing by reference, and
what is preferable way to fix this case? Maybe there already exists
some bug? I can not reproduce this case on any existing backend, it
seems x86 and arm passes SF and DF uniformly, so I am writing here,
not in bugzilla.
---
With best regards, Konstantin