static GTY(()) vec <odr_type, va_gc> *odr_types_ptr;
#define odr_types (*odr_types_ptr)
+/* Set TYPE_BINFO of TYPE and its variants to BINFO. */
+void
+set_type_binfo (tree type, tree binfo)
+{
+ for (; type; type = TYPE_NEXT_VARIANT (type))
+ if (COMPLETE_TYPE_P (type))
+ TYPE_BINFO (type) = binfo;
+ else
+ gcc_assert (!TYPE_BINFO (type));
+}
+
/* TYPE is equivalent to VAL by ODR, but its tree representation differs
from VAL->type. This may happen in LTO where tree merging did not merge
all variants of the same type. It may or may not mean the ODR violation.
{
unsigned int i;
- TYPE_BINFO (val->type) = TYPE_BINFO (type);
+ set_type_binfo (val->type, TYPE_BINFO (type));
for (i = 0; i < val->types->length (); i++)
{
if (TYPE_BINFO ((*val->types)[i])
== master_binfo)
- TYPE_BINFO ((*val->types)[i]) = TYPE_BINFO (type);
+ set_type_binfo ((*val->types)[i], TYPE_BINFO (type));
}
+ BINFO_TYPE (TYPE_BINFO (type)) = val->type;
}
else
- TYPE_BINFO (type) = master_binfo;
+ set_type_binfo (type, master_binfo);
}
}
}
val = ggc_cleared_alloc<odr_type_d> ();
val->type = type;
+ gcc_assert (BINFO_TYPE (TYPE_BINFO (val->type)) = type);
val->bases = vNULL;
val->derived_types = vNULL;
val->anonymous_namespace = type_in_anonymous_namespace_p (type);
if (!fld)
goto give_up;
- type = TREE_TYPE (fld);
+ type = TYPE_MAIN_VARIANT (TREE_TYPE (fld));
offset -= pos;
/* DECL_ARTIFICIAL represents a basetype. */
if (!DECL_ARTIFICIAL (fld))
}
else if (TREE_CODE (type) == ARRAY_TYPE)
{
- tree subtype = TREE_TYPE (type);
+ tree subtype = TYPE_MAIN_VARIANT (TREE_TYPE (type));
/* Give up if we don't know array size. */
if (!tree_fits_shwi_p (TYPE_SIZE (subtype))
contains_type_p (tree outer_type, HOST_WIDE_INT offset,
tree otr_type)
{
- ipa_polymorphic_call_context context = {offset, outer_type,
+ ipa_polymorphic_call_context context = {offset,
+ TYPE_MAIN_VARIANT (outer_type),
false, true};
return get_class_context (&context, otr_type);
}
{
gcc_assert (DECL_P (base));
- context->outer_type = TREE_TYPE (base);
+ context->outer_type = TYPE_MAIN_VARIANT (TREE_TYPE (base));
context->offset = offset;
/* Make very conservative assumption that all objects
may be in construction.
*otr_token = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (ref));
/* Set up basic info in case we find nothing interesting in the analysis. */
- context->outer_type = *otr_type;
+ context->outer_type = TYPE_MAIN_VARIANT (*otr_type);
context->offset = 0;
base_pointer = OBJ_TYPE_REF_OBJECT (ref);
context->maybe_derived_type = true;
if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE
&& SSA_NAME_VAR (base_pointer) == DECL_ARGUMENTS (fndecl))
{
- context->outer_type = TREE_TYPE (TREE_TYPE (base_pointer));
+ context->outer_type
+ = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (base_pointer)));
gcc_assert (TREE_CODE (context->outer_type) == RECORD_TYPE);
/* Dynamic casting has possibly upcasted the type
object. */
if (DECL_BY_REFERENCE (SSA_NAME_VAR (base_pointer)))
{
- context->outer_type = TREE_TYPE (TREE_TYPE (base_pointer));
+ context->outer_type
+ = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (base_pointer)));
gcc_assert (!POINTER_TYPE_P (context->outer_type));
/* Only type inconsistent programs can have otr_type that is
not part of outer type. */
bool can_refer;
bool skipped = false;
+ otr_type = TYPE_MAIN_VARIANT (otr_type);
+
/* If ODR is not initialized, return empty incomplete list. */
if (!odr_hash)
{
type = get_odr_type (otr_type, true);
+ /* Recording type variants would wast results cache. */
+ gcc_assert (!context.outer_type
+ || TYPE_MAIN_VARIANT (context.outer_type) == context.outer_type);
+
/* Lookup the outer class type we want to walk. */
if (context.outer_type
&& !get_class_context (&context, otr_type))
return nodes;
}
+ /* Check that get_class_context kept the main variant. */
+ gcc_assert (!context.outer_type
+ || TYPE_MAIN_VARIANT (context.outer_type) == context.outer_type);
+
/* We canonicalize our query, so we do not need extra hashtable entries. */
/* Without outer type, we have no use for offset. Just do the