+2015-05-22 Jan Hubicka <hubicka@ucw.cz>
+
+ PR lto/66180
+ * ipa-devirt.c (type_with_linkage): Check that TYPE_STUB_DECL
+ is set; check for assembler name at LTO time.
+ (type_in_anonymous_namespace): Remove hacks, check that all
+ anonymous types are called "<anon>"
+ (odr_type_p): Simplify; add check for "<anon>"
+ (odr_subtypes_equivalent): Add odr_type_p check.
+ * tree.c (need_assembler_name_p): Even anonymous namespace needs
+ assembler name.
+
2015-05-22 Jan Hubicka <hubicka@ucw.cz>
* ipa-utils.h (method_class_type): Remove.
if (dep)
return;
- id = get_mangled_id (decl);
+ /* During LTO we keep mangled names of TYPE_DECLs for ODR type merging.
+ It is not needed to assign names to anonymous namespace, but we use the
+ "<anon>" marker to be able to tell if type is C++ ODR type or type
+ produced by other language. */
+ if (TREE_CODE (decl) == TYPE_DECL
+ && TYPE_STUB_DECL (TREE_TYPE (decl))
+ && !TREE_PUBLIC (TYPE_STUB_DECL (TREE_TYPE (decl))))
+ id = get_identifier ("<anon>");
+ else
+ {
+ gcc_assert (TREE_CODE (decl) != TYPE_DECL
+ || !no_linkage_check (TREE_TYPE (decl), true));
+ id = get_mangled_id (decl);
+ }
SET_DECL_ASSEMBLER_NAME (decl, id);
if (G.need_abi_warning
{
/* Builtin types do not define linkage, their TYPE_CONTEXT is NULL. */
if (!TYPE_CONTEXT (t)
- || !TYPE_NAME (t) || TREE_CODE (TYPE_NAME (t)) != TYPE_DECL)
+ || !TYPE_NAME (t) || TREE_CODE (TYPE_NAME (t)) != TYPE_DECL
+ || !TYPE_STUB_DECL (t))
return false;
+ /* In LTO do not get confused by non-C++ produced types or types built
+ with -fno-lto-odr-type-merigng. */
+ if (in_lto_p)
+ {
+ /* To support -fno-lto-odr-type-merigng recognize types with vtables
+ to have linkage. */
+ if (RECORD_OR_UNION_TYPE_P (t)
+ && TYPE_BINFO (t) && BINFO_VTABLE (TYPE_BINFO (t)))
+ return true;
+ /* Do not accept any other types - we do not know if they were produced
+ by C++ FE. */
+ if (!DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t)))
+ return false;
+ }
+
return (RECORD_OR_UNION_TYPE_P (t)
|| TREE_CODE (t) == ENUMERAL_TYPE);
}
{
gcc_assert (type_with_linkage_p (t));
+ /* Keep -fno-lto-odr-type-merging working by recognizing classes with vtables
+ properly into anonymous namespaces. */
+ if (RECORD_OR_UNION_TYPE_P (t)
+ && TYPE_BINFO (t) && BINFO_VTABLE (TYPE_BINFO (t)))
+ return (TYPE_STUB_DECL (t) && !TREE_PUBLIC (TYPE_STUB_DECL (t)));
+
if (TYPE_STUB_DECL (t) && !TREE_PUBLIC (TYPE_STUB_DECL (t)))
{
- if (DECL_ARTIFICIAL (TYPE_NAME (t)))
- return true;
- tree ctx = DECL_CONTEXT (TYPE_NAME (t));
- while (ctx)
- {
- if (TREE_CODE (ctx) == NAMESPACE_DECL)
- return !TREE_PUBLIC (ctx);
- if (TREE_CODE (ctx) == BLOCK)
- ctx = BLOCK_SUPERCONTEXT (ctx);
- else
- ctx = get_containing_scope (ctx);
- }
+ /* C++ FE uses magic <anon> as assembler names of anonymous types.
+ verify that this match with type_in_anonymous_namespace_p. */
+#ifdef ENABLE_CHECKING
+ if (in_lto_p)
+ gcc_assert (!strcmp ("<anon>",
+ IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (t)))));
+#endif
+ return true;
}
return false;
}
bool
odr_type_p (const_tree t)
{
- if (type_with_linkage_p (t) && type_in_anonymous_namespace_p (t))
- return true;
/* We do not have this information when not in LTO, but we do not need
to care, since it is used only for type merging. */
gcc_checking_assert (in_lto_p || flag_lto);
- return (TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
- && (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t))));
+ /* To support -fno-lto-odr-type-merging consider types with vtables ODR. */
+ if (type_with_linkage_p (t) && type_in_anonymous_namespace_p (t))
+ return true;
+
+ if (TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
+ && (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t))))
+ {
+#ifdef ENABLE_CHECKING
+ /* C++ FE uses magic <anon> as assembler names of anonymous types.
+ verify that this match with type_in_anonymous_namespace_p. */
+ gcc_assert (!type_with_linkage_p (t)
+ || strcmp ("<anon>",
+ IDENTIFIER_POINTER
+ (DECL_ASSEMBLER_NAME (TYPE_NAME (t))))
+ || type_in_anonymous_namespace_p (t));
+#endif
+ return true;
+ }
+ return false;
}
/* Return TRUE if all derived types of T are known and thus
return false;
/* Limit recursion: If subtypes are ODR types and we know
that they are same, be happy. */
- if (!get_odr_type (t1, true)->odr_violated)
+ if (!odr_type_p (t1) || !get_odr_type (t1, true)->odr_violated)
return true;
}