handle DW_AT_type on an enumeration

Message ID 87zjk6gszd.fsf@fleche.redhat.com
State Committed
Headers

Commit Message

Tom Tromey March 31, 2014, 5:47 p.m. UTC
  >>>>> "Mark" == Mark Wielaard <mjw@redhat.com> writes:

Mark> I build and did a make check against GCC with this patch applied:
Mark> http://gcc.gnu.org/ml/gcc-patches/2014-03/msg01448.html
Mark> And saw no regressions (and the new test passes) on RHEL6 x86_64.

Thanks.

>> @@ -13247,6 +13255,20 @@ read_enumeration_type (struct die_info
>> *die, struct dwarf2_cu *cu)
>> /* Finish the creation of this type by using the enum's children.  */
>> update_enumeration_type_from_children (die, type, cu);

Mark> You might want to add a comment here that you are still calling
Mark> update_enumeration_type_from_children to guess the TYPE_FLAG_ENUM even
Mark> though you will drop the TYPE_UNSIGNED guess later. At least I was a
Mark> little confused at first why you still called
Mark> update_enumeration_type_from_children in case you already knew the type.

I've added

  /* Finish the creation of this type by using the enum's children.
     We must call this even when the underlying type has been provided
     so that we can determine if we're looking at a "flag" enum.  */
  update_enumeration_type_from_children (die, type, cu);

New patch appended.

Tom
  

Comments

Tom Tromey April 14, 2014, 6:06 p.m. UTC | #1
Tom> +2014-03-31  Tom Tromey  <tromey@redhat.com>
Tom> +
Tom> +	* dwarf2read.c (read_enumeration_type): Handle DW_AT_type.

I'm checking this in now.

Tom
  

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 25ab6fa..341287b 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,7 @@ 
+2014-03-31  Tom Tromey  <tromey@redhat.com>
+
+	* dwarf2read.c (read_enumeration_type): Handle DW_AT_type.
+
 2014-03-30  Doug Evans  <xdje42@gmail.com>
 
 	* infrun.c (set_last_target_status): New function.
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 64f7383..964c956 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -13224,6 +13224,14 @@  read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
   if (name != NULL)
     TYPE_TAG_NAME (type) = name;
 
+  attr = dwarf2_attr (die, DW_AT_type, cu);
+  if (attr != NULL)
+    {
+      struct type *underlying_type = die_type (die, cu);
+
+      TYPE_TARGET_TYPE (type) = underlying_type;
+    }
+
   attr = dwarf2_attr (die, DW_AT_byte_size, cu);
   if (attr)
     {
@@ -13242,9 +13250,25 @@  read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
   if (die_is_declaration (die, cu))
     TYPE_STUB (type) = 1;
 
-  /* Finish the creation of this type by using the enum's children.  */
+  /* Finish the creation of this type by using the enum's children.
+     We must call this even when the underlying type has been provided
+     so that we can determine if we're looking at a "flag" enum.  */
   update_enumeration_type_from_children (die, type, cu);
 
+  /* If this type has an underlying type that is not a stub, then we
+     may use its attributes.  We always use the "unsigned" attribute
+     in this situation, because ordinarily we guess whether the type
+     is unsigned -- but the guess can be wrong and the underlying type
+     can tell us the reality.  However, we defer to a local size
+     attribute if one exists, because this lets the compiler override
+     the underlying type if needed.  */
+  if (TYPE_TARGET_TYPE (type) != NULL && !TYPE_STUB (TYPE_TARGET_TYPE (type)))
+    {
+      TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TYPE_TARGET_TYPE (type));
+      if (TYPE_LENGTH (type) == 0)
+	TYPE_LENGTH (type) = TYPE_LENGTH (TYPE_TARGET_TYPE (type));
+    }
+
   return set_die_type (die, type, cu);
 }
 
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 569c899..0711f14 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,7 @@ 
+2014-03-31  Tom Tromey  <tromey@redhat.com>
+
+	* gdb.dwarf2/enum-type.exp: New file.
+
 2014-03-31  Yao Qi  <yao@codesourcery.com>
 
 	* gdb.base/source-dir.exp: Allow ';' as a directory separator.
diff --git a/gdb/testsuite/gdb.dwarf2/enum-type.exp b/gdb/testsuite/gdb.dwarf2/enum-type.exp
new file mode 100644
index 0000000..60457a6
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/enum-type.exp
@@ -0,0 +1,60 @@ 
+# Copyright 2014 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 dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+if {![dwarf2_support]} {
+    return 0
+}
+
+standard_testfile main.c enum-type-dw.S
+
+# Make some DWARF for the test.
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+    cu {} {
+	DW_TAG_compile_unit {
+                {DW_AT_language @DW_LANG_C}
+                {DW_AT_name     enum-type-dw.c}
+                {DW_AT_comp_dir /tmp}
+        } {
+	    declare_labels integer_label array_elt_label array_label \
+                big_array_label
+
+            integer_label: DW_TAG_base_type {
+                {DW_AT_byte_size 4 DW_FORM_sdata}
+                {DW_AT_encoding  @DW_ATE_signed}
+                {DW_AT_name      integer}
+            }
+
+	    DW_TAG_enumeration_type {
+		{DW_AT_name E}
+		{DW_AT_type :$integer_label}
+	    } {
+		DW_TAG_enumerator {
+		    {DW_AT_name ONE}
+		    {DW_AT_const_value 1}
+		}
+	    }
+	}
+    }
+}
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} \
+	  [list $srcfile $asm_file] {nodebug}] } {
+    return -1
+}
+
+gdb_test "print sizeof(enum E)" " = 4"