re PR ipa/87957 (ICE tree check: expected tree that contains ‘decl minimal’ structure...
authorJan Hubicka <jh@suse.cz>
Wed, 21 Nov 2018 17:31:19 +0000 (18:31 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Wed, 21 Nov 2018 17:31:19 +0000 (17:31 +0000)
PR lto/87957
* tree.c (fld_decl_context): Break out from ...
(free_lang_data_in_decl): ... here; free TREE_PUBLIC, TREE_PRIVATE
DECL_ARTIFICIAL of TYPE_DECL; do not free TREE_TYPE of TYPE_DECL.
(fld_incomplete_type_of): Build copy of TYP_DECL.
* ipa-devirt.c (free_enum_values): Rename to ...
(free_odr_warning_data): ... this one; free also duplicated TYPE_DECLs
and TREE_TYPEs of TYPE_DECLs.
(get_odr_type): Initialize odr_vtable_hash if needed.

From-SVN: r266350

gcc/ChangeLog
gcc/ipa-devirt.c
gcc/tree.c

index 88db1c1e15d6b99fd8f268565aa4b97eeeccad15..82a1710e4e467cf6bd4facf9801318bd7d591d70 100644 (file)
@@ -1,3 +1,15 @@
+2018-11-21  Jan Hubicka  <jh@suse.cz>
+
+       PR lto/87957
+       * tree.c (fld_decl_context): Break out from ...
+       (free_lang_data_in_decl): ... here; free TREE_PUBLIC, TREE_PRIVATE
+       DECL_ARTIFICIAL of TYPE_DECL; do not free TREE_TYPE of TYPE_DECL.
+       (fld_incomplete_type_of): Build copy of TYP_DECL.
+       * ipa-devirt.c (free_enum_values): Rename to ...
+       (free_odr_warning_data): ... this one; free also duplicated TYPE_DECLs
+       and TREE_TYPEs of TYPE_DECLs.
+       (get_odr_type): Initialize odr_vtable_hash if needed.
+
 2018-11-21  Alexandre Oliva <oliva@adacore.com>
 
        * final.c (compute_discriminator): Declare.  Renamed from...
index b72789c72bb6a210e7ce53c4ec35f358ed59e9ea..8c375ff07bd5cd4275239ec2d818828260cb61d1 100644 (file)
@@ -2025,6 +2025,8 @@ get_odr_type (tree type, bool insert)
   if ((!slot || !*slot) && in_lto_p && can_be_vtable_hashed_p (type))
     {
       hash = hash_odr_vtable (type);
+      if (!odr_vtable_hash)
+        odr_vtable_hash = new odr_vtable_hash_type (23);
       vtable_slot = odr_vtable_hash->find_slot_with_hash (type, hash,
                                                   insert ? INSERT : NO_INSERT);
     }
@@ -2289,27 +2291,43 @@ dump_type_inheritance_graph (FILE *f)
           "%i duplicates overall\n", num_all_types, num_types, num_duplicates);
 }
 
-/* Save some WPA->ltrans streaming by freeing enum values.  */
+/* Save some WPA->ltrans streaming by freeing stuff needed only for good
+   ODR warnings.
+   We free TYPE_VALUES of enums and also make TYPE_DECLs to not point back
+   to the type (which is needed to keep them in the same SCC and preserve
+   location information to output warnings) and subsequently we make all
+   TYPE_DECLS of same assembler name equivalent.  */
 
 static void
-free_enum_values ()
+free_odr_warning_data ()
 {
-  static bool enum_values_freed = false;
-  if (enum_values_freed || !flag_wpa || !odr_types_ptr)
+  static bool odr_data_freed = false;
+
+  if (odr_data_freed || !flag_wpa || !odr_types_ptr)
     return;
-  enum_values_freed = true;
-  unsigned int i;
-  for (i = 0; i < odr_types.length (); i++)
+
+  odr_data_freed = true;
+
+  for (unsigned int i = 0; i < odr_types.length (); i++)
     if (odr_types[i])
       {
-       if (TREE_CODE (odr_types[i]->type) == ENUMERAL_TYPE)
-         TYPE_VALUES (odr_types[i]->type) = NULL;
+       tree t = odr_types[i]->type;
+
+       if (TREE_CODE (t) == ENUMERAL_TYPE)
+         TYPE_VALUES (t) = NULL;
+       TREE_TYPE (TYPE_NAME (t)) = void_type_node;
+
        if (odr_types[i]->types)
           for (unsigned int j = 0; j < odr_types[i]->types->length (); j++)
-           if (TREE_CODE ((*odr_types[i]->types)[j]) == ENUMERAL_TYPE)
-             TYPE_VALUES ((*odr_types[i]->types)[j]) = NULL;
+           {
+             tree td = (*odr_types[i]->types)[j];
+
+             if (TREE_CODE (td) == ENUMERAL_TYPE)
+               TYPE_VALUES (td) = NULL;
+             TYPE_NAME (td) = TYPE_NAME (t);
+           }
       }
-  enum_values_freed = true;
+  odr_data_freed = true;
 }
 
 /* Initialize IPA devirt and build inheritance tree graph.  */
