Fix duplicates for anonymous structures with -fdump-ada-spec
authorEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 14 Feb 2020 23:11:04 +0000 (00:11 +0100)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 14 Feb 2020 23:13:18 +0000 (00:13 +0100)
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.

gcc/c-family/ChangeLog
gcc/c-family/c-ada-spec.c

index cabf850a9213d9288ee468dcf517c799fcd254b9..e4250724e84f315de6fdccc97ff7b55fdc699f37 100644 (file)
@@ -1,3 +1,20 @@
+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
index e0c18c883da25e38343e700ddbb07620d62ec3d9..6d9192f2a266bde53d0238259f0db52273a3b4d0 100644 (file)
@@ -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);
 }