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>
PR c/93640
......
......@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic.h"
#include "stringpool.h"
#include "attribs.h"
#include "bitmap.h"
/* Local functions, macros and variables. */
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)
}
}
/* 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
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))
pp_ada_tree_identifier (buffer, DECL_NAME (t1), t1, false);
if (DECL_NAME (parent))
pp_ada_tree_identifier (buffer, DECL_NAME (parent), parent, false);
else
{
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);
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)))
switch (TREE_CODE (t))
{
case ARRAY_TYPE:
pp_string (buffer, "_array");
......@@ -1516,6 +1508,8 @@ dump_ada_double_name (pretty_printer *buffer, tree t1, tree t2)
pp_string (buffer, "_unknown");
break;
}
pp_scalar (buffer, "%d", TYPE_UID (t));
}
/* 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)
/* Print the dimensions. */
dump_ada_array_domains (buffer, node, spc);
/* Print array's type. */
/* Print the component type. */
if (!char_array)
{
/* Retrieve the element type. */
tree tmp = node;
while (TREE_CODE (tmp) == ARRAY_TYPE)
tmp = TREE_TYPE (tmp);
......@@ -1829,10 +1822,12 @@ dump_ada_array_type (pretty_printer *buffer, tree node, tree type, int spc)
if (TREE_CODE (tmp) != POINTER_TYPE)
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);
else
dump_ada_double_name (buffer, type, get_underlying_decl (tmp));
else if (type)
dump_anonymous_type_name (buffer, tmp, type);
}
}
......@@ -2469,10 +2464,11 @@ dump_forward_type (pretty_printer *buffer, tree type, tree t, int spc)
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.
PARENT is the parent node of T. SPC is the indentation level.
/* Dump in BUFFER anonymous types nested inside T's definition. PARENT is the
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
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);
pass on the nested TYPE_DECLs and a second pass on the unnamed types. */
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;
/* Find possible anonymous pointers/arrays/structs/unions recursively. */
type = TREE_TYPE (t);
if (type == NULL_TREE)
if (!type)
return;
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)
&& DECL_NAME (field) != DECL_NAME (t)
&& !DECL_ORIGINAL_TYPE (field)
&& 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))
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.
PARENT is the parent node of T. SPC is the indentation level. */
/* Likewise, but to be invoked only at top level. We dump each anonymous type
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
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 decl, tmp;
......@@ -2523,6 +2532,11 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent,
break;
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);
while (TREE_CODE (tmp) == ARRAY_TYPE)
tmp = TREE_TYPE (tmp);
......@@ -2533,7 +2547,7 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent,
&& !TREE_VISITED (decl))
{
/* 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;
}
else if (!decl && TREE_CODE (tmp) == POINTER_TYPE)
......@@ -2545,7 +2559,7 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent,
else
pp_string (buffer, "type ");
dump_ada_double_name (buffer, parent, field);
dump_anonymous_type_name (buffer, field_type, parent);
pp_string (buffer, " is ");
dump_ada_array_type (buffer, field_type, parent, spc);
pp_semicolon (buffer);
......@@ -2561,7 +2575,7 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent,
if (TYPE_NAME (field_type))
dump_ada_node (buffer, field_type, NULL_TREE, spc, false, true);
else
dump_ada_double_name (buffer, parent, field);
dump_anonymous_type_name (buffer, field_type, parent);
pp_string (buffer, " is ");
dump_ada_enum_type (buffer, field_type, spc);
pp_semicolon (buffer);
......@@ -2570,14 +2584,14 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent,
case RECORD_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 ");
if (TYPE_NAME (field_type))
dump_ada_node (buffer, field_type, NULL_TREE, spc, false, true);
else
dump_ada_double_name (buffer, parent, field);
dump_anonymous_type_name (buffer, field_type, parent);
if (TREE_CODE (field_type) == UNION_TYPE)
pp_string (buffer, " (discr : unsigned := 0)");
......@@ -2843,7 +2857,7 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
pp_string (buffer, "subtype ");
else
{
dump_nested_types (buffer, t, t, spc);
dump_nested_types (buffer, t, spc);
if (separate_class_package (t))
{
......@@ -2920,8 +2934,6 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
}
else
{
tree tmp = TYPE_NAME (TREE_TYPE (t));
if (spc == INDENT_INCR || TREE_STATIC (t))
is_var = true;
......@@ -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)
pp_string (buffer, "aliased ");
if (tmp)
dump_ada_node (buffer, tmp, type, spc, false, true);
if (TYPE_NAME (TREE_TYPE (t)))
dump_ada_node (buffer, TREE_TYPE (t), type, spc, false, true);
else if (type)
dump_ada_double_name (buffer, type, t);
dump_anonymous_type_name (buffer, TREE_TYPE (t), type);
else
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)
pp_string (buffer, " : ");
if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t))
|| TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
{
if (TYPE_NAME (TREE_TYPE (t))
|| TREE_CODE (TREE_TYPE (t)) != ENUMERAL_TYPE)
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_CODE (TREE_TYPE (t)) != POINTER_TYPE
&& (TYPE_NAME (TREE_TYPE (t))
|| (TREE_CODE (TREE_TYPE (t)) != INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (t)) != ENUMERAL_TYPE)))
pp_string (buffer, "aliased ");
if (TREE_READONLY (t) && TREE_CODE (t) != FIELD_DECL)
pp_string (buffer, "constant ");
if (TREE_READONLY (t) && TREE_CODE (t) != FIELD_DECL)
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
dump_ada_specs (void (*collect_all_refs)(const char *),
int (*check)(tree, cpp_operation))
{
bitmap_obstack_initialize (NULL);
/* Iterate over the list of files to dump specs for. */
for (int i = 0; i < source_refs_used; i++)
dump_ads (source_refs[i], collect_all_refs, check);
......@@ -3481,4 +3483,6 @@ dump_ada_specs (void (*collect_all_refs)(const char *),
/* Free various tables. */
free (source_refs);
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