forked from Imagelibrary/binutils-gdb
treat identical enum types as the same type
This is to avoid an unnecessary multiple-choice menu for an
expression involving an enumeral declared in two types, when
the second type is an identical copy of the first type. This
happens in the following situation:
type Color is (Black, Red, Green, Blue, White);
type RGB_Color is new Color range Red .. Blue;
In that case, an implict type is created, and is used as the base
type for type RGB_Color. This base type is a copy of type Color.
We've added some extensive comments explaining the situation and
our approach further.
gdb/ChangeLog:
* ada-lang.c (ada_identical_enum_types_p): New function.
(symbols_are_identical_enums): New function.
(remove_extra_symbols): Do nothing if NSYMS < 2.
Use symbols_are_identical_enums.
gdb/testsuite/ChangeLog:
* gdb.ada/same_enum: New testcase.
This commit is contained in:
@@ -1,3 +1,10 @@
|
||||
2011-07-01 Joel Brobecker <brobecker@adacore.com>
|
||||
|
||||
* ada-lang.c (ada_identical_enum_types_p): New function.
|
||||
(symbols_are_identical_enums): New function.
|
||||
(remove_extra_symbols): Do nothing if NSYMS < 2.
|
||||
Use symbols_are_identical_enums.
|
||||
|
||||
2011-07-01 Joel Brobecker <brobecker@adacore.com>
|
||||
|
||||
* ada-valprint.c (ada_value_print): Handle typedefs.
|
||||
|
||||
124
gdb/ada-lang.c
124
gdb/ada-lang.c
@@ -4365,6 +4365,108 @@ is_nondebugging_type (struct type *type)
|
||||
return (name != NULL && strcmp (name, "<variable, no debug info>") == 0);
|
||||
}
|
||||
|
||||
/* Return nonzero if TYPE1 and TYPE2 are two enumeration types
|
||||
that are deemed "identical" for practical purposes.
|
||||
|
||||
This function assumes that TYPE1 and TYPE2 are both TYPE_CODE_ENUM
|
||||
types and that their number of enumerals is identical (in other
|
||||
words, TYPE_NFIELDS (type1) == TYPE_NFIELDS (type2)). */
|
||||
|
||||
static int
|
||||
ada_identical_enum_types_p (struct type *type1, struct type *type2)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* The heuristic we use here is fairly conservative. We consider
|
||||
that 2 enumerate types are identical if they have the same
|
||||
number of enumerals and that all enumerals have the same
|
||||
underlying value and name. */
|
||||
|
||||
/* All enums in the type should have an identical underlying value. */
|
||||
for (i = 0; i < TYPE_NFIELDS (type1); i++)
|
||||
if (TYPE_FIELD_BITPOS (type1, i) != TYPE_FIELD_BITPOS (type2, i))
|
||||
return 0;
|
||||
|
||||
/* All enumerals should also have the same name (modulo any numerical
|
||||
suffix). */
|
||||
for (i = 0; i < TYPE_NFIELDS (type1); i++)
|
||||
{
|
||||
char *name_1 = TYPE_FIELD_NAME (type1, i);
|
||||
char *name_2 = TYPE_FIELD_NAME (type2, i);
|
||||
int len_1 = strlen (name_1);
|
||||
int len_2 = strlen (name_2);
|
||||
|
||||
ada_remove_trailing_digits (TYPE_FIELD_NAME (type1, i), &len_1);
|
||||
ada_remove_trailing_digits (TYPE_FIELD_NAME (type2, i), &len_2);
|
||||
if (len_1 != len_2
|
||||
|| strncmp (TYPE_FIELD_NAME (type1, i),
|
||||
TYPE_FIELD_NAME (type2, i),
|
||||
len_1) != 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return nonzero if all the symbols in SYMS are all enumeral symbols
|
||||
that are deemed "identical" for practical purposes. Sometimes,
|
||||
enumerals are not strictly identical, but their types are so similar
|
||||
that they can be considered identical.
|
||||
|
||||
For instance, consider the following code:
|
||||
|
||||
type Color is (Black, Red, Green, Blue, White);
|
||||
type RGB_Color is new Color range Red .. Blue;
|
||||
|
||||
Type RGB_Color is a subrange of an implicit type which is a copy
|
||||
of type Color. If we call that implicit type RGB_ColorB ("B" is
|
||||
for "Base Type"), then type RGB_ColorB is a copy of type Color.
|
||||
As a result, when an expression references any of the enumeral
|
||||
by name (Eg. "print green"), the expression is technically
|
||||
ambiguous and the user should be asked to disambiguate. But
|
||||
doing so would only hinder the user, since it wouldn't matter
|
||||
what choice he makes, the outcome would always be the same.
|
||||
So, for practical purposes, we consider them as the same. */
|
||||
|
||||
static int
|
||||
symbols_are_identical_enums (struct ada_symbol_info *syms, int nsyms)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Before performing a thorough comparison check of each type,
|
||||
we perform a series of inexpensive checks. We expect that these
|
||||
checks will quickly fail in the vast majority of cases, and thus
|
||||
help prevent the unnecessary use of a more expensive comparison.
|
||||
Said comparison also expects us to make some of these checks
|
||||
(see ada_identical_enum_types_p). */
|
||||
|
||||
/* Quick check: All symbols should have an enum type. */
|
||||
for (i = 0; i < nsyms; i++)
|
||||
if (TYPE_CODE (SYMBOL_TYPE (syms[i].sym)) != TYPE_CODE_ENUM)
|
||||
return 0;
|
||||
|
||||
/* Quick check: They should all have the same value. */
|
||||
for (i = 1; i < nsyms; i++)
|
||||
if (SYMBOL_VALUE (syms[i].sym) != SYMBOL_VALUE (syms[0].sym))
|
||||
return 0;
|
||||
|
||||
/* Quick check: They should all have the same number of enumerals. */
|
||||
for (i = 1; i < nsyms; i++)
|
||||
if (TYPE_NFIELDS (SYMBOL_TYPE (syms[i].sym))
|
||||
!= TYPE_NFIELDS (SYMBOL_TYPE (syms[0].sym)))
|
||||
return 0;
|
||||
|
||||
/* All the sanity checks passed, so we might have a set of
|
||||
identical enumeration types. Perform a more complete
|
||||
comparison of the type of each symbol. */
|
||||
for (i = 1; i < nsyms; i++)
|
||||
if (!ada_identical_enum_types_p (SYMBOL_TYPE (syms[i].sym),
|
||||
SYMBOL_TYPE (syms[0].sym)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Remove any non-debugging symbols in SYMS[0 .. NSYMS-1] that definitely
|
||||
duplicate other symbols in the list (The only case I know of where
|
||||
this happens is when object files containing stabs-in-ecoff are
|
||||
@@ -4377,6 +4479,12 @@ remove_extra_symbols (struct ada_symbol_info *syms, int nsyms)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
/* We should never be called with less than 2 symbols, as there
|
||||
cannot be any extra symbol in that case. But it's easy to
|
||||
handle, since we have nothing to do in that case. */
|
||||
if (nsyms < 2)
|
||||
return nsyms;
|
||||
|
||||
i = 0;
|
||||
while (i < nsyms)
|
||||
{
|
||||
@@ -4428,6 +4536,22 @@ remove_extra_symbols (struct ada_symbol_info *syms, int nsyms)
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
/* If all the remaining symbols are identical enumerals, then
|
||||
just keep the first one and discard the rest.
|
||||
|
||||
Unlike what we did previously, we do not discard any entry
|
||||
unless they are ALL identical. This is because the symbol
|
||||
comparison is not a strict comparison, but rather a practical
|
||||
comparison. If all symbols are considered identical, then
|
||||
we can just go ahead and use the first one and discard the rest.
|
||||
But if we cannot reduce the list to a single element, we have
|
||||
to ask the user to disambiguate anyways. And if we have to
|
||||
present a multiple-choice menu, it's less confusing if the list
|
||||
isn't missing some choices that were identical and yet distinct. */
|
||||
if (symbols_are_identical_enums (syms, nsyms))
|
||||
nsyms = 1;
|
||||
|
||||
return nsyms;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
2011-07-01 Joel Brobecker <brobecker@adacore.com>
|
||||
|
||||
* gdb.ada/same_enum: New testcase.
|
||||
|
||||
2011-07-01 Joel Brobecker <brobecker@adacore.com>
|
||||
|
||||
* gdb.ada/ptr_typedef: New testcase.
|
||||
|
||||
37
gdb/testsuite/gdb.ada/same_enum.exp
Normal file
37
gdb/testsuite/gdb.ada/same_enum.exp
Normal file
@@ -0,0 +1,37 @@
|
||||
# Copyright 2011 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
load_lib "ada.exp"
|
||||
|
||||
set testdir "same_enum"
|
||||
set testfile "${testdir}/a"
|
||||
set srcfile ${srcdir}/${subdir}/${testfile}.adb
|
||||
set binfile ${objdir}/${subdir}/${testfile}
|
||||
|
||||
file mkdir ${objdir}/${subdir}/${testdir}
|
||||
if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug ]] != "" } {
|
||||
return -1
|
||||
}
|
||||
|
||||
clean_restart ${testfile}
|
||||
|
||||
# Try printing the value of the enumeral `red'. This is normally
|
||||
# ambiguous, as there are two distinct types that define that
|
||||
# littleral. But, from a practical standpoint, it doesn't matter
|
||||
# which one we pick, since both have the same value (in most cases,
|
||||
# it's because the two types are strongly related).
|
||||
gdb_test "print red" "= red"
|
||||
|
||||
|
||||
24
gdb/testsuite/gdb.ada/same_enum/a.adb
Normal file
24
gdb/testsuite/gdb.ada/same_enum/a.adb
Normal file
@@ -0,0 +1,24 @@
|
||||
-- Copyright 2011 Free Software Foundation, Inc.
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
with Pck; use Pck;
|
||||
|
||||
procedure A is
|
||||
FC : Color := Red;
|
||||
SC : Color := Green;
|
||||
begin
|
||||
Do_Nothing (FC'Address);
|
||||
Do_Nothing (SC'Address);
|
||||
end A;
|
||||
22
gdb/testsuite/gdb.ada/same_enum/pck.adb
Normal file
22
gdb/testsuite/gdb.ada/same_enum/pck.adb
Normal file
@@ -0,0 +1,22 @@
|
||||
-- Copyright 2011 Free Software Foundation, Inc.
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package body Pck is
|
||||
procedure Do_Nothing (A : System.Address) is
|
||||
begin
|
||||
null;
|
||||
end Do_Nothing;
|
||||
end Pck;
|
||||
|
||||
24
gdb/testsuite/gdb.ada/same_enum/pck.ads
Normal file
24
gdb/testsuite/gdb.ada/same_enum/pck.ads
Normal file
@@ -0,0 +1,24 @@
|
||||
-- Copyright 2011 Free Software Foundation, Inc.
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
with System;
|
||||
|
||||
package Pck is
|
||||
type Color is (Black, Red, Green, Blue, White);
|
||||
type RGB_Color is new Color range Red .. Blue;
|
||||
|
||||
procedure Do_Nothing (A : System.Address);
|
||||
end Pck;
|
||||
|
||||
Reference in New Issue
Block a user