aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree.c')
-rw-r--r--gcc/tree.c44
1 files changed, 39 insertions, 5 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index b469b97..7e44b40 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -11853,11 +11853,6 @@ types_same_for_odr (tree type1, tree 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;
@@ -11868,7 +11863,46 @@ types_same_for_odr (tree type1, tree type2)
if (type_in_anonymous_namespace_p (type1)
|| type_in_anonymous_namespace_p (type2))
return false;
+ /* When assembler name of virtual table is available, it is
+ easy to compare types for equivalence. */
+ if (TYPE_BINFO (type1) && TYPE_BINFO (type2)
+ && BINFO_VTABLE (TYPE_BINFO (type1))
+ && BINFO_VTABLE (TYPE_BINFO (type2)))
+ {
+ tree v1 = BINFO_VTABLE (TYPE_BINFO (type1));
+ tree v2 = BINFO_VTABLE (TYPE_BINFO (type2));
+ if (TREE_CODE (v1) == POINTER_PLUS_EXPR)
+ {
+ if (TREE_CODE (v2) != POINTER_PLUS_EXPR
+ || !operand_equal_p (TREE_OPERAND (v1, 1),
+ TREE_OPERAND (v2, 1), 0))
+ return false;
+ v1 = TREE_OPERAND (TREE_OPERAND (v1, 0), 0);
+ v2 = TREE_OPERAND (TREE_OPERAND (v2, 0), 0);
+ }
+ v1 = DECL_ASSEMBLER_NAME (v1);
+ v2 = DECL_ASSEMBLER_NAME (v2);
+ /* If we ever start adding random .blah suffixes after
+ assembler names, we need to compare for match ignoring
+ these (and update odr_type_hash, too). */
+#ifdef ENABLE_CHECKING
+ gcc_assert (!strchr (IDENTIFIER_POINTER (v1), '.')
+ && !strchr (IDENTIFIER_POINTER (v2), '.'));
+#endif
+ return (v1 == v2);
+ }
+
+ /* FIXME: the code comparing type names consider all instantiations of the
+ same template to have same name. This is because we have no access
+ to template parameters. For types with no virtual method tables
+ we thus can return false positives. At the moment we do not need
+ to compare types in other scenarios than devirtualization. */
+
+ /* 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;
if (!TYPE_NAME (type1))
return false;
if (!decls_same_for_odr (TYPE_NAME (type1), TYPE_NAME (type2)))