diff options
author | Simon Marchi <simon.marchi@efficios.com> | 2020-12-09 13:52:03 -0500 |
---|---|---|
committer | Simon Marchi <simon.marchi@polymtl.ca> | 2020-12-09 15:31:44 -0500 |
commit | bd1768de2174b4f22ccd7ea1c076e031c5835cce (patch) | |
tree | 6fb7d7ebcf8e94c7bdb77f9173a481c0a4d99178 | |
parent | f47d1c255d21d7425b8a45c7a20979e9cb553ed8 (diff) | |
download | gdb-bd1768de2174b4f22ccd7ea1c076e031c5835cce.zip gdb-bd1768de2174b4f22ccd7ea1c076e031c5835cce.tar.gz gdb-bd1768de2174b4f22ccd7ea1c076e031c5835cce.tar.bz2 |
gdb: split get_discrete_bounds in two
get_discrete_bounds is not flexible for ranges (TYPE_CODE_RANGE), in the
sense that it returns true (success) only if both bounds are present and
constant values.
This is a problem for code that only needs to know the low bound and
fails unnecessarily if the high bound is unknown.
Split the function in two, get_discrete_low_bound and
get_discrete_high_bound, that both return an optional. Provide a new
implementation of get_discrete_bounds based on the two others, so the
callers don't have to be changed.
gdb/ChangeLog:
* gdbtypes.c (get_discrete_bounds): Implement with
get_discrete_low_bound and get_discrete_high_bound.
(get_discrete_low_bound): New.
(get_discrete_high_bound): New.
Change-Id: I986b5e9c0dd969800e3fb9546af9c827d52e80d0
-rw-r--r-- | gdb/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/gdbtypes.c | 189 |
2 files changed, 137 insertions, 59 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 1350023..8d5002d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,12 @@ 2020-12-09 Simon Marchi <simon.marchi@efficios.com> + * gdbtypes.c (get_discrete_bounds): Implement with + get_discrete_low_bound and get_discrete_high_bound. + (get_discrete_low_bound): New. + (get_discrete_high_bound): New. + +2020-12-09 Simon Marchi <simon.marchi@efficios.com> + * gdbtypes.h (get_discrete_bounds): Return bool, adjust all callers. * gdbtypes.c (get_discrete_bounds): Return bool. diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 274fc25..30310b4 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -1024,73 +1024,127 @@ has_static_range (const struct range_bounds *bounds) && bounds->stride.kind () == PROP_CONST); } -/* See gdbtypes.h. */ +/* If TYPE's low bound is a known constant, return it, else return nullopt. */ -bool -get_discrete_bounds (struct type *type, LONGEST *lowp, LONGEST *highp) +static gdb::optional<LONGEST> +get_discrete_low_bound (struct type *type) { type = check_typedef (type); switch (type->code ()) { case TYPE_CODE_RANGE: - /* This function currently only works for ranges with two defined, - constant bounds. */ - if (type->bounds ()->low.kind () != PROP_CONST - || type->bounds ()->high.kind () != PROP_CONST) + { + /* This function only works for ranges with a constant low bound. */ + if (type->bounds ()->low.kind () != PROP_CONST) + return {}; + + LONGEST low = type->bounds ()->low.const_val (); + + if (TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_ENUM) + { + gdb::optional<LONGEST> low_pos + = discrete_position (TYPE_TARGET_TYPE (type), low); + + if (low_pos.has_value ()) + low = *low_pos; + } + + return low; + } + + case TYPE_CODE_ENUM: + { + if (type->num_fields () > 0) + { + /* The enums may not be sorted by value, so search all + entries. */ + LONGEST low = TYPE_FIELD_ENUMVAL (type, 0); + + for (int i = 0; i < type->num_fields (); i++) + { + if (TYPE_FIELD_ENUMVAL (type, i) < low) + low = TYPE_FIELD_ENUMVAL (type, i); + } + + /* Set unsigned indicator if warranted. */ + if (low >= 0) + TYPE_UNSIGNED (type) = 1; + + return low; + } + else + return 0; + } + + case TYPE_CODE_BOOL: + return 0; + + case TYPE_CODE_INT: + if (TYPE_LENGTH (type) > sizeof (LONGEST)) /* Too big */ return false; - *lowp = type->bounds ()->low.const_val (); - *highp = type->bounds ()->high.const_val (); + if (!TYPE_UNSIGNED (type)) + return -(1 << (TYPE_LENGTH (type) * TARGET_CHAR_BIT - 1)); - if (TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_ENUM) - { - gdb::optional<LONGEST> low_pos - = discrete_position (TYPE_TARGET_TYPE (type), *lowp); + /* fall through */ + case TYPE_CODE_CHAR: + return 0; - if (low_pos.has_value ()) - *lowp = *low_pos; + default: + return false; + } +} - gdb::optional<LONGEST> high_pos - = discrete_position (TYPE_TARGET_TYPE (type), *highp); +/* If TYPE's high bound is a known constant, return it, else return nullopt. */ - if (high_pos.has_value ()) - *highp = *high_pos; - } - return true; +static gdb::optional<LONGEST> +get_discrete_high_bound (struct type *type) +{ + type = check_typedef (type); + switch (type->code ()) + { + case TYPE_CODE_RANGE: + { + /* This function only works for ranges with a constant high bound. */ + if (type->bounds ()->high.kind () != PROP_CONST) + return {}; + + LONGEST high = type->bounds ()->high.const_val (); + + if (TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_ENUM) + { + gdb::optional<LONGEST> high_pos + = discrete_position (TYPE_TARGET_TYPE (type), high); + + if (high_pos.has_value ()) + high = *high_pos; + } + + return high; + } case TYPE_CODE_ENUM: - if (type->num_fields () > 0) - { - /* The enums may not be sorted by value, so search all - entries. */ - int i; + { + if (type->num_fields () > 0) + { + /* The enums may not be sorted by value, so search all + entries. */ + LONGEST high = TYPE_FIELD_ENUMVAL (type, 0); - *lowp = *highp = TYPE_FIELD_ENUMVAL (type, 0); - for (i = 0; i < type->num_fields (); i++) - { - if (TYPE_FIELD_ENUMVAL (type, i) < *lowp) - *lowp = TYPE_FIELD_ENUMVAL (type, i); - if (TYPE_FIELD_ENUMVAL (type, i) > *highp) - *highp = TYPE_FIELD_ENUMVAL (type, i); - } + for (int i = 0; i < type->num_fields (); i++) + { + if (TYPE_FIELD_ENUMVAL (type, i) > high) + high = TYPE_FIELD_ENUMVAL (type, i); + } - /* Set unsigned indicator if warranted. */ - if (*lowp >= 0) - { - TYPE_UNSIGNED (type) = 1; - } - } - else - { - *lowp = 0; - *highp = -1; - } - return true; + return high; + } + else + return -1; + } case TYPE_CODE_BOOL: - *lowp = 0; - *highp = 1; - return true; + return 1; case TYPE_CODE_INT: if (TYPE_LENGTH (type) > sizeof (LONGEST)) /* Too big */ @@ -1098,25 +1152,42 @@ get_discrete_bounds (struct type *type, LONGEST *lowp, LONGEST *highp) if (!TYPE_UNSIGNED (type)) { - *lowp = -(1 << (TYPE_LENGTH (type) * TARGET_CHAR_BIT - 1)); - *highp = -*lowp - 1; - return true; + LONGEST low = -(1 << (TYPE_LENGTH (type) * TARGET_CHAR_BIT - 1)); + return -low - 1; } + /* fall through */ case TYPE_CODE_CHAR: - *lowp = 0; - /* This round-about calculation is to avoid shifting by - TYPE_LENGTH (type) * TARGET_CHAR_BIT, which will not work - if TYPE_LENGTH (type) == sizeof (LONGEST). */ - *highp = 1 << (TYPE_LENGTH (type) * TARGET_CHAR_BIT - 1); - *highp = (*highp - 1) | *highp; - return true; + { + /* This round-about calculation is to avoid shifting by + TYPE_LENGTH (type) * TARGET_CHAR_BIT, which will not work + if TYPE_LENGTH (type) == sizeof (LONGEST). */ + LONGEST high = 1 << (TYPE_LENGTH (type) * TARGET_CHAR_BIT - 1); + return (high - 1) | high; + } default: return false; } } +/* See gdbtypes.h. */ + +bool +get_discrete_bounds (struct type *type, LONGEST *lowp, LONGEST *highp) +{ + gdb::optional<LONGEST> low = get_discrete_low_bound (type); + gdb::optional<LONGEST> high = get_discrete_high_bound (type); + + if (!low.has_value () || !high.has_value ()) + return false; + + *lowp = *low; + *highp = *high; + + return true; +} + /* Assuming TYPE is a simple, non-empty array type, compute its upper and lower bound. Save the low bound into LOW_BOUND if not NULL. Save the high bound into HIGH_BOUND if not NULL. |