@@ -2323,7 +2341,7 @@ build_type_inheritance_graph (void)
 
   if (odr_hash)
     {
-      free_enum_values ();
+      free_odr_warning_data ();
       return;
     }
   timevar_push (TV_IPA_INHERITANCE);
@@ -2370,7 +2388,7 @@ build_type_inheritance_graph (void)
       dump_type_inheritance_graph (inheritance_dump_file);
       dump_end (TDI_inheritance, inheritance_dump_file);
     }
-  free_enum_values ();
+  free_odr_warning_data ();
   timevar_pop (TV_IPA_INHERITANCE);
 }
 
index 50c4cd0e4a16d40460ea9c6067747b0196996ce2..8264e9c7f141f1ab9149196de2a34b7822d80e70 100644 (file)
@@ -5206,6 +5206,24 @@ fld_process_array_type (tree t, tree t2, hash_map<tree, tree> *map,
   return array;
 }
 
+/* Return CTX after removal of contexts that are not relevant  */
+
+static tree
+fld_decl_context (tree ctx)
+{
+  /* Variably modified types are needed for tree_is_indexable to decide
+     whether the type needs to go to local or global section.
+     This code is semi-broken but for now it is easiest to keep contexts
+     as expected.  */
+  if (ctx && TYPE_P (ctx)
+      && !variably_modified_type_p (ctx, NULL_TREE))
+     {
+       while (ctx && TYPE_P (ctx))
+        ctx = TYPE_CONTEXT (ctx);
+     }
+  return ctx;
+}
+
 /* For T being aggregate type try to turn it into a incomplete variant.
    Return T if no simplification is possible.  */
 
@@ -5267,6 +5285,28 @@ fld_incomplete_type_of (tree t, struct free_lang_data_d *fld)
            }
          else
            TYPE_VALUES (copy) = NULL;
+
+         /* Build copy of TYPE_DECL in TYPE_NAME if necessary.
+            This is needed for ODR violation warnings to come out right (we
+            want duplicate TYPE_DECLs whenever the type is duplicated because
+            of ODR violation.  Because lang data in the TYPE_DECL may not
+            have been freed yet, rebuild it from scratch and copy relevant
+            fields.  */
+         TYPE_NAME (copy) = fld_simplified_type_name (copy);
+         tree name = TYPE_NAME (copy);
+
+         if (name && TREE_CODE (name) == TYPE_DECL)
+           {
+             gcc_checking_assert (TREE_TYPE (name) == t);
+             tree name2 = build_decl (DECL_SOURCE_LOCATION (name), TYPE_DECL,
+                                      DECL_NAME (name), copy);
+             if (DECL_ASSEMBLER_NAME_SET_P (name))
+               SET_DECL_ASSEMBLER_NAME (name2, DECL_ASSEMBLER_NAME (name));
+             SET_DECL_ALIGN (name2, 0);
+             DECL_CONTEXT (name2) = fld_decl_context
+                                        (DECL_CONTEXT (name));
+             TYPE_NAME (copy) = name2;
+           }
        }
       return copy;
    }
@@ -5423,7 +5463,8 @@ free_lang_data_in_type (tree type, struct free_lang_data_d *fld)
       if (TREE_CODE (type) == ENUMERAL_TYPE)
        {
          /* Type values are used only for C++ ODR checking.  Drop them
-            for all type variants and non-ODR types.  */
+            for all type variants and non-ODR types.
+            For ODR types the data is freed in free_odr_warning_data.  */
          if (TYPE_MAIN_VARIANT (type) != type
              || !type_with_linkage_p (type))
            TYPE_VALUES (type) = NULL;
@@ -5455,11 +5496,7 @@ free_lang_data_in_type (tree type, struct free_lang_data_d *fld)
       TYPE_CONTEXT (type) = ctx;
     }
 
