bool rtti_broken;
};
+/* Return true if T is a type with linkage defined. */
+
+static bool
+type_with_linkage_p (const_tree t)
+{
+ return (RECORD_OR_UNION_TYPE_P (t)
+ || TREE_CODE (t) == ENUMERAL_TYPE);
+}
+
+/* Return true if T is in anonymous namespace.
+ This works only on those C++ types with linkage defined. */
+
+bool
+type_in_anonymous_namespace_p (const_tree t)
+{
+ gcc_assert (type_with_linkage_p (t));
+ /* TREE_PUBLIC of TYPE_STUB_DECL may not be properly set for
+ backend produced types (such as va_arg_type); those have CONTEXT NULL
+ and never are considered anonymoius. */
+ if (!TYPE_CONTEXT (t))
+ return false;
+ return (TYPE_STUB_DECL (t) && !TREE_PUBLIC (TYPE_STUB_DECL (t)));
+}
+
+/* Return true of T is type with One Definition Rule info attached.
+ It means that either it is anonymous type or it has assembler name
+ set. */
+
+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)
+ && (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t))));
+}
+
/* Return TRUE if all derived types of T are known and thus
we may consider the walk of derived type complete.
static bool
can_be_name_hashed_p (tree t)
{
- return (!in_lto_p || type_in_anonymous_namespace_p (t)
- || (TYPE_NAME (t) && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t))));
+ return (!in_lto_p || odr_type_p (t));
}
/* Hash type by its ODR name. */
return htab_hash_pointer (t);
/* Anonymous types are unique. */
- if (type_in_anonymous_namespace_p (t))
+ if (type_with_linkage_p (t) && type_in_anonymous_namespace_p (t))
return htab_hash_pointer (t);
gcc_checking_assert (TYPE_NAME (t)
if (TYPE_MAIN_VARIANT (t) != t)
return false;
/* Anonymous namespace types are always handled by name hash. */
- if (type_in_anonymous_namespace_p (t))
+ if (type_with_linkage_p (t) && type_in_anonymous_namespace_p (t))
return false;
return (TREE_CODE (t) == RECORD_TYPE
&& TYPE_BINFO (t) && BINFO_VTABLE (TYPE_BINFO (t)));
/* Check for anonymous namespaces. Those have !TREE_PUBLIC
on the corresponding TYPE_STUB_DECL. */
- if (type_in_anonymous_namespace_p (type1)
- || type_in_anonymous_namespace_p (type2))
+ if ((type_with_linkage_p (type1) && type_in_anonymous_namespace_p (type1))
+ || (type_with_linkage_p (type2) && type_in_anonymous_namespace_p (type2)))
return false;
return false;
/* Check for anonymous namespaces. Those have !TREE_PUBLIC
on the corresponding TYPE_STUB_DECL. */
- if (type_in_anonymous_namespace_p (t1)
- || type_in_anonymous_namespace_p (t2))
+ if ((type_with_linkage_p (t1) && type_in_anonymous_namespace_p (t1))
+ || (type_with_linkage_p (t2) && type_in_anonymous_namespace_p (t2)))
return false;
gcc_checking_assert (DECL_ASSEMBLER_NAME (TYPE_NAME (t1)));
gcc_checking_assert (DECL_ASSEMBLER_NAME (TYPE_NAME (t2)));
odr_subtypes_equivalent_p (tree t1, tree t2,
hash_set<type_pair,pair_traits> *visited)
{
- bool an1, an2;
/* This can happen in incomplete types that should be handled earlier. */
gcc_assert (t1 && t2);
return true;
/* Anonymous namespace types must match exactly. */
- an1 = type_in_anonymous_namespace_p (t1);
- an2 = type_in_anonymous_namespace_p (t2);
- if (an1 != an2 || an1)
+ if ((type_with_linkage_p (t1) && type_in_anonymous_namespace_p (t1))
+ || (type_with_linkage_p (t2) && type_in_anonymous_namespace_p (t2)))
return false;
/* For ODR types be sure to compare their names.
}
/* It is a quite common bug to reference anonymous namespace type in
non-anonymous namespace class. */
- if (type_in_anonymous_namespace_p (t1)
- || type_in_anonymous_namespace_p (t2))
+ if ((type_with_linkage_p (t1) && type_in_anonymous_namespace_p (t1))
+ || (type_with_linkage_p (t2) && type_in_anonymous_namespace_p (t2)))
{
- if (!type_in_anonymous_namespace_p (t1))
+ if (type_with_linkage_p (t1) && !type_in_anonymous_namespace_p (t1))
{
tree tmp = t1;;
t1 = t2;
/* Check first for the obvious case of pointer identity. */
if (t1 == t2)
return true;
- gcc_assert (!type_in_anonymous_namespace_p (t1));
- gcc_assert (!type_in_anonymous_namespace_p (t2));
+ gcc_assert (!type_with_linkage_p (t1) || !type_in_anonymous_namespace_p (t1));
+ gcc_assert (!type_with_linkage_p (t2) || !type_in_anonymous_namespace_p (t2));
/* Can't be the same type if the types don't have the same code. */
if (TREE_CODE (t1) != TREE_CODE (t2))
return false;
}
if ((TYPE_MAIN_VARIANT (t1) == t1 || TYPE_MAIN_VARIANT (t2) == t2)
+ && COMPLETE_TYPE_P (TYPE_MAIN_VARIANT (t1))
+ && COMPLETE_TYPE_P (TYPE_MAIN_VARIANT (t2))
+ && odr_type_p (TYPE_MAIN_VARIANT (t1))
+ && odr_type_p (TYPE_MAIN_VARIANT (t2))
&& (TYPE_METHODS (TYPE_MAIN_VARIANT (t1))
!= TYPE_METHODS (TYPE_MAIN_VARIANT (t2))))
{
- for (f1 = TYPE_METHODS (TYPE_MAIN_VARIANT (t1)),
- f2 = TYPE_METHODS (TYPE_MAIN_VARIANT (t2));
- f1 && f2 ; f1 = DECL_CHAIN (f1), f2 = DECL_CHAIN (f2))
- {
- if (DECL_ASSEMBLER_NAME (f1) != DECL_ASSEMBLER_NAME (f2))
- {
- warn_odr (t1, t2, f1, f2, warn, warned,
- G_("a different method of same type "
- "is defined in another translation unit"));
- return false;
- }
- if (DECL_VIRTUAL_P (f1) != DECL_VIRTUAL_P (f2))
- {
- warn_odr (t1, t2, f1, f2, warn, warned,
- G_("s definition that differs by virtual "
- "keyword in another translation unit"));
- return false;
- }
- if (DECL_VINDEX (f1) != DECL_VINDEX (f2))
- {
- warn_odr (t1, t2, f1, f2, warn, warned,
- G_("virtual table layout differs in another "
- "translation unit"));
- return false;
- }
- if (odr_subtypes_equivalent_p (TREE_TYPE (f1), TREE_TYPE (f2), visited))
- {
- warn_odr (t1, t2, f1, f2, warn, warned,
- G_("method with incompatible type is defined "
- "in another translation unit"));
- return false;
- }
- }
- if (f1 || f2)
+ /* Currently free_lang_data sets TYPE_METHODS to error_mark_node
+ if it is non-NULL so this loop will never realy execute. */
+ if (TYPE_METHODS (TYPE_MAIN_VARIANT (t1)) != error_mark_node
+ && TYPE_METHODS (TYPE_MAIN_VARIANT (t2)) != error_mark_node)
+ for (f1 = TYPE_METHODS (TYPE_MAIN_VARIANT (t1)),
+ f2 = TYPE_METHODS (TYPE_MAIN_VARIANT (t2));
+ f1 && f2 ; f1 = DECL_CHAIN (f1), f2 = DECL_CHAIN (f2))
+ {
+ if (DECL_ASSEMBLER_NAME (f1) != DECL_ASSEMBLER_NAME (f2))
+ {
+ warn_odr (t1, t2, f1, f2, warn, warned,
+ G_("a different method of same type "
+ "is defined in another "
+ "translation unit"));
+ return false;
+ }
+ if (DECL_VIRTUAL_P (f1) != DECL_VIRTUAL_P (f2))
+ {
+ warn_odr (t1, t2, f1, f2, warn, warned,
+ G_("s definition that differs by virtual "
+ "keyword in another translation unit"));
+ return false;
+ }
+ if (DECL_VINDEX (f1) != DECL_VINDEX (f2))
+ {
+ warn_odr (t1, t2, f1, f2, warn, warned,
+ G_("virtual table layout differs "
+ "in another translation unit"));
+ return false;
+ }
+ if (odr_subtypes_equivalent_p (TREE_TYPE (f1),
+ TREE_TYPE (f2), visited))
+ {
+ warn_odr (t1, t2, f1, f2, warn, warned,
+ G_("method with incompatible type is "
+ "defined in another translation unit"));
+ return false;
+ }
+ }
+ if ((f1 == NULL) != (f2 == NULL))
{
warn_odr (t1, t2, NULL, NULL, warn, warned,
G_("a type with different number of methods "
val->type = type;
val->bases = vNULL;
val->derived_types = vNULL;
- val->anonymous_namespace = type_in_anonymous_namespace_p (type);
+ if (type_with_linkage_p (type))
+ val->anonymous_namespace = type_in_anonymous_namespace_p (type);
+ else
+ val->anonymous_namespace = 0;
build_bases = COMPLETE_TYPE_P (val->type);
insert_to_odr_array = true;
if (slot)