]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gimple-fold.c (gimple_extract_devirt_binfo_from_cst): Use types_same_for_odr.
authorJan Hubicka <jh@suse.cz>
Fri, 21 Jun 2013 06:43:39 +0000 (08:43 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Fri, 21 Jun 2013 06:43:39 +0000 (06:43 +0000)
* gimple-fold.c (gimple_extract_devirt_binfo_from_cst): Use
types_same_for_odr.
* tree.c (decls_same_for_odr): New function.
(same_for_edr): New function.
(types_same_for_odr): New function.
(get_binfo_at_offset): Use it.
* tree.h (types_same_for_odr): Declare.

From-SVN: r200288

gcc/ChangeLog
gcc/gimple-fold.c
gcc/tree.c
gcc/tree.h

index e3484bd5a4ee2585e5af64029c3c6a0bd7de08fd..c18f056d06e2e6675c3877dcf42723454d3feb6c 100644 (file)
@@ -1,3 +1,13 @@
+2013-06-20  Jan Hubicka  <jh@suse.cz>
+
+       * gimple-fold.c (gimple_extract_devirt_binfo_from_cst): Use
+       types_same_for_odr.
+       * tree.c (decls_same_for_odr): New function.
+       (same_for_edr): New function.
+       (types_same_for_odr): New function.
+       (get_binfo_at_offset): Use it.
+       * tree.h (types_same_for_odr): Declare.
+
 2013-06-20  Oleg Endo <oleg.endo@t-online.de>
            Jason Merrill  <jason@redhat.com>
 
index b6d22b3a7c835012edcbf84af4554863525efbaa..728d3610f11cdd57b6a02a2cb77192e7899c0a2e 100644 (file)
@@ -1038,7 +1038,7 @@ gimple_extract_devirt_binfo_from_cst (tree cst)
       HOST_WIDE_INT pos, size;
       tree fld;
 
-      if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (expected_type))
+      if (types_same_for_odr (type, expected_type))
        break;
       if (offset < 0)
        return NULL_TREE;
index 67553b89294d5d2d984f46b76a52e8d89a3a65ad..ab1173525c71396621f4888cf3a434d61660e62a 100644 (file)
@@ -218,6 +218,7 @@ static void print_value_expr_statistics (void);
 static int type_hash_marked_p (const void *);
 static unsigned int type_hash_list (const_tree, hashval_t);
 static unsigned int attribute_hash_list (const_tree, hashval_t);
+static bool decls_same_for_odr (tree decl1, tree decl2);
 
 tree global_trees[TI_MAX];
 tree integer_types[itk_none];
@@ -11711,6 +11712,127 @@ lhd_gcc_personality (void)
   return gcc_eh_personality_decl;
 }
 
