Record and output access specifiers for nested typedefs

We currently do not record access information for typedefs defined inside
classes.  Consider:

struct foo
{
   typedef int PUBLIC;
 private:
   typedef int PRIVATE;
   PRIVATE b;
};

(gdb) ptype foo
type = struct foo {
  private:
    PRIVATE b;

    typedef int PRIVATE;
    typedef int PUBLIC;
}

This patch fixes this:

(gdb) ptype foo
type = struct foo {
  private:
    PRIVATE b;

    typedef int PRIVATE;
  public:
    typedef int PUBLIC;
}

gdb/ChangeLog:

	* c-typeprint.c (enum access_specifier): Moved here from
	c_type_print_base.
	(output_access_specifier): New function.
	(c_type_print_base): Consider typedefs when assessing
	whether access labels are needed.
	Use output_access_specifier as needed.
	Output access specifier for typedefs, if needed.
	* dwarf2read.c (dwarf2_add_typedef): Record DW_AT_accessibility.
	* gdbtypes.h (struct typedef_field) <is_protected, is_private>: New
	fields.
	(TYPE_TYPEDEF_FIELD_PROTECTED, TYPE_TYPEDEF_FIELD_PRIVATE): New
	accessor macros.

gdb/testsuite/ChangeLog:

	* gdb.cp/classes.cc (class_with_typedefs, class_with_public_typedef)
	(class_with_protected_typedef, class_with_private_typedef)
	(struct_with_public_typedef, struct_with_protected_typedef)
	(struct_with_private_typedef): New classes/structs.
	* gdb.cp/classes.exp (test_ptype_class_objects): Add tests for
	typedefs and access specifiers.
This commit is contained in:
Keith Seitz
2017-10-16 17:19:29 -07:00
parent 087ce8fa02
commit c191a6875b
5 changed files with 264 additions and 59 deletions

View File

@ -32,6 +32,16 @@
#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_prefix (struct type *,
struct ui_file *,
int, int, int,
@ -826,6 +836,45 @@ c_type_print_template_args (const struct type_print_options *flags,
fputs_filtered (_("] "), stream);
}
/* 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
output_access_specifier (struct ui_file *stream,
enum access_specifier last_access,
int level, bool is_protected, bool is_private)
{
if (is_protected)
{
if (last_access != s_protected)
{
last_access = s_protected;
fprintfi_filtered (level + 2, stream,
"protected:\n");
}
}
else if (is_private)
{
if (last_access != s_private)
{
last_access = s_private;
fprintfi_filtered (level + 2, stream,
"private:\n");
}
}
else
{
if (last_access != s_public)
{
last_access = s_public;
fprintfi_filtered (level + 2, stream,
"public:\n");
}
}
return last_access;
}
/* Print the name of the type (or the ultimate pointer target,
function value or array element), or the description of a structure
or union.
@ -850,11 +899,7 @@ c_type_print_base (struct type *type, struct ui_file *stream,
{
int i;
int len, real_len;
enum
{
s_none, s_public, s_private, s_protected
}
section_type;
enum access_specifier section_type;
int need_access_label = 0;
int j, len2;
@ -1034,6 +1079,18 @@ c_type_print_base (struct type *type, struct ui_file *stream,
break;
}
}
QUIT;
if (!need_access_label)
{
for (i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (type); ++i)
{
if (!TYPE_TYPEDEF_FIELD_PRIVATE (type, i))
{
need_access_label = 1;
break;
}
}
}
}
else
{
@ -1068,6 +1125,19 @@ c_type_print_base (struct type *type, struct ui_file *stream,
break;
}
}
QUIT;
if (!need_access_label)
{
for (i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (type); ++i)
{
if (TYPE_TYPEDEF_FIELD_PROTECTED (type, i)
|| TYPE_TYPEDEF_FIELD_PRIVATE (type, i))
{
need_access_label = 1;
break;
}
}
}
}
/* If there is a base class for this type,
@ -1088,33 +1158,10 @@ c_type_print_base (struct type *type, struct ui_file *stream,
if (need_access_label)
{
if (TYPE_FIELD_PROTECTED (type, i))
{
if (section_type != s_protected)
{
section_type = s_protected;
fprintfi_filtered (level + 2, stream,
"protected:\n");
}
}
else if (TYPE_FIELD_PRIVATE (type, i))
{
if (section_type != s_private)
{
section_type = s_private;
fprintfi_filtered (level + 2, stream,
"private:\n");
}
}
else
{
if (section_type != s_public)
{
section_type = s_public;
fprintfi_filtered (level + 2, stream,
"public:\n");
}
}
section_type = output_access_specifier
(stream, section_type, level,
TYPE_FIELD_PROTECTED (type, i),
TYPE_FIELD_PRIVATE (type, i));
}
print_spaces_filtered (level + 4, stream);
@ -1187,33 +1234,10 @@ c_type_print_base (struct type *type, struct ui_file *stream,
inner_cleanup = make_cleanup (null_cleanup, NULL);
QUIT;
if (TYPE_FN_FIELD_PROTECTED (f, j))
{
if (section_type != s_protected)
{
section_type = s_protected;
fprintfi_filtered (level + 2, stream,
"protected:\n");
}
}
else if (TYPE_FN_FIELD_PRIVATE (f, j))
{
if (section_type != s_private)
{
section_type = s_private;
fprintfi_filtered (level + 2, stream,
"private:\n");
}
}
else
{
if (section_type != s_public)
{
section_type = s_public;
fprintfi_filtered (level + 2, stream,
"public:\n");
}
}
section_type = output_access_specifier
(stream, section_type, level,
TYPE_FN_FIELD_PROTECTED (f, j),
TYPE_FN_FIELD_PRIVATE (f, j));
print_spaces_filtered (level + 4, stream);
if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
@ -1325,6 +1349,13 @@ c_type_print_base (struct type *type, struct ui_file *stream,
gdb_assert (TYPE_CODE (target) == TYPE_CODE_TYPEDEF);
target = TYPE_TARGET_TYPE (target);
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));
}
print_spaces_filtered (level + 4, stream);
fprintf_filtered (stream, "typedef ");