Commit 1d757b09 by Eric Botcazou

Fix duplicates for anonymous structures with -fdump-ada-spec

This fixes a weakness in the way -fdump-ada-spec builds names for
anonymous structures in the C/C++ code, resulting in duplicate
identifiers under specific circumstances.

c-family/
	* c-ada-spec.c: Include bitmap.h.
	(dump_ada_double_name): Rename into...
	(dump_anonymous_type_name): ...this.  Always use the TYPE_UID.
	(dump_ada_array_type): Adjust to above renaming.  Robustify.
	(dump_nested_types_1): New function copied from...  Add
	dumped_types parameter and pass it down to dump_nested_type.
	(dump_nested_types): ...this.  Remove parent parameter.  Just
	call dump_nested_types_1 on an automatic bitmap.
	(dump_nested_type): Add dumped_types parameter.
	<ARRAY_TYPE>: Do not dump it if already present in dumped_types.
	Adjust recursive calls and adjust to above renaming.
	(dump_ada_declaration): Adjust call to dump_nested_types.
	Tidy up and adjust to above renaming.
	(dump_ada_specs): Initialize and release bitmap obstack.
parent c26007ab
2020-02-14 Eric Botcazou <ebotcazou@adacore.com>
* c-ada-spec.c: Include bitmap.h.
(dump_ada_double_name): Rename into...
(dump_anonymous_type_name): ...this. Always use the TYPE_UID.
(dump_ada_array_type): Adjust to above renaming. Robustify.
(dump_nested_types_1): New function copied from... Add dumped_types
parameter and pass it down to dump_nested_type.
(dump_nested_types): ...this. Remove parent parameter. Just call
dump_nested_types_1 on an automatic bitmap.
(dump_nested_type): Add dumped_types parameter.
<ARRAY_TYPE>: Do not dump it if already present in dumped_types.
Adjust recursive calls and adjust to above renaming.
(dump_ada_declaration): Adjust call to dump_nested_types.
Tidy up and adjust to above renaming.
(dump_ada_specs): Initialize and release bitmap obstack.
2020-02-10 Martin Sebor <msebor@redhat.com> 2020-02-10 Martin Sebor <msebor@redhat.com>
PR c/93640 PR c/93640
......
...@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic.h" #include "diagnostic.h"
#include "stringpool.h" #include "stringpool.h"
#include "attribs.h" #include "attribs.h"
#include "bitmap.h"
/* Local functions, macros and variables. */ /* Local functions, macros and variables. */
static int dump_ada_node (pretty_printer *, tree, tree, int, bool, bool); static int dump_ada_node (pretty_printer *, tree, tree, int, bool, bool);
...@@ -1475,30 +1476,21 @@ dump_ada_decl_name (pretty_printer *buffer, tree decl, bool limited_access) ...@@ -1475,30 +1476,21 @@ dump_ada_decl_name (pretty_printer *buffer, tree decl, bool limited_access)
} }
} }
/* Dump in BUFFER a name based on both T1 and T2 followed by a suffix. */ /* Dump in BUFFER a name for the type T, which is a _TYPE without TYPE_NAME.
PARENT is the parent node of T. */
static void static void
dump_ada_double_name (pretty_printer *buffer, tree t1, tree t2) dump_anonymous_type_name (pretty_printer *buffer, tree t, tree parent)
{ {
if (DECL_NAME (t1)) if (DECL_NAME (parent))
pp_ada_tree_identifier (buffer, DECL_NAME (t1), t1, false); pp_ada_tree_identifier (buffer, DECL_NAME (parent), parent, false);
else else
{ {
pp_string (buffer, "anon"); pp_string (buffer, "anon");
pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t1))); pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (parent)));
} }
pp_underscore (buffer); switch (TREE_CODE (t))
if (DECL_NAME (t2))
pp_ada_tree_identifier (buffer, DECL_NAME (t2), t2, false);
else
{
pp_string (buffer, "anon");
pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t2)));
}
switch (TREE_CODE (TREE_TYPE (t2)))
{ {
case ARRAY_TYPE: case ARRAY_TYPE:
pp_string (buffer, "_array"); pp_string (buffer, "_array");
...@@ -1516,6 +1508,8 @@ dump_ada_double_name (pretty_printer *buffer, tree t1, tree t2) ...@@ -1516,6 +1508,8 @@ dump_ada_double_name (pretty_printer *buffer, tree t1, tree t2)
pp_string (buffer, "_unknown"); pp_string (buffer, "_unknown");
break; break;
} }
pp_scalar (buffer, "%d", TYPE_UID (t));
} }
/* Dump in BUFFER aspect Import on a given node T. SPC is the current /* Dump in BUFFER aspect Import on a given node T. SPC is the current
...@@ -1816,10 +1810,9 @@ dump_ada_array_type (pretty_printer *buffer, tree node, tree type, int spc) ...@@ -1816,10 +1810,9 @@ dump_ada_array_type (pretty_printer *buffer, tree node, tree type, int spc)
/* Print the dimensions. */ /* Print the dimensions. */
dump_ada_array_domains (buffer, node, spc); dump_ada_array_domains (buffer, node, spc);
/* Print array's type. */ /* Print the component type. */
if (!char_array) if (!char_array)
{ {
/* Retrieve the element type. */
tree tmp = node; tree tmp = node;
while (TREE_CODE (tmp) == ARRAY_TYPE) while (TREE_CODE (tmp) == ARRAY_TYPE)
tmp = TREE_TYPE (tmp); tmp = TREE_TYPE (tmp);
...@@ -1829,10 +1822,12 @@ dump_ada_array_type (pretty_printer *buffer, tree node, tree type, int spc) ...@@ -1829,10 +1822,12 @@ dump_ada_array_type (pretty_printer *buffer, tree node, tree type, int spc)
if (TREE_CODE (tmp) != POINTER_TYPE) if (TREE_CODE (tmp) != POINTER_TYPE)
pp_string (buffer, "aliased "); pp_string (buffer, "aliased ");
if (TYPE_NAME (tmp) || !RECORD_OR_UNION_TYPE_P (tmp)) if (TYPE_NAME (tmp)
|| (!RECORD_OR_UNION_TYPE_P (tmp)
&& TREE_CODE (tmp) != ENUMERAL_TYPE))
dump_ada_node (buffer, tmp, node, spc, false, true); dump_ada_node (buffer, tmp, node, spc, false, true);
else else if (type)
dump_ada_double_name (buffer, type, get_underlying_decl (tmp)); dump_anonymous_type_name (buffer, tmp, type);
} }
} }
...@@ -2469,10 +2464,11 @@ dump_forward_type (pretty_printer *buffer, tree type, tree t, int spc) ...@@ -2469,10 +2464,11 @@ dump_forward_type (pretty_printer *buffer, tree type, tree t, int spc)
TREE_VISITED (decl) = 1; TREE_VISITED (decl) = 1;
} }
static void dump_nested_type (pretty_printer *, tree, tree, tree, int); static void dump_nested_type (pretty_printer *, tree, tree, tree, bitmap, int);
/* Dump in BUFFER anonymous types nested inside T's definition. /* Dump in BUFFER anonymous types nested inside T's definition. PARENT is the
PARENT is the parent node of T. SPC is the indentation level. parent node of T. DUMPED_TYPES is the bitmap of already dumped types. SPC
is the indentation level.
In C anonymous nested tagged types have no name whereas in C++ they have In C anonymous nested tagged types have no name whereas in C++ they have
one. In C their TYPE_DECL is at top level whereas in C++ it is nested. one. In C their TYPE_DECL is at top level whereas in C++ it is nested.
...@@ -2484,13 +2480,14 @@ static void dump_nested_type (pretty_printer *, tree, tree, tree, int); ...@@ -2484,13 +2480,14 @@ static void dump_nested_type (pretty_printer *, tree, tree, tree, int);
pass on the nested TYPE_DECLs and a second pass on the unnamed types. */ pass on the nested TYPE_DECLs and a second pass on the unnamed types. */
static void static void
dump_nested_types (pretty_printer *buffer, tree t, tree parent, int spc) dump_nested_types_1 (pretty_printer *buffer, tree t, tree parent,
bitmap dumped_types, int spc)
{ {
tree type, field; tree type, field;
/* Find possible anonymous pointers/arrays/structs/unions recursively. */ /* Find possible anonymous pointers/arrays/structs/unions recursively. */
type = TREE_TYPE (t); type = TREE_TYPE (t);
if (type == NULL_TREE) if (!type)
return; return;
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
...@@ -2498,19 +2495,31 @@ dump_nested_types (pretty_printer *buffer, tree t, tree parent, int spc) ...@@ -2498,19 +2495,31 @@ dump_nested_types (pretty_printer *buffer, tree t, tree parent, int spc)
&& DECL_NAME (field) != DECL_NAME (t) && DECL_NAME (field) != DECL_NAME (t)
&& !DECL_ORIGINAL_TYPE (field) && !DECL_ORIGINAL_TYPE (field)
&& TYPE_NAME (TREE_TYPE (field)) != TYPE_NAME (type)) && TYPE_NAME (TREE_TYPE (field)) != TYPE_NAME (type))
dump_nested_type (buffer, field, t, parent, spc); dump_nested_type (buffer, field, t, parent, dumped_types, spc);
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL && !TYPE_NAME (TREE_TYPE (field))) if (TREE_CODE (field) == FIELD_DECL && !TYPE_NAME (TREE_TYPE (field)))
dump_nested_type (buffer, field, t, parent, spc); dump_nested_type (buffer, field, t, parent, dumped_types, spc);
} }
/* Dump in BUFFER the anonymous type of FIELD inside T. /* Likewise, but to be invoked only at top level. We dump each anonymous type
PARENT is the parent node of T. SPC is the indentation level. */ nested inside T's definition exactly once, even if it is referenced several
times in it (typically an array type), with a name prefixed by that of T. */
static void
dump_nested_types (pretty_printer *buffer, tree t, int spc)
{
auto_bitmap dumped_types;
dump_nested_types_1 (buffer, t, t, dumped_types, spc);
}
/* Dump in BUFFER the anonymous type of FIELD inside T. PARENT is the parent
node of T. DUMPED_TYPES is the bitmap of already dumped types. SPC is the
indentation level. */
static void static void
dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent, dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent,
int spc) bitmap dumped_types, int spc)
{ {
tree field_type = TREE_TYPE (field); tree field_type = TREE_TYPE (field);
tree decl, tmp; tree decl, tmp;
...@@ -2523,6 +2532,11 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent, ...@@ -2523,6 +2532,11 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent,
break; break;
case ARRAY_TYPE: case ARRAY_TYPE:
/* Anonymous array types are shared. */
if (!bitmap_set_bit (dumped_types, TYPE_UID (field_type)))
return;
/* Recurse on the element type if need be. */
tmp = TREE_TYPE (field_type); tmp = TREE_TYPE (field_type);
while (TREE_CODE (tmp) == ARRAY_TYPE) while (TREE_CODE (tmp) == ARRAY_TYPE)
tmp = TREE_TYPE (tmp); tmp = TREE_TYPE (tmp);
...@@ -2533,7 +2547,7 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent, ...@@ -2533,7 +2547,7 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent,
&& !TREE_VISITED (decl)) && !TREE_VISITED (decl))
{ {
/* Generate full declaration. */ /* Generate full declaration. */
dump_nested_type (buffer, decl, t, parent, spc); dump_nested_type (buffer, decl, t, parent, dumped_types, spc);
TREE_VISITED (decl) = 1; TREE_VISITED (decl) = 1;
} }
else if (!decl && TREE_CODE (tmp) == POINTER_TYPE) else if (!decl && TREE_CODE (tmp) == POINTER_TYPE)
...@@ -2545,7 +2559,7 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent, ...@@ -2545,7 +2559,7 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent,
else else
pp_string (buffer, "type "); pp_string (buffer, "type ");
dump_ada_double_name (buffer, parent, field); dump_anonymous_type_name (buffer, field_type, parent);
pp_string (buffer, " is "); pp_string (buffer, " is ");
dump_ada_array_type (buffer, field_type, parent, spc); dump_ada_array_type (buffer, field_type, parent, spc);
pp_semicolon (buffer); pp_semicolon (buffer);
...@@ -2561,7 +2575,7 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent, ...@@ -2561,7 +2575,7 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent,
if (TYPE_NAME (field_type)) if (TYPE_NAME (field_type))
dump_ada_node (buffer, field_type, NULL_TREE, spc, false, true); dump_ada_node (buffer, field_type, NULL_TREE, spc, false, true);
else else
dump_ada_double_name (buffer, parent, field); dump_anonymous_type_name (buffer, field_type, parent);
pp_string (buffer, " is "); pp_string (buffer, " is ");
dump_ada_enum_type (buffer, field_type, spc); dump_ada_enum_type (buffer, field_type, spc);
pp_semicolon (buffer); pp_semicolon (buffer);
...@@ -2570,14 +2584,14 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent, ...@@ -2570,14 +2584,14 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent,
case RECORD_TYPE: case RECORD_TYPE:
case UNION_TYPE: case UNION_TYPE:
dump_nested_types (buffer, field, t, spc); dump_nested_types_1 (buffer, field, parent, dumped_types, spc);
pp_string (buffer, "type "); pp_string (buffer, "type ");
if (TYPE_NAME (field_type)) if (TYPE_NAME (field_type))
dump_ada_node (buffer, field_type, NULL_TREE, spc, false, true); dump_ada_node (buffer, field_type, NULL_TREE, spc, false, true);
else else
dump_ada_double_name (buffer, parent, field); dump_anonymous_type_name (buffer, field_type, parent);
if (TREE_CODE (field_type) == UNION_TYPE) if (TREE_CODE (field_type) == UNION_TYPE)
pp_string (buffer, " (discr : unsigned := 0)"); pp_string (buffer, " (discr : unsigned := 0)");
...@@ -2843,7 +2857,7 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) ...@@ -2843,7 +2857,7 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
pp_string (buffer, "subtype "); pp_string (buffer, "subtype ");
else else
{ {
dump_nested_types (buffer, t, t, spc); dump_nested_types (buffer, t, spc);
if (separate_class_package (t)) if (separate_class_package (t))
{ {
...@@ -2920,8 +2934,6 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) ...@@ -2920,8 +2934,6 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
} }
else else
{ {
tree tmp = TYPE_NAME (TREE_TYPE (t));
if (spc == INDENT_INCR || TREE_STATIC (t)) if (spc == INDENT_INCR || TREE_STATIC (t))
is_var = true; is_var = true;
...@@ -2930,10 +2942,10 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) ...@@ -2930,10 +2942,10 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
if (TREE_CODE (TREE_TYPE (TREE_TYPE (t))) != POINTER_TYPE) if (TREE_CODE (TREE_TYPE (TREE_TYPE (t))) != POINTER_TYPE)
pp_string (buffer, "aliased "); pp_string (buffer, "aliased ");
if (tmp) if (TYPE_NAME (TREE_TYPE (t)))
dump_ada_node (buffer, tmp, type, spc, false, true); dump_ada_node (buffer, TREE_TYPE (t), type, spc, false, true);
else if (type) else if (type)
dump_ada_double_name (buffer, type, t); dump_anonymous_type_name (buffer, TREE_TYPE (t), type);
else else
dump_ada_array_type (buffer, TREE_TYPE (t), type, spc); dump_ada_array_type (buffer, TREE_TYPE (t), type, spc);
} }
...@@ -3152,33 +3164,21 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) ...@@ -3152,33 +3164,21 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
pp_string (buffer, " : "); pp_string (buffer, " : ");
if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)) if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE
|| TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE) && (TYPE_NAME (TREE_TYPE (t))
{ || (TREE_CODE (TREE_TYPE (t)) != INTEGER_TYPE
if (TYPE_NAME (TREE_TYPE (t)) && TREE_CODE (TREE_TYPE (t)) != ENUMERAL_TYPE)))
|| TREE_CODE (TREE_TYPE (t)) != ENUMERAL_TYPE) pp_string (buffer, "aliased ");
pp_string (buffer, "aliased ");
if (TREE_READONLY (t) && TREE_CODE (t) != FIELD_DECL)
pp_string (buffer, "constant ");
if (TYPE_NAME (TREE_TYPE (t)))
dump_ada_node (buffer, TREE_TYPE (t), t, spc, false, true);
else if (type)
dump_ada_double_name (buffer, type, t);
}
else
{
if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE
&& (TYPE_NAME (TREE_TYPE (t))
|| TREE_CODE (TREE_TYPE (t)) != INTEGER_TYPE))
pp_string (buffer, "aliased ");
if (TREE_READONLY (t) && TREE_CODE (t) != FIELD_DECL) if (TREE_READONLY (t) && TREE_CODE (t) != FIELD_DECL)
pp_string (buffer, "constant "); pp_string (buffer, "constant ");
dump_ada_node (buffer, TREE_TYPE (t), t, spc, false, true); if (TYPE_NAME (TREE_TYPE (t))
} || (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (t))
&& TREE_CODE (TREE_TYPE (t)) != ENUMERAL_TYPE))
dump_ada_node (buffer, TREE_TYPE (t), t, spc, false, true);
else if (type)
dump_anonymous_type_name (buffer, TREE_TYPE (t), type);
} }
} }
...@@ -3474,6 +3474,8 @@ void ...@@ -3474,6 +3474,8 @@ void
dump_ada_specs (void (*collect_all_refs)(const char *), dump_ada_specs (void (*collect_all_refs)(const char *),
int (*check)(tree, cpp_operation)) int (*check)(tree, cpp_operation))
{ {
bitmap_obstack_initialize (NULL);
/* Iterate over the list of files to dump specs for. */ /* Iterate over the list of files to dump specs for. */
for (int i = 0; i < source_refs_used; i++) for (int i = 0; i < source_refs_used; i++)
dump_ads (source_refs[i], collect_all_refs, check); dump_ads (source_refs[i], collect_all_refs, check);
...@@ -3481,4 +3483,6 @@ dump_ada_specs (void (*collect_all_refs)(const char *), ...@@ -3481,4 +3483,6 @@ dump_ada_specs (void (*collect_all_refs)(const char *),
/* Free various tables. */ /* Free various tables. */
free (source_refs); free (source_refs);
delete overloaded_names; delete overloaded_names;
bitmap_obstack_release (NULL);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment