Reorganize code to handle TYPE_CODE_{STRUCT,UNION} on 'c_type_print_base'

While doing the 'ptype /o' work, I noticed that 'c_type_print_base'
was very long, with a big amount of code just to handle the case of
TYPE_CODE_{STRUCT,UNION}.  This made working with the function a bit
difficult, specially because of the level of indentation.

This commit moves this part of the code to their own functions.  Now
we have a 'c_type_print_base_struct_union' with most of the code, and
also 'need_access_label_p', which is a subset of the code that was
also a good candidate for having its own function.

gdb/ChangeLog:
2017-12-15  Sergio Durigan Junior  <sergiodj@redhat.com>

	* c-typeprint.c (need_access_label_p): New function.
	(c_type_print_base_struct_union): New function.
	(c_type_print_base): Move code to handle
	TYPE_CODE_{STRUCT,UNION} to the functions mentioned above.
This commit is contained in:
Sergio Durigan Junior 2017-12-11 11:57:19 -05:00
parent fc076a47fd
commit a27ed7d613
2 changed files with 410 additions and 434 deletions

View file

@ -1,3 +1,10 @@
2017-12-15 Sergio Durigan Junior <sergiodj@redhat.com>
* c-typeprint.c (need_access_label_p): New function.
(c_type_print_base_struct_union): New function.
(c_type_print_base): Move code to handle
TYPE_CODE_{STRUCT,UNION} to the functions mentioned above.
2017-12-15 Richard Henderson <rth@redhat.com>
Uros Bizjak <ubizjak@gmail.com>

View file

