PR lto/89692
	* tree.c (fld_type_variant, fld_incomplete_type_of,
	fld_process_array_type): Call fld->pset.add and don't call
	add_tree_to_fld_list if it returns true.
	(free_lang_data_in_type): Similarly with self-recursive call.  Purge
	non-marked types from TYPE_NEXT_VARIANT list.
	(find_decls_types_r): Call fld_worklist_push for TYPE_CANONICAL (t).

	* g++.dg/other/pr89692.C: New test.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@269862 138bc75d-0d04-0410-961f-82ee72b054a4
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2f1bf46..2f0c540 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2019-03-21  Jan Hubicka  <hubicka@ucw.cz>
+	    Jakub Jelinek  <jakub@redhat.com>
+
+	PR lto/89692
+	* tree.c (fld_type_variant, fld_incomplete_type_of,
+	fld_process_array_type): Call fld->pset.add and don't call
+	add_tree_to_fld_list if it returns true.
+	(free_lang_data_in_type): Similarly with self-recursive call.  Purge
+	non-marked types from TYPE_NEXT_VARIANT list.
+	(find_decls_types_r): Call fld_worklist_push for TYPE_CANONICAL (t).
+
 2019-03-21  Jakub Jelinek  <jakub@redhat.com>
 
 	* hash-table.h (hash_table): Add Lazy template parameter defaulted
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2334e97..4edc0ef 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
 2019-03-21  Jakub Jelinek  <jakub@redhat.com>
 
+	PR lto/89692
+	* g++.dg/other/pr89692.C: New test.
+
 	PR c++/89767
 	* g++.dg/cpp1y/lambda-init18.C: New test.
 	* g++.dg/cpp1y/lambda-init19.C: New test.
diff --git a/gcc/testsuite/g++.dg/other/pr89692.C b/gcc/testsuite/g++.dg/other/pr89692.C
new file mode 100644
index 0000000..36adeb5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/pr89692.C
@@ -0,0 +1,20 @@
+// PR lto/89692
+// { dg-do compile }
+// { dg-require-effective-target lto }
+// { dg-options "-flto -O2" }
+
+struct S {
+  short int a, b;
+  unsigned char c : 1;
+};
+
+bool
+foo (void)
+{
+  unsigned char d[sizeof (S)] = { 0 };
+  S e;
+
+  __builtin_memcpy (&e, d, sizeof (d));
+
+  return e.c == d[0];
+}
diff --git a/gcc/tree.c b/gcc/tree.c
index ae8ff08..65f8cd3 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -5215,7 +5215,8 @@
   if (inner_type)
     TREE_TYPE (v) = inner_type;
   gcc_checking_assert (fld_type_variant_equal_p (t,v, inner_type));
-  add_tree_to_fld_list (v, fld);
+  if (!fld->pset.add (v))
+    add_tree_to_fld_list (v, fld);
   return v;
 }
 
@@ -5253,7 +5254,8 @@
       array = build_array_type_1 (t2, TYPE_DOMAIN (t),
 				  TYPE_TYPELESS_STORAGE (t), false);
       TYPE_CANONICAL (array) = TYPE_CANONICAL (t);
-      add_tree_to_fld_list (array, fld);
+      if (!fld->pset.add (array))
+	add_tree_to_fld_list (array, fld);
     }
   return array;
 }
@@ -5298,7 +5300,8 @@
 						TYPE_REF_CAN_ALIAS_ALL (t));
 	  gcc_assert (TYPE_CANONICAL (t2) != t2
 		      && TYPE_CANONICAL (t2) == TYPE_CANONICAL (TREE_TYPE (t)));
-	  add_tree_to_fld_list (first, fld);
+	  if (!fld->pset.add (first))
+	    add_tree_to_fld_list (first, fld);
 	  return fld_type_variant (first, t, fld);
 	}
       return t;
@@ -5321,7 +5324,8 @@
 	  copy = build_distinct_type_copy (t);
 
 	  /* It is possible that type was not seen by free_lang_data yet.  */
-	  add_tree_to_fld_list (copy, fld);
+	  if (!fld->pset.add (copy))
+	    add_tree_to_fld_list (copy, fld);
 	  TYPE_SIZE (copy) = NULL;
 	  TYPE_USER_ALIGN (copy) = 0;
 	  TYPE_SIZE_UNIT (copy) = NULL;
@@ -5445,6 +5449,18 @@
 
   TYPE_NEEDS_CONSTRUCTING (type) = 0;
 
+  /* Purge non-marked variants from the variants chain, so that they
+     don't reappear in the IL after free_lang_data.  */
+  while (TYPE_NEXT_VARIANT (type)
+	 && !fld->pset.contains (TYPE_NEXT_VARIANT (type)))
+    {
+      tree t = TYPE_NEXT_VARIANT (type);
+      TYPE_NEXT_VARIANT (type) = TYPE_NEXT_VARIANT (t);
+      /* Turn the removed types into distinct types.  */
+      TYPE_MAIN_VARIANT (t) = t;
+      TYPE_NEXT_VARIANT (t) = NULL_TREE;
+    }
+
   if (TREE_CODE (type) == FUNCTION_TYPE)
     {
       TREE_TYPE (type) = fld_simplified_type (TREE_TYPE (type), fld);
@@ -5464,7 +5480,8 @@
 			  & ~TYPE_QUAL_CONST
 			  & ~TYPE_QUAL_VOLATILE;
 	      TREE_VALUE (p) = build_qualified_type (arg_type, quals);
-	      free_lang_data_in_type (TREE_VALUE (p), fld);
+	      if (!fld->pset.add (TREE_VALUE (p)))
+		free_lang_data_in_type (TREE_VALUE (p), fld);
 	    }
 	  /* C++ FE uses TREE_PURPOSE to store initial values.  */
 	  TREE_PURPOSE (p) = NULL;
@@ -5886,8 +5903,7 @@
 	    ctx = BLOCK_SUPERCONTEXT (ctx);
 	  fld_worklist_push (ctx, fld);
 	}
-      /* Do not walk TYPE_CANONICAL.  We do not stream it and thus do not
-	 and want not to reach unused types this way.  */
+      fld_worklist_push (TYPE_CANONICAL (t), fld);
 
       if (RECORD_OR_UNION_TYPE_P (t) && TYPE_BINFO (t))
 	{