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:
parent
fc076a47fd
commit
a27ed7d613
2 changed files with 410 additions and 434 deletions
|
@ -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>
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue