gdb/riscv: Handle empty C++ structs during argument passing
authorAndrew Burgess <andrew.burgess@embecosm.com>
Fri, 5 Apr 2019 12:50:19 +0000 (13:50 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Thu, 11 Apr 2019 22:37:45 +0000 (23:37 +0100)
commit9f0272f8548164b024ff9fd151686b2b904a5d59
tree0d23c89b0c26d8f0259e823c218e7ed6931fc5cd
parent02cf60c7a42710ee0364698c436b6ca5e771374b
gdb/riscv: Handle empty C++ structs during argument passing

This commit resolves a large number of failures in the test script
gdb.base/infcall-nested-structs.exp which were caused by GDB (for
RISC-V) incorrectly handling empty C++ structures when preparing
arguments for a dummy call, or collecting a return value.

The issue is further complicated in that there was a bug in GCC, such
that in some cases GCC would generate incorrect code when passing a
small structure that contained empty sub-structures.  This was fixed
in GCC trunk on 5-March-2019, so in order to see the best results with
this patch you'll need a recent version of GCC.

Anything that used to work should continue to work after this patch,
regardless of GCC version being used.

The fix in this commit is that GDB now pays more attention to the
offset of fields within a structure when preparing arguments as in C++
an empty structure has a non-zero size, this is an example:

  struct s1 { struct s2 { } empty; int f; };

We previously assumed that 'f' was at offset 0 inside type 's1',
however this is not the case in C++ as 's2' has size 1, and with
alignment 'f' is likely at some even bigger offset inside 's1'.

gdb/ChangeLog:

* riscv-tdep.c (riscv_call_arg_complex_float): Fix offset of first
component to 0.
(riscv_struct_info::riscv_struct_info): Initialise m_offsets
member.
(riscv_struct_info::analyse): New implementation using new
analyse_inner member function.
(riscv_struct_info::field_offset): New member function.
(riscv_struct_info::m_offsets): New member variable.
(riscv_struct_info::analyse_inner): New private member function,
takes the old implementation of riscv_struct_info::analyse but
extended to track field offsets.
(riscv_call_arg_struct): Update the struct folding special cases
to handle cases where empty C++ structs, which are non-zero
length, are found.
(riscv_arg_location): Initialise the length of each location, a
non-zero length now indicates the location is in use.
(riscv_push_dummy_call): Allow for the first location having a
non-zero offset when setting up arguments.
(riscv_return_value): Likewise, but for return values.
gdb/ChangeLog
gdb/riscv-tdep.c