summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Brobecker <brobecker@gnat.com>2008-09-30 21:36:21 +0000
committerJoel Brobecker <brobecker@gnat.com>2008-09-30 21:36:21 +0000
commit915c7c520062a28b8bf2681864f9510d450bea7d (patch)
tree7213fb1993060ce9c868d2383d1c7f4828ad242f
parentc086827c5d322371f24908a85b7cf02f7b0e6333 (diff)
downloadgdb-915c7c520062a28b8bf2681864f9510d450bea7d.tar.gz
* ada-lang.c (ada_lookup_struct_elt_type): Handle case of a "naked"
variant branch. (empty_record): Use INIT_CPLUS_SPECIFIC, since this field is not supposed to be null. Fixes debugger segfaults. (is_unchecked_variant): New function. (to_fixed_variant_branch_type): Modify to leave unchecked unions untouched. (ada_template_to_fixed_record_type_1): Fix comment.
-rw-r--r--gdb/ChangeLog11
-rw-r--r--gdb/ada-lang.c36
2 files changed, 43 insertions, 4 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 4a02fb7c5d7..d67ea1c0d1e 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@
+2008-09-30 Paul Hilfinger <brobecker@adacore.com>
+
+ * ada-lang.c (ada_lookup_struct_elt_type): Handle case of a "naked"
+ variant branch.
+ (empty_record): Use INIT_CPLUS_SPECIFIC, since this field is not
+ supposed to be null. Fixes debugger segfaults.
+ (is_unchecked_variant): New function.
+ (to_fixed_variant_branch_type): Modify to leave unchecked unions
+ untouched.
+ (ada_template_to_fixed_record_type_1): Fix comment.
+
2008-09-30 Joel Brobecker <brobecker@adacore.com>
* ada-lang.c (standard_exc): New static constant.
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 45a59f2c57c..53505165926 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -6403,9 +6403,19 @@ ada_lookup_struct_elt_type (struct type *type, char *name, int refok,
for (j = TYPE_NFIELDS (field_type) - 1; j >= 0; j -= 1)
{
+ /* FIXME pnh 2008/01/26: We check for a field that is
+ NOT wrapped in a struct, since the compiler sometimes
+ generates these for unchecked variant types. Revisit
+ if the compiler changes this practice. */
+ char *v_field_name = TYPE_FIELD_NAME (field_type, j);
disp = 0;
- t = ada_lookup_struct_elt_type (TYPE_FIELD_TYPE (field_type, j),
- name, 0, 1, &disp);
+ if (v_field_name != NULL
+ && field_name_match (v_field_name, name))
+ t = ada_check_typedef (TYPE_FIELD_TYPE (field_type, j));
+ else
+ t = ada_lookup_struct_elt_type (TYPE_FIELD_TYPE (field_type, j),
+ name, 0, 1, &disp);
+
if (t != NULL)
{
if (dispp != NULL)
@@ -6442,6 +6452,20 @@ BadName:
}
/* Assuming that VAR_TYPE is the type of a variant part of a record (a union),
+ within a value of type OUTER_TYPE, return true iff VAR_TYPE
+ represents an unchecked union (that is, the variant part of a
+ record that is named in an Unchecked_Union pragma). */
+
+static int
+is_unchecked_variant (struct type *var_type, struct type *outer_type)
+{
+ char *discrim_name = ada_variant_discrim_name (var_type);
+ return (ada_lookup_struct_elt_type (outer_type, discrim_name, 0, 1, NULL)
+ == NULL);
+}
+
+
+/* Assuming that VAR_TYPE is the type of a variant part of a record (a union),
within a value of type OUTER_TYPE that is stored in GDB at
OUTER_VALADDR, determine which variant clause (field number in VAR_TYPE,
numbering from 0) is applicable. Returns -1 if none are. */
@@ -6812,6 +6836,7 @@ empty_record (struct objfile *objfile)
TYPE_CODE (type) = TYPE_CODE_STRUCT;
TYPE_NFIELDS (type) = 0;
TYPE_FIELDS (type) = NULL;
+ INIT_CPLUS_SPECIFIC (type);
TYPE_NAME (type) = "<empty>";
TYPE_TAG_NAME (type) = NULL;
TYPE_LENGTH (type) = 0;
@@ -6933,7 +6958,7 @@ ada_template_to_fixed_record_type_1 (struct type *type,
}
/* We handle the variant part, if any, at the end because of certain
- odd cases in which it is re-ordered so as NOT the last field of
+ odd cases in which it is re-ordered so as NOT to be the last field of
the record. This can happen in the presence of representation
clauses. */
if (variant_field >= 0)
@@ -7180,7 +7205,8 @@ to_fixed_record_type (struct type *type0, const gdb_byte *valaddr,
union type. Any necessary discriminants' values should be in DVAL,
a record value. That is, this routine selects the appropriate
branch of the union at ADDR according to the discriminant value
- indicated in the union's type name. */
+ indicated in the union's type name. Returns VAR_TYPE0 itself if
+ it represents a variant subject to a pragma Unchecked_Union. */
static struct type *
to_fixed_variant_branch_type (struct type *var_type0, const gdb_byte *valaddr,
@@ -7200,6 +7226,8 @@ to_fixed_variant_branch_type (struct type *var_type0, const gdb_byte *valaddr,
if (templ_type != NULL)
var_type = templ_type;
+ if (is_unchecked_variant (var_type, value_type (dval)))
+ return var_type0;
which =
ada_which_variant_applies (var_type,
value_type (dval), value_contents (dval));