-  /* Drop TYPE_DECLs in TYPE_NAME in favor of the identifier in the
-     TYPE_DECL if the type doesn't have linkage.
-     this must match fld_  */
-  if (type != TYPE_MAIN_VARIANT (type) || ! type_with_linkage_p (type))
-    TYPE_STUB_DECL (type) = NULL;
+  TYPE_STUB_DECL (type) = NULL;
   TYPE_NAME (type) = fld_simplified_type_name (type);
 }
 
@@ -5486,16 +5523,19 @@ need_assembler_name_p (tree decl)
      e.g.  -fno-signed-char/-fsigned-char mismatches to be handled well.
      See cp/mangle.c:write_builtin_type for details.  */
 
-  if (flag_lto_odr_type_mering
-      && TREE_CODE (decl) == TYPE_DECL
-      && DECL_NAME (decl)
-      && decl == TYPE_NAME (TREE_TYPE (decl))
-      && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TREE_TYPE (decl)
-      && !TYPE_ARTIFICIAL (TREE_TYPE (decl))
-      && (type_with_linkage_p (TREE_TYPE (decl))
-         || TREE_CODE (TREE_TYPE (decl)) == INTEGER_TYPE)
-      && !variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
-    return !DECL_ASSEMBLER_NAME_SET_P (decl);
+  if (TREE_CODE (decl) == TYPE_DECL)
+    {
+      if (flag_lto_odr_type_mering
+         && DECL_NAME (decl)
+         && decl == TYPE_NAME (TREE_TYPE (decl))
+         && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TREE_TYPE (decl)
+         && !TYPE_ARTIFICIAL (TREE_TYPE (decl))
+         && (type_with_linkage_p (TREE_TYPE (decl))
+             || TREE_CODE (TREE_TYPE (decl)) == INTEGER_TYPE)
+         && !variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
+       return !DECL_ASSEMBLER_NAME_SET_P (decl);
+      return false;
+    }
   /* Only FUNCTION_DECLs and VAR_DECLs are considered.  */
   if (!VAR_OR_FUNCTION_DECL_P (decl))
     return false;
@@ -5649,13 +5689,15 @@ free_lang_data_in_decl (tree decl, struct free_lang_data_d *fld)
     {
       DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
       DECL_VISIBILITY_SPECIFIED (decl) = 0;
-      /* TREE_PUBLIC is used to tell if type is anonymous.  */
+      TREE_PUBLIC (decl) = 0;
+      TREE_PRIVATE (decl) = 0;
+      DECL_ARTIFICIAL (decl) = 0;
       TYPE_DECL_SUPPRESS_DEBUG (decl) = 0;
       DECL_INITIAL (decl) = NULL_TREE;
       DECL_ORIGINAL_TYPE (decl) = NULL_TREE;
       DECL_MODE (decl) = VOIDmode;
-      TREE_TYPE (decl) = void_type_node;
       SET_DECL_ALIGN (decl, 0);
+      /* TREE_TYPE is cleared at WPA time in free_odr_warning_data.  */
     }
   else if (TREE_CODE (decl) == FIELD_DECL)
     {
@@ -5688,20 +5730,7 @@ free_lang_data_in_decl (tree decl, struct free_lang_data_d *fld)
   if (TREE_CODE (decl) != FIELD_DECL
       && ((TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
           || !DECL_VIRTUAL_P (decl)))
-    {
-      tree ctx = DECL_CONTEXT (decl);
-      /* Variably modified types are needed for tree_is_indexable to decide
-        whether the type needs to go to local or global section.
-        This code is semi-broken but for now it is easiest to keep contexts
-        as expected.  */
-      if (ctx && TYPE_P (ctx)
-         && !variably_modified_type_p (ctx, NULL_TREE))
-        {
-          while (ctx && TYPE_P (ctx))
-            ctx = TYPE_CONTEXT (ctx);
-          DECL_CONTEXT (decl) = ctx;
-        }
-    }
+    DECL_CONTEXT (decl) = fld_decl_context (DECL_CONTEXT (decl));
 }