diff mbox series

Improve ODR warnings

Message ID 20181120155716.ytmn243wiwl4vemb@kam.mff.cuni.cz
State New
Headers show
Series Improve ODR warnings | expand

Commit Message

Jan Hubicka Nov. 20, 2018, 3:57 p.m. UTC
Hi,
this patch fixes another problem with ODR warnings (and I hope I am one patch
away from closing that PR).

As shown in the first testcase Martin attached, we output very confusing
warning about wrong alignment of subtype instead of noticing that type
contains field of type that already violates ODR.  This used to (mostly)
work by accient since types was registered in streaming order that goes
by SCCs. Since Maritn sabilized the order to follow locations this is no
longer true. It was not robust anyway since two types may share SCC
(they ought not anymore but still it is better to not have correctness
of warnings dependent on details on the streaming).

This patch fixes it by simply making register_odr_type to first recurse to
subtypes to be sure that everything is registered in right order.

Testcases are still missing - there is location being output wrong which I
will work next.

lto-bootstrapped/regtested x86_64-linux, will commit it shortly.

Honza

	PR lto/87957
	* ipa-devirt.c (odr_subtypes_equivalent_p): Report ODR violation
	when sybtype already violates ODR.
	(get_odr_type): Do not ICE when insert is false and type duplicate
	is not registered yet.
	(register_odr_type): Be sure to register subtypes first.
diff mbox series

Patch

Index: ipa-devirt.c
===================================================================
--- ipa-devirt.c	(revision 266314)
+++ ipa-devirt.c	(working copy)
@@ -692,14 +692,17 @@  odr_subtypes_equivalent_p (tree t1, tree
      and other ODR even though it is a violation.  */
   if (types_odr_comparable (t1, t2))
     {
+      if (t1 != t2
+	  && odr_type_p (TYPE_MAIN_VARIANT (t1))
+	  && get_odr_type (TYPE_MAIN_VARIANT (t1), true)->odr_violated)
+	return false;
       if (!types_same_for_odr (t1, t2))
         return false;
       if (!type_variants_equivalent_p (t1, t2, warn, warned))
 	return false;
       /* Limit recursion: If subtypes are ODR types and we know
 	 that they are same, be happy.  */
-      if (!odr_type_p (TYPE_MAIN_VARIANT (t1))
-	  || !get_odr_type (TYPE_MAIN_VARIANT (t1), true)->odr_violated)
+      if (odr_type_p (TYPE_MAIN_VARIANT (t1)))
         return true;
     }
 
@@ -2047,10 +2050,9 @@  get_odr_type (tree type, bool insert)
       else if (*vtable_slot)
 	val = *vtable_slot;
 
-      if (val->type != type
+      if (val->type != type && insert
 	  && (!val->types_set || !val->types_set->add (type)))
 	{
-	  gcc_assert (insert);
 	  /* We have type duplicate, but it may introduce vtable name or
  	     mangled name; be sure to keep hashes in sync.  */
 	  if (in_lto_p && can_be_vtable_hashed_p (type)
@@ -2144,7 +2146,36 @@  register_odr_type (tree type)
         odr_vtable_hash = new odr_vtable_hash_type (23);
     }
   if (type == TYPE_MAIN_VARIANT (type))
-    get_odr_type (type, true);
+    {
+      /* To get ODR warings right, first register all sub-types.  */
+      if (RECORD_OR_UNION_TYPE_P (type)
+	  && COMPLETE_TYPE_P (type))
+	{
+	  /* Limit recursion on types which are already registered.  */
+	  odr_type ot = get_odr_type (type, false);
+	  if (ot
+	      && (ot->type == type
+		  || (ot->types_set
+		      && ot->types_set->contains (type))))
+	    return;
+	  for (tree f = TYPE_FIELDS (type); f; f = TREE_CHAIN (f))
+	    if (TREE_CODE (f) == FIELD_DECL)
+	      {
+		tree subtype = TREE_TYPE (f);
+
+		while (TREE_CODE (subtype) == ARRAY_TYPE)
+		  subtype = TREE_TYPE (subtype);
+		if (type_with_linkage_p (TYPE_MAIN_VARIANT (subtype)))
+		  register_odr_type (TYPE_MAIN_VARIANT (subtype));
+	      }
+	   if (TYPE_BINFO (type))
+	     for (unsigned int i = 0;
+	          i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type)); i++)
+	       register_odr_type (BINFO_TYPE (BINFO_BASE_BINFO
+						 (TYPE_BINFO (type), i)));
+	}
+      get_odr_type (type, true);
+    }
 }
 
 /* Return true if type is known to have no derivations.  */