[v2,9/9] Simplify C++ type-printing

Message ID 20231027-field-bits-v2-9-cbec64f2136a@adacore.com
State New
Headers
Series Remove char-based bitfield macros |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-arm success Testing passed

Commit Message

Tom Tromey Oct. 27, 2023, 5:36 p.m. UTC
  The C++ type-printing code had its own variant of the accessibility
enum.  This patch removes this and changes the code to use the new one
from gdbtypes.h.

This patch also changes the C++ code to recognize the default
accessibility of a class.  This makes ptype a bit more C++-like, and
lets us remove a chunk of questionable code.
---
 gdb/c-typeprint.c                        | 136 +++++++------------------------
 gdb/testsuite/gdb.base/ptype-offsets.exp |   6 --
 2 files changed, 30 insertions(+), 112 deletions(-)
  

Patch

diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c
index 4a0c6950b0c..40f69481f07 100644
--- a/gdb/c-typeprint.c
+++ b/gdb/c-typeprint.c
@@ -33,16 +33,6 @@ 
 #include "cp-abi.h"
 #include "cp-support.h"
 
-/* A list of access specifiers used for printing.  */
-
-enum access_specifier
-{
-  s_none,
-  s_public,
-  s_private,
-  s_protected
-};
-
 static void c_type_print_varspec_suffix (struct type *, struct ui_file *, int,
 					 int, int,
 					 enum language,
@@ -866,85 +856,32 @@  print_spaces_filtered_with_print_options
 /* Output an access specifier to STREAM, if needed.  LAST_ACCESS is the
    last access specifier output (typically returned by this function).  */
 
-static enum access_specifier
+static accessibility
 output_access_specifier (struct ui_file *stream,
-			 enum access_specifier last_access,
-			 int level, bool is_protected, bool is_private,
+			 accessibility last_access,
+			 int level, accessibility new_access,
 			 const struct type_print_options *flags)
 {
-  if (is_protected)
+  if (last_access == new_access)
+    return new_access;
+
+  if (new_access == accessibility::PROTECTED)
     {
-      if (last_access != s_protected)
-	{
-	  last_access = s_protected;
-	  print_spaces_filtered_with_print_options (level + 2, stream, flags);
-	  gdb_printf (stream, "protected:\n");
-	}
+      print_spaces_filtered_with_print_options (level + 2, stream, flags);
+      gdb_printf (stream, "protected:\n");
     }
-  else if (is_private)
+  else if (new_access == accessibility::PRIVATE)
     {
-      if (last_access != s_private)
-	{
-	  last_access = s_private;
-	  print_spaces_filtered_with_print_options (level + 2, stream, flags);
-	  gdb_printf (stream, "private:\n");
-	}
+      print_spaces_filtered_with_print_options (level + 2, stream, flags);
+      gdb_printf (stream, "private:\n");
     }
   else
     {
-      if (last_access != s_public)
-	{
-	  last_access = s_public;
-	  print_spaces_filtered_with_print_options (level + 2, stream, flags);
-	  gdb_printf (stream, "public:\n");
-	}
+      print_spaces_filtered_with_print_options (level + 2, stream, flags);
+      gdb_printf (stream, "public:\n");
     }
 
-  return last_access;
-}
-
-/* Return true if an access label (i.e., "public:", "private:",
-   "protected:") needs to be printed for TYPE.  */
-
-static bool
-need_access_label_p (struct type *type)
-{
-  if (type->is_declared_class ())
-    {
-      for (int i = TYPE_N_BASECLASSES (type); i < type->num_fields (); i++)
-	if (!type->field (i).is_private ())
-	  return true;
-      for (int j = 0; j < TYPE_NFN_FIELDS (type); j++)
-	for (int i = 0; i < TYPE_FN_FIELDLIST_LENGTH (type, j); i++)
-	  if (!TYPE_FN_FIELD_PRIVATE (TYPE_FN_FIELDLIST1 (type,
-							  j), i))
-	    return true;
-      for (int i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (type); ++i)
-	if (!TYPE_TYPEDEF_FIELD_PRIVATE (type, i))
-	  return true;
-    }
-  else
-    {
-      for (int i = TYPE_N_BASECLASSES (type); i < type->num_fields (); i++)
-	if (!type->field (i).is_public ())
-	  return true;
-      for (int j = 0; j < TYPE_NFN_FIELDS (type); j++)
-	{
-	  for (int i = 0; i < TYPE_FN_FIELDLIST_LENGTH (type, j); i++)
-	    if (TYPE_FN_FIELD_PROTECTED (TYPE_FN_FIELDLIST1 (type,
-							     j), i)
-		|| TYPE_FN_FIELD_PRIVATE (TYPE_FN_FIELDLIST1 (type,
-							      j),
-					  i))
-	      return true;
-	}
-      for (int i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (type); ++i)
-	if (TYPE_TYPEDEF_FIELD_PROTECTED (type, i)
-	    || TYPE_TYPEDEF_FIELD_PRIVATE (type, i))
-	  return true;
-    }
-
-  return false;
+  return new_access;
 }
 
 /* Helper function that temporarily disables FLAGS->PRINT_OFFSETS,
@@ -1067,17 +1004,9 @@  c_type_print_base_struct_union (struct type *type, struct ui_file *stream,
 			metadata_style.style ().ptr (), nullptr);
 	}
 
-      /* Start off with no specific section type, so we can print
-	 one for the first field we find, and use that section type
-	 thereafter until we find another type.  */
-
-      enum access_specifier section_type = s_none;
-
-      /* For a class, if all members are private, there's no need
-	 for a "private:" label; similarly, for a struct or union
-	 masquerading as a class, if all members are public, there's
-	 no need for a "public:" label.  */
-      bool need_access_label = need_access_label_p (type);
+      accessibility section_type = (type->is_declared_class ()
+				    ? accessibility::PRIVATE
+				    : accessibility::PUBLIC);
 
       /* If there is a base class for this type,
 	 do not print the field that it occupies.  */
@@ -1098,13 +1027,10 @@  c_type_print_base_struct_union (struct type *type, struct ui_file *stream,
 	      || type->field (i).is_artificial ())
 	    continue;
 
-	  if (need_access_label)
-	    {
-	      section_type = output_access_specifier
-		(stream, section_type, level,
-		 type->field (i).is_protected (),
-		 type->field (i).is_private (), flags);
-	    }
+	  section_type
+	    = output_access_specifier (stream, section_type, level,
+				       type->field (i).get_accessibility (),
+				       flags);
 
 	  bool is_static = type->field (i).is_static ();
 
@@ -1176,7 +1102,7 @@  c_type_print_base_struct_union (struct type *type, struct ui_file *stream,
 	    if (!TYPE_FN_FIELD_ARTIFICIAL (f, j))
 	      real_len++;
 	}
-      if (real_len > 0 && section_type != s_none)
+      if (real_len > 0)
 	gdb_printf (stream, "\n");
 
       /* C++: print out the methods.  */
@@ -1207,8 +1133,8 @@  c_type_print_base_struct_union (struct type *type, struct ui_file *stream,
 	      QUIT;
 	      section_type = output_access_specifier
 		(stream, section_type, level,
-		 TYPE_FN_FIELD_PROTECTED (f, j),
-		 TYPE_FN_FIELD_PRIVATE (f, j), flags);
+		 TYPE_FN_FIELD (f, j).accessibility,
+		 flags);
 
 	      print_spaces_filtered_with_print_options (level + 4, stream,
 							flags);
@@ -1334,13 +1260,11 @@  c_type_print_base_struct_union (struct type *type, struct ui_file *stream,
 	      gdb_assert (target->code () == TYPE_CODE_TYPEDEF);
 	      target = target->target_type ();
 
-	      if (need_access_label)
-		{
-		  section_type = output_access_specifier
-		    (stream, section_type, level,
-		     TYPE_TYPEDEF_FIELD_PROTECTED (type, i),
-		     TYPE_TYPEDEF_FIELD_PRIVATE (type, i), flags);
-		}
+	      section_type = (output_access_specifier
+			      (stream, section_type, level,
+			       TYPE_TYPEDEF_FIELD (type, i).accessibility,
+			       flags));
+
 	      print_spaces_filtered_with_print_options (level + 4, stream,
 							flags);
 	      gdb_printf (stream, "typedef ");
diff --git a/gdb/testsuite/gdb.base/ptype-offsets.exp b/gdb/testsuite/gdb.base/ptype-offsets.exp
index 2cfc70f1686..f36bd2fdedf 100644
--- a/gdb/testsuite/gdb.base/ptype-offsets.exp
+++ b/gdb/testsuite/gdb.base/ptype-offsets.exp
@@ -36,7 +36,6 @@  if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
 gdb_test "ptype /o struct abc" \
     [string_to_regexp [multi_line \
 "/* offset      |    size */  type = struct abc \{" \
-"                             public:" \
 "/*      8      |       8 */    void *field1;" \
 "/*     16: 0   |       4 */    unsigned int field2 : 1;" \
 "/* XXX  7-bit hole       */" \
@@ -61,7 +60,6 @@  gdb_test "ptype /o struct abc" \
 gdb_test "ptype /ox struct abc" \
     [string_to_regexp [multi_line \
 "/* offset      |    size */  type = struct abc {" \
-"                             public:" \
 "/* 0x0008      |  0x0008 */    void *field1;" \
 "/* 0x0010: 0x0 |  0x0004 */    unsigned int field2 : 1;" \
 "/* XXX  7-bit hole       */" \
@@ -86,7 +84,6 @@  gdb_test "ptype /ox struct abc" \
 gdb_test "ptype /oTM struct abc" \
     [string_to_regexp [multi_line \
 "/* offset      |    size */  type = struct abc \{" \
-"                             public:" \
 "/*      8      |       8 */    void *field1;" \
 "/*     16: 0   |       4 */    unsigned int field2 : 1;" \
 "/* XXX  7-bit hole       */" \
@@ -116,7 +113,6 @@  gdb_test "ptype /oTM struct abc" \
 gdb_test "ptype /TMo struct abc" \
     [string_to_regexp [multi_line \
 "/* offset      |    size */  type = struct abc \{" \
-"                             public:" \
 "/*      8      |       8 */    void *field1;" \
 "/*     16: 0   |       4 */    unsigned int field2 : 1;" \
 "/* XXX  7-bit hole       */" \
@@ -421,7 +417,6 @@  with_test_prefix "with_hex_default" {
   gdb_test "ptype /o struct abc" \
       [string_to_regexp [multi_line \
   "/* offset      |    size */  type = struct abc \{" \
-  "                             public:" \
   "/* 0x0008      |  0x0008 */    void *field1;" \
   "/* 0x0010: 0x0 |  0x0004 */    unsigned int field2 : 1;" \
   "/* XXX  7-bit hole       */" \
@@ -445,7 +440,6 @@  with_test_prefix "with_hex_default" {
   gdb_test "ptype /od struct abc" \
       [string_to_regexp [multi_line \
   "/* offset      |    size */  type = struct abc \{" \
-  "                             public:" \
   "/*      8      |       8 */    void *field1;" \
   "/*     16: 0   |       4 */    unsigned int field2 : 1;" \
   "/* XXX  7-bit hole       */" \