+/* For languages with One Definition Rule, work out if
+   trees are actually the same even if the tree representation
+   differs.  This handles only decls appearing in TYPE_NAME
+   and TYPE_CONTEXT.  That is NAMESPACE_DECL, TYPE_DECL,
+   RECORD_TYPE and IDENTIFIER_NODE.  */
+
+static bool
+same_for_odr (tree t1, tree t2)
+{
+  if (t1 == t2)
+    return true;
+  if (!t1 || !t2)
+    return false;
+  /* C and C++ FEs differ by using IDENTIFIER_NODE and TYPE_DECL.  */
+  if (TREE_CODE (t1) == IDENTIFIER_NODE
+      && TREE_CODE (t2) == TYPE_DECL
+      && DECL_FILE_SCOPE_P (t1))
+    {
+      t2 = DECL_NAME (t2);
+      gcc_assert (TREE_CODE (t2) == IDENTIFIER_NODE);
+    }
+  if (TREE_CODE (t2) == IDENTIFIER_NODE
+      && TREE_CODE (t1) == TYPE_DECL
+      && DECL_FILE_SCOPE_P (t2))
+    {
+      t1 = DECL_NAME (t1);
+      gcc_assert (TREE_CODE (t1) == IDENTIFIER_NODE);
+    }
+  if (TREE_CODE (t1) != TREE_CODE (t2))
+    return false;
+  if (TYPE_P (t1))
+    return types_same_for_odr (t1, t2);
+  if (DECL_P (t1))
+    return decls_same_for_odr (t1, t2);
+  return false;
+}
+
+/* For languages with One Definition Rule, work out if
+   decls are actually the same even if the tree representation
+   differs.  This handles only decls appearing in TYPE_NAME
+   and TYPE_CONTEXT.  That is NAMESPACE_DECL, TYPE_DECL,
+   RECORD_TYPE and IDENTIFIER_NODE.  */
+
+static bool
+decls_same_for_odr (tree decl1, tree decl2)
+{
+  if (decl1 && TREE_CODE (decl1) == TYPE_DECL
+      && DECL_ORIGINAL_TYPE (decl1))
+    decl1 = DECL_ORIGINAL_TYPE (decl1);
+  if (decl2 && TREE_CODE (decl2) == TYPE_DECL
+      && DECL_ORIGINAL_TYPE (decl2))
+    decl2 = DECL_ORIGINAL_TYPE (decl2);
+  if (decl1 == decl2)
+    return true;
+  if (!decl1 || !decl2)
+    return false;
+  gcc_checking_assert (DECL_P (decl1) && DECL_P (decl2));
+  if (TREE_CODE (decl1) != TREE_CODE (decl2))
+    return false;
+  if (TREE_CODE (decl1) == TRANSLATION_UNIT_DECL)
+    return true;
+  if (TREE_CODE (decl1) != NAMESPACE_DECL
+      && TREE_CODE (decl1) != TYPE_DECL)
+    return false;
+  if (!DECL_NAME (decl1))
+    return false;
+  gcc_checking_assert (TREE_CODE (DECL_NAME (decl1)) == IDENTIFIER_NODE);
+  gcc_checking_assert (!DECL_NAME (decl2)
+                      ||  TREE_CODE (DECL_NAME (decl2)) == IDENTIFIER_NODE);
+  if (DECL_NAME (decl1) != DECL_NAME (decl2))
+    return false;
+  return same_for_odr (DECL_CONTEXT (decl1),
+                      DECL_CONTEXT (decl2));
+}
+
+/* For languages with One Definition Rule, work out if
+   types are same even if the tree representation differs. 
+   This is non-trivial for LTO where minnor differences in
+   the type representation may have prevented type merging
+   to merge two copies of otherwise equivalent type.  */
+
+bool
+types_same_for_odr (tree type1, tree type2)
+{
+  gcc_checking_assert (TYPE_P (type1) && TYPE_P (type2));
+  type1 = TYPE_MAIN_VARIANT (type1);
+  type2 = TYPE_MAIN_VARIANT (type2);
+  if (type1 == type2)
+    return true;
+
+  /* If types are not structuraly same, do not bother to contnue.
+     Match in the remainder of code would mean ODR violation.  */
+  if (!types_compatible_p (type1, type2))
+    return false;
+
+#ifndef ENABLE_CHECKING
+  if (!in_lto_p)
+    return false;
+#endif
+
+  /* Check for anonymous namespaces. Those have !TREE_PUBLIC
+     on the corresponding TYPE_STUB_DECL.  */
+  if (TYPE_STUB_DECL (type1) != TYPE_STUB_DECL (type2)
+      && (!TYPE_STUB_DECL (type1)
+         || !TYPE_STUB_DECL (type2)
+         || !TREE_PUBLIC (TYPE_STUB_DECL (type1))
+         || !TREE_PUBLIC (TYPE_STUB_DECL (type2))))
+    return false;
+
+  if (!TYPE_NAME (type1))
+    return false;
+  if (!decls_same_for_odr (TYPE_NAME (type1), TYPE_NAME (type2)))
+    return false;
+  if (!same_for_odr (TYPE_CONTEXT (type1), TYPE_CONTEXT (type2)))
+    return false;
+  /* When not in LTO the MAIN_VARIANT check should be the same.  */
+  gcc_assert (in_lto_p);
+    
+  return true;
+}
+
 /* Try to find a base info of BINFO that would have its field decl at offset
    OFFSET within the BINFO type and which is of EXPECTED_TYPE.  If it can be
    found, return, otherwise return NULL_TREE.  */
@@ -11726,7 +11848,7 @@ get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type)
       tree fld;
       int i;
 
-      if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (expected_type))
+      if (types_same_for_odr (type, expected_type))
          return binfo;
       if (offset < 0)
        return NULL_TREE;
@@ -11756,7 +11878,7 @@ get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type)
        {
          tree base_binfo, found_binfo = NULL_TREE;
          for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
-           if (TREE_TYPE (base_binfo) == TREE_TYPE (fld))
+           if (types_same_for_odr (TREE_TYPE (base_binfo), TREE_TYPE (fld)))
              {
                found_binfo = base_binfo;
                break;
index cbbdd0bbc0839d58eb2ffb1770508f8a36442db2..b4445170088e5398604af105b5491b9f6ae9d4bb 100644 (file)
@@ -5974,6 +5974,7 @@ extern location_t tree_nonartificial_location (tree);
 extern tree block_ultimate_origin (const_tree);
 
 extern tree get_binfo_at_offset (tree, HOST_WIDE_INT, tree);
+extern bool types_same_for_odr (tree type1, tree type2);
 extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *,
                                     HOST_WIDE_INT *, HOST_WIDE_INT *);
 extern bool contains_bitfld_component_ref_p (const_tree);