@ -875,90 +875,65 @@ output_access_specifier (struct ui_file *stream,
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.
/* Return true is an access label (i.e., "public:", "private:",
"protected:") needs to be printed for TYPE. */
SHOW positive means print details about the type (e.g. enum
values), and print structure elements passing SHOW - 1 for show.
SHOW negative means just print the type name or struct tag if there
is one. If there is no name, print something sensible but concise
like "struct {...}".
SHOW zero means just print the type name or struct tag if there is
one. If there is no name, print something sensible but not as
concise like "struct {int x; int y;}".
LEVEL is the number of spaces to indent by.
We increase it for some recursive calls. */
void
c_type_print_base (struct type *type, struct ui_file *stream,
int show, int level, const struct type_print_options *flags)
static bool
need_access_label_p (struct type *type)
{
int i;
int len, real_len;
enum access_specifier section_type;
int need_access_label = 0;
int j, len2;
if (TYPE_DECLARED_CLASS (type))
{
QUIT;
if (type == NULL)
{
fputs_filtered (_("<type unknown>"), stream);
return;
for (int i = TYPE_N_BASECLASSES (type); i < TYPE_NFIELDS (type); i++)
if (!TYPE_FIELD_PRIVATE (type, i))
return true;
QUIT;
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;
QUIT;
for (int i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (type); ++i)
if (!TYPE_TYPEDEF_FIELD_PRIVATE (type, i))
return true;
}
/* When SHOW is zero or less, and there is a valid type name, then
always just print the type name directly from the type. */
/* If we have "typedef struct foo {. . .} bar;" do we want to print
it as "struct foo" or as "bar"? Pick the latter, because C++
folk tend to expect things like "class5 *foo" rather than "struct
class5 *foo". */
if (show <= 0
&& TYPE_NAME (type) != NULL)
{
c_type_print_modifier (type, stream, 0, 1);
print_name_maybe_canonical (TYPE_NAME (type), flags, stream);
return;
}
type = check_typedef (type);
switch (TYPE_CODE (type))
{
case TYPE_CODE_TYPEDEF:
/* If we get here, the typedef doesn't have a name, and we
couldn't resolve TYPE_TARGET_TYPE. Not much we can do. */
gdb_assert (TYPE_NAME (type) == NULL);
gdb_assert (TYPE_TARGET_TYPE (type) == NULL);
fprintf_filtered (stream, _("<unnamed typedef>"));
break;
case TYPE_CODE_FUNC:
case TYPE_CODE_METHOD:
if (TYPE_TARGET_TYPE (type) == NULL)
type_print_unknown_return_type (stream);
else
c_type_print_base (TYPE_TARGET_TYPE (type),
stream, show, level, flags);
break;
case TYPE_CODE_ARRAY:
case TYPE_CODE_PTR:
case TYPE_CODE_MEMBERPTR:
case TYPE_CODE_REF:
case TYPE_CODE_RVALUE_REF:
case TYPE_CODE_METHODPTR:
c_type_print_base (TYPE_TARGET_TYPE (type),
stream, show, level, flags);
break;
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
{
QUIT;
for (int i = TYPE_N_BASECLASSES (type); i < TYPE_NFIELDS (type); i++)
if (TYPE_FIELD_PRIVATE (type, i) || TYPE_FIELD_PROTECTED (type, i))
return true;
QUIT;
for (int j = 0; j < TYPE_NFN_FIELDS (type); j++)
{
QUIT;
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;
}
QUIT;
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;
}
/* Helper for 'c_type_print_base' that handles structs and unions.
For a description of the arguments, see 'c_type_print_base'. */
static void
c_type_print_base_struct_union (struct type *type, struct ui_file *stream,
int show, int level,
const struct type_print_options *flags)
{
struct type_print_options local_flags = *flags;
struct type_print_options semi_local_flags = *flags;
struct cleanup *local_cleanups = make_cleanup (null_cleanup, NULL);
@ -1044,108 +1019,20 @@ c_type_print_base (struct type *type, struct ui_file *stream,
one for the first field we find, and use that section type
thereafter until we find another type. */
section_type = s_none;
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. */
if (TYPE_DECLARED_CLASS (type))
{
QUIT;
len = TYPE_NFIELDS (type);
for (i = TYPE_N_BASECLASSES (type); i < len; i++)
if (!TYPE_FIELD_PRIVATE (type, i))
{
need_access_label = 1;
break;
}
QUIT;
if (!need_access_label)
{
len2 = TYPE_NFN_FIELDS (type);
for (j = 0; j < len2; j++)
{
len = TYPE_FN_FIELDLIST_LENGTH (type, j);
for (i = 0; i < len; i++)
if (!TYPE_FN_FIELD_PRIVATE (TYPE_FN_FIELDLIST1 (type,
j), i))
{
need_access_label = 1;
break;
}
if (need_access_label)
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
{
QUIT;
len = TYPE_NFIELDS (type);
for (i = TYPE_N_BASECLASSES (type); i < len; i++)
if (TYPE_FIELD_PRIVATE (type, i)
|| TYPE_FIELD_PROTECTED (type, i))
{
need_access_label = 1;
break;
}
QUIT;
if (!need_access_label)
{
len2 = TYPE_NFN_FIELDS (type);
for (j = 0; j < len2; j++)
{
QUIT;
len = TYPE_FN_FIELDLIST_LENGTH (type, j);
for (i = 0; i < len; i++)
if (TYPE_FN_FIELD_PROTECTED (TYPE_FN_FIELDLIST1 (type,
j), i)
|| TYPE_FN_FIELD_PRIVATE (TYPE_FN_FIELDLIST1 (type,
j),
i))
{
need_access_label = 1;
break;
}
if (need_access_label)
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;
}
}
}
}
bool need_access_label = need_access_label_p (type);
/* If there is a base class for this type,
do not print the field that it occupies. */
len = TYPE_NFIELDS (type);
int len = TYPE_NFIELDS (type);
vptr_fieldno = get_vptr_fieldno (type, &basetype);
for (i = TYPE_N_BASECLASSES (type); i < len; i++)
for (int i = TYPE_N_BASECLASSES (type); i < len; i++)
{
QUIT;
@ -1191,8 +1078,8 @@ c_type_print_base (struct type *type, struct ui_file *stream,
len = TYPE_NFN_FIELDS (type);
if (!flags->print_methods)
len = 0;
real_len = 0;
for (i = 0; i < len; i++)
int real_len = 0;
for (int i = 0; i < len; i++)
{
struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
int len2 = TYPE_FN_FIELDLIST_LENGTH (type, i);
@ -1206,7 +1093,7 @@ c_type_print_base (struct type *type, struct ui_file *stream,
fprintf_filtered (stream, "\n");
/* C++: print out the methods. */
for (i = 0; i < len; i++)
for (int i = 0; i < len; i++)
{
struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i);
@ -1337,7 +1224,7 @@ c_type_print_base (struct type *type, struct ui_file *stream,
if (TYPE_NFIELDS (type) != 0 || TYPE_NFN_FIELDS (type) != 0)
fprintf_filtered (stream, "\n");
for (i = 0; i < TYPE_NESTED_TYPES_COUNT (type); ++i)
for (int i = 0; i < TYPE_NESTED_TYPES_COUNT (type); ++i)
{
print_spaces_filtered (level + 4, stream);
c_print_type (TYPE_NESTED_TYPES_FIELD_TYPE (type, i),
@ -1354,7 +1241,7 @@ c_type_print_base (struct type *type, struct ui_file *stream,
|| TYPE_NESTED_TYPES_COUNT (type) != 0)
fprintf_filtered (stream, "\n");
for (i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (type); i++)
for (int i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (type); i++)
{
struct type *target = TYPE_TYPEDEF_FIELD_TYPE (type, i);
@ -1387,7 +1274,89 @@ c_type_print_base (struct type *type, struct ui_file *stream,
}
do_cleanups (local_cleanups);
}
/* Print the name of the type (or the ultimate pointer target,
function value or array element), or the description of a structure
or union.
SHOW positive means print details about the type (e.g. enum
values), and print structure elements passing SHOW - 1 for show.
SHOW negative means just print the type name or struct tag if there
is one. If there is no name, print something sensible but concise
like "struct {...}".
SHOW zero means just print the type name or struct tag if there is
one. If there is no name, print something sensible but not as
concise like "struct {int x; int y;}".
LEVEL is the number of spaces to indent by.
We increase it for some recursive calls. */
void
c_type_print_base (struct type *type, struct ui_file *stream,
int show, int level, const struct type_print_options *flags)
{
int i;
int len;
QUIT;
if (type == NULL)
{
fputs_filtered (_("<type unknown>"), stream);
return;
}
/* When SHOW is zero or less, and there is a valid type name, then
always just print the type name directly from the type. */
/* If we have "typedef struct foo {. . .} bar;" do we want to print
it as "struct foo" or as "bar"? Pick the latter, because C++
folk tend to expect things like "class5 *foo" rather than "struct
class5 *foo". */
if (show <= 0
&& TYPE_NAME (type) != NULL)
{
c_type_print_modifier (type, stream, 0, 1);
print_name_maybe_canonical (TYPE_NAME (type), flags, stream);
return;
}
type = check_typedef (type);
switch (TYPE_CODE (type))
{
case TYPE_CODE_TYPEDEF:
/* If we get here, the typedef doesn't have a name, and we
couldn't resolve TYPE_TARGET_TYPE. Not much we can do. */
gdb_assert (TYPE_NAME (type) == NULL);
gdb_assert (TYPE_TARGET_TYPE (type) == NULL);
fprintf_filtered (stream, _("<unnamed typedef>"));
break;
case TYPE_CODE_FUNC:
case TYPE_CODE_METHOD:
if (TYPE_TARGET_TYPE (type) == NULL)
type_print_unknown_return_type (stream);
else
c_type_print_base (TYPE_TARGET_TYPE (type),
stream, show, level, flags);
break;
case TYPE_CODE_ARRAY:
case TYPE_CODE_PTR:
case TYPE_CODE_MEMBERPTR:
case TYPE_CODE_REF:
case TYPE_CODE_RVALUE_REF:
case TYPE_CODE_METHODPTR:
c_type_print_base (TYPE_TARGET_TYPE (type),
stream, show, level, flags);
break;
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
c_type_print_base_struct_union (type, stream, show, level, flags);
break;
case TYPE_CODE_ENUM: