aboutsummaryrefslogtreecommitdiff
path: root/gdb/s390-tdep.c
diff options
context:
space:
mode:
authorAndreas Arnez <arnez@linux.ibm.com>2019-10-15 14:20:14 +0200
committerAndreas Arnez <arnez@linux.ibm.com>2019-10-15 14:20:14 +0200
commitba18312d8f2cecf88b6edcbc277f433a62131e58 (patch)
treef1083c75b6db6a816e3e9f05e6f608c8150e1de9 /gdb/s390-tdep.c
parent9a73315161bc07d958060847ae01996312e1b30f (diff)
downloadgdb-ba18312d8f2cecf88b6edcbc277f433a62131e58.zip
gdb-ba18312d8f2cecf88b6edcbc277f433a62131e58.tar.gz
gdb-ba18312d8f2cecf88b6edcbc277f433a62131e58.tar.bz2
s390: Fix infcalls passing a single-field struct with static members
The infcall-nested-structs test case yields 36 FAILs on s390x because GCC and GDB disagree on how to pass a C++ struct like this as an argument to a function: struct s { float x; static float y; }; For the purpose of argument passing, GCC ignores static fields, while GDB does not. Thus GCC passes the argument in a floating-point register and GDB passes it via memory. Fix this by explicitly ignoring static fields when detecting single-field structs. gdb/ChangeLog: * s390-tdep.c (s390_effective_inner_type): Ignore static fields when unwrapping single-field structs.
Diffstat (limited to 'gdb/s390-tdep.c')
-rw-r--r--gdb/s390-tdep.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
index e7f1215..6bd0528 100644
--- a/gdb/s390-tdep.c
+++ b/gdb/s390-tdep.c
@@ -1637,11 +1637,26 @@ s390_address_class_name_to_type_flags (struct gdbarch *gdbarch,
static struct type *
s390_effective_inner_type (struct type *type, unsigned int min_size)
{
- while (TYPE_CODE (type) == TYPE_CODE_STRUCT
- && TYPE_NFIELDS (type) == 1)
+ while (TYPE_CODE (type) == TYPE_CODE_STRUCT)
{
- struct type *inner = check_typedef (TYPE_FIELD_TYPE (type, 0));
+ struct type *inner = NULL;
+ /* Find a non-static field, if any. Unless there's exactly one,
+ abort the unwrapping. */
+ for (int i = 0; i < TYPE_NFIELDS (type); i++)
+ {
+ struct field f = TYPE_FIELD (type, i);
+
+ if (field_is_static (&f))
+ continue;
+ if (inner != NULL)
+ return type;
+ inner = FIELD_TYPE (f);
+ }
+
+ if (inner == NULL)
+ break;
+ inner = check_typedef (inner);
if (TYPE_LENGTH (inner) < min_size)
break;
type = inner;