Commit d4398a43 by Richard Guenther Committed by Richard Biener

re PR lto/42451 ('warning: type of "array" does not match original declaration' with -flto/-fwhopr)

2010-07-22  Richard Guenther  <rguenther@suse.de>

	PR lto/42451
	* gimple.c (gtc_next_dfs_num): New global.
	(struct sccs): Make value a union, add integer same_p member.
	(gtc_visit): New function.
	(gimple_types_compatible_p_1): New function, split out from ...
	(gimple_types_compatible_p): ... here.  Start a DFS walk here.
	(iterative_hash_gimple_type): Adjust for sccs change.

	* gcc.dg/lto/20100720-3_0.c: New testcase.
	* gcc.dg/lto/20100720-3_1.c: Likewise.

From-SVN: r162415
parent 3cf8ccdf
2010-07-22 Richard Guenther <rguenther@suse.de>
PR lto/42451
* gimple.c (gtc_next_dfs_num): New global.
(struct sccs): Make value a union, add integer same_p member.
(gtc_visit): New function.
(gimple_types_compatible_p_1): New function, split out from ...
(gimple_types_compatible_p): ... here. Start a DFS walk here.
(iterative_hash_gimple_type): Adjust for sccs change.
2010-07-22 Martin Jambor <mjambor@suse.cz> 2010-07-22 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/44891 PR tree-optimization/44891
......
...@@ -3174,6 +3174,9 @@ struct type_pair_d ...@@ -3174,6 +3174,9 @@ struct type_pair_d
}; };
typedef struct type_pair_d *type_pair_t; typedef struct type_pair_d *type_pair_t;
DEF_VEC_P(type_pair_t);
DEF_VEC_ALLOC_P(type_pair_t,heap);
/* Return a hash value for the type pair pointed-to by P. */ /* Return a hash value for the type pair pointed-to by P. */
static hashval_t static hashval_t
...@@ -3231,6 +3234,24 @@ lookup_type_pair (tree t1, tree t2, htab_t *visited_p, struct obstack *ob_p) ...@@ -3231,6 +3234,24 @@ lookup_type_pair (tree t1, tree t2, htab_t *visited_p, struct obstack *ob_p)
return p; return p;
} }
/* Per pointer state for the SCC finding. The on_sccstack flag
is not strictly required, it is true when there is no hash value
recorded for the type and false otherwise. But querying that
is slower. */
struct sccs
{
unsigned int dfsnum;
unsigned int low;
bool on_sccstack;
union {
hashval_t hash;
int same_p;
} u;
};
static unsigned int next_dfs_num;
static unsigned int gtc_next_dfs_num;
/* Return true if T1 and T2 have the same name. If FOR_COMPLETION_P is /* Return true if T1 and T2 have the same name. If FOR_COMPLETION_P is
true then if any type has no name return false, otherwise return true then if any type has no name return false, otherwise return
...@@ -3344,39 +3365,52 @@ gimple_compatible_complete_and_incomplete_subtype_p (tree t1, tree t2) ...@@ -3344,39 +3365,52 @@ gimple_compatible_complete_and_incomplete_subtype_p (tree t1, tree t2)
return false; return false;
} }
/* Return 1 iff T1 and T2 are structurally identical. static bool
Otherwise, return 0. */ gimple_types_compatible_p_1 (tree, tree, bool, VEC(type_pair_t, heap) **,
struct pointer_map_t *, struct obstack *);
bool /* DFS visit the edge from the callers type pair with state *STATE to
gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p) the pair T1, T2 while operating in FOR_MERGING_P mode.
Update the merging status if it is not part of the SCC containing the
callers pair and return it.
SCCSTACK, SCCSTATE and SCCSTATE_OBSTACK are state for the DFS walk done. */
static bool
gtc_visit (tree t1, tree t2, bool for_merging_p,
struct sccs *state,
VEC(type_pair_t, heap) **sccstack,
struct pointer_map_t *sccstate,
struct obstack *sccstate_obstack)
{ {
type_pair_t p = NULL; struct sccs *cstate = NULL;
type_pair_t p;
void **slot;
/* Check first for the obvious case of pointer identity. */ /* Check first for the obvious case of pointer identity. */
if (t1 == t2) if (t1 == t2)
return 1; return true;
/* Check that we have two types to compare. */ /* Check that we have two types to compare. */
if (t1 == NULL_TREE || t2 == NULL_TREE) if (t1 == NULL_TREE || t2 == NULL_TREE)
return 0; return false;
/* If the types have been previously registered and found equal /* If the types have been previously registered and found equal
they still are. */ they still are. */
if (TYPE_CANONICAL (t1) if (TYPE_CANONICAL (t1)
&& TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2)) && TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2))
return 1; return true;
/* Can't be the same type if the types don't have the same code. */ /* Can't be the same type if the types don't have the same code. */
if (TREE_CODE (t1) != TREE_CODE (t2)) if (TREE_CODE (t1) != TREE_CODE (t2))
return 0; return false;
/* Can't be the same type if they have different CV qualifiers. */ /* Can't be the same type if they have different CV qualifiers. */
if (TYPE_QUALS (t1) != TYPE_QUALS (t2)) if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
return 0; return false;
/* Void types are always the same. */ /* Void types are always the same. */
if (TREE_CODE (t1) == VOID_TYPE) if (TREE_CODE (t1) == VOID_TYPE)
return 1; return true;
/* Do some simple checks before doing three hashtable queries. */ /* Do some simple checks before doing three hashtable queries. */
if (INTEGRAL_TYPE_P (t1) if (INTEGRAL_TYPE_P (t1)
...@@ -3392,23 +3426,17 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p) ...@@ -3392,23 +3426,17 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p)
|| TYPE_PRECISION (t1) != TYPE_PRECISION (t2) || TYPE_PRECISION (t1) != TYPE_PRECISION (t2)
|| TYPE_MODE (t1) != TYPE_MODE (t2) || TYPE_MODE (t1) != TYPE_MODE (t2)
|| TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2)) || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
return 0; return false;
if (TREE_CODE (t1) == INTEGER_TYPE if (TREE_CODE (t1) == INTEGER_TYPE
&& (TYPE_IS_SIZETYPE (t1) != TYPE_IS_SIZETYPE (t2) && (TYPE_IS_SIZETYPE (t1) != TYPE_IS_SIZETYPE (t2)
|| TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2))) || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)))
return 0; return false;
/* That's all we need to check for float and fixed-point types. */ /* That's all we need to check for float and fixed-point types. */
if (SCALAR_FLOAT_TYPE_P (t1) if (SCALAR_FLOAT_TYPE_P (t1)
|| FIXED_POINT_TYPE_P (t1)) || FIXED_POINT_TYPE_P (t1))
return 1; return true;
/* Perform cheap tail-recursion for vector and complex types. */
if (TREE_CODE (t1) == VECTOR_TYPE
|| TREE_CODE (t1) == COMPLEX_TYPE)
return gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2),
for_merging_p);
/* For integral types fall thru to more complex checks. */ /* For integral types fall thru to more complex checks. */
} }
...@@ -3418,17 +3446,16 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p) ...@@ -3418,17 +3446,16 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p)
/* Can't be the same type if they have different alignment or mode. */ /* Can't be the same type if they have different alignment or mode. */
if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2) if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2)
|| TYPE_MODE (t1) != TYPE_MODE (t2)) || TYPE_MODE (t1) != TYPE_MODE (t2))
return 0; return false;
} }
/* If the hash values of t1 and t2 are different the types can't /* If the hash values of t1 and t2 are different the types can't
possibly be the same. This helps keeping the type-pair hashtable possibly be the same. This helps keeping the type-pair hashtable
small, only tracking comparisons for hash collisions. */ small, only tracking comparisons for hash collisions. */
if (gimple_type_hash (t1) != gimple_type_hash (t2)) if (gimple_type_hash (t1) != gimple_type_hash (t2))
return 0; return false;
/* If we've visited this type pair before (in the case of aggregates /* Allocate a new cache entry for this comparison. */
with self-referential types), and we made a decision, return it. */
p = lookup_type_pair (t1, t2, p = lookup_type_pair (t1, t2,
for_merging_p ? &gtc_visited : &gtc_visited2, for_merging_p ? &gtc_visited : &gtc_visited2,
for_merging_p ? &gtc_ob : &gtc_ob2); for_merging_p ? &gtc_ob : &gtc_ob2);
...@@ -3438,17 +3465,60 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p) ...@@ -3438,17 +3465,60 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p)
same, return the cached result. */ same, return the cached result. */
return p->same_p == 1; return p->same_p == 1;
} }
else if (p->same_p == -1)
gcc_assert (p->same_p == -2);
if ((slot = pointer_map_contains (sccstate, p)) != NULL)
cstate = (struct sccs *)*slot;
if (!cstate)
{ {
/* We are currently comparing this pair of types, assume bool res;
that they are the same and let the caller decide. */ /* Not yet visited. DFS recurse. */
return 1; res = gimple_types_compatible_p_1 (t1, t2, for_merging_p,
sccstack, sccstate, sccstate_obstack);
if (!cstate)
cstate = (struct sccs *)* pointer_map_contains (sccstate, p);
state->low = MIN (state->low, cstate->low);
/* If the type is no longer on the SCC stack and thus is not part
of the parents SCC mix in its hash value. Otherwise we will
ignore the type for hashing purposes and return the unaltered
hash value. */
if (!cstate->on_sccstack)
return res;
} }
if (cstate->dfsnum < state->dfsnum
&& cstate->on_sccstack)
state->low = MIN (cstate->dfsnum, state->low);
/* We are part of our parents SCC, skip this entry and return true. */
return true;
}
/* Worker for gimple_types_compatible.
SCCSTACK, SCCSTATE and SCCSTATE_OBSTACK are state for the DFS walk done. */
static bool
gimple_types_compatible_p_1 (tree t1, tree t2, bool for_merging_p,
VEC(type_pair_t, heap) **sccstack,
struct pointer_map_t *sccstate,
struct obstack *sccstate_obstack)
{
type_pair_t p;
struct sccs *state;
/* Allocate a new cache entry for this comparison. */
p = lookup_type_pair (t1, t2,
for_merging_p ? &gtc_visited : &gtc_visited2,
for_merging_p ? &gtc_ob : &gtc_ob2);
gcc_assert (p->same_p == -2); gcc_assert (p->same_p == -2);
/* Mark the (T1, T2) comparison in progress. */ state = XOBNEW (sccstate_obstack, struct sccs);
p->same_p = -1; *pointer_map_insert (sccstate, p) = state;
VEC_safe_push (type_pair_t, heap, *sccstack, p);
state->dfsnum = gtc_next_dfs_num++;
state->low = state->dfsnum;
state->on_sccstack = true;
/* If their attributes are not the same they can't be the same type. */ /* If their attributes are not the same they can't be the same type. */
if (!attribute_list_equal (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2))) if (!attribute_list_equal (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2)))
...@@ -3457,11 +3527,18 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p) ...@@ -3457,11 +3527,18 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p)
/* Do type-specific comparisons. */ /* Do type-specific comparisons. */
switch (TREE_CODE (t1)) switch (TREE_CODE (t1))
{ {
case VECTOR_TYPE:
case COMPLEX_TYPE:
if (!gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2), for_merging_p,
state, sccstack, sccstate, sccstate_obstack))
goto different_types;
goto same_types;
case ARRAY_TYPE: case ARRAY_TYPE:
/* Array types are the same if the element types are the same and /* Array types are the same if the element types are the same and
the number of elements are the same. */ the number of elements are the same. */
if (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2), if (!gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2), for_merging_p,
for_merging_p) state, sccstack, sccstate, sccstate_obstack)
|| TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2) || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)
|| TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2)) || TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2))
goto different_types; goto different_types;
...@@ -3509,8 +3586,9 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p) ...@@ -3509,8 +3586,9 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p)
case METHOD_TYPE: case METHOD_TYPE:
/* Method types should belong to the same class. */ /* Method types should belong to the same class. */
if (!gimple_types_compatible_p (TYPE_METHOD_BASETYPE (t1), if (!gtc_visit (TYPE_METHOD_BASETYPE (t1), TYPE_METHOD_BASETYPE (t2),
TYPE_METHOD_BASETYPE (t2), for_merging_p)) for_merging_p,
state, sccstack, sccstate, sccstate_obstack))
goto different_types; goto different_types;
/* Fallthru */ /* Fallthru */
...@@ -3521,8 +3599,8 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p) ...@@ -3521,8 +3599,8 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p)
if ((for_merging_p if ((for_merging_p
|| !gimple_compatible_complete_and_incomplete_subtype_p || !gimple_compatible_complete_and_incomplete_subtype_p
(TREE_TYPE (t1), TREE_TYPE (t2))) (TREE_TYPE (t1), TREE_TYPE (t2)))
&& !gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2), && !gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2), for_merging_p,
for_merging_p)) state, sccstack, sccstate, sccstate_obstack))
goto different_types; goto different_types;
if (!targetm.comp_type_attributes (t1, t2)) if (!targetm.comp_type_attributes (t1, t2))
...@@ -3541,9 +3619,9 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p) ...@@ -3541,9 +3619,9 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p)
if ((for_merging_p if ((for_merging_p
|| !gimple_compatible_complete_and_incomplete_subtype_p || !gimple_compatible_complete_and_incomplete_subtype_p
(TREE_VALUE (parms1), TREE_VALUE (parms2))) (TREE_VALUE (parms1), TREE_VALUE (parms2)))
&& !gimple_types_compatible_p (TREE_VALUE (parms1), && !gtc_visit (TREE_VALUE (parms1), TREE_VALUE (parms2),
TREE_VALUE (parms2), for_merging_p,
for_merging_p)) state, sccstack, sccstate, sccstate_obstack))
goto different_types; goto different_types;
} }
...@@ -3555,11 +3633,11 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p) ...@@ -3555,11 +3633,11 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p)
case OFFSET_TYPE: case OFFSET_TYPE:
{ {
if (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2), if (!gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2), for_merging_p,
for_merging_p) state, sccstack, sccstate, sccstate_obstack)
|| !gimple_types_compatible_p (TYPE_OFFSET_BASETYPE (t1), || !gtc_visit (TYPE_OFFSET_BASETYPE (t1),
TYPE_OFFSET_BASETYPE (t2), TYPE_OFFSET_BASETYPE (t2), for_merging_p,
for_merging_p)) state, sccstack, sccstate, sccstate_obstack))
goto different_types; goto different_types;
goto same_types; goto same_types;
...@@ -3582,8 +3660,8 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p) ...@@ -3582,8 +3660,8 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p)
/* Otherwise, pointer and reference types are the same if the /* Otherwise, pointer and reference types are the same if the
pointed-to types are the same. */ pointed-to types are the same. */
if (gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2), if (gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2), for_merging_p,
for_merging_p)) state, sccstack, sccstate, sccstate_obstack))
goto same_types; goto same_types;
goto different_types; goto different_types;
...@@ -3678,8 +3756,8 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p) ...@@ -3678,8 +3756,8 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p)
if (DECL_NAME (f1) != DECL_NAME (f2) if (DECL_NAME (f1) != DECL_NAME (f2)
|| DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2) || DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
|| !gimple_compare_field_offset (f1, f2) || !gimple_compare_field_offset (f1, f2)
|| !gimple_types_compatible_p (TREE_TYPE (f1), || !gtc_visit (TREE_TYPE (f1), TREE_TYPE (f2), for_merging_p,
TREE_TYPE (f2), for_merging_p)) state, sccstack, sccstate, sccstate_obstack))
goto different_types; goto different_types;
} }
...@@ -3697,32 +3775,143 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p) ...@@ -3697,32 +3775,143 @@ gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p)
/* Common exit path for types that are not compatible. */ /* Common exit path for types that are not compatible. */
different_types: different_types:
p->same_p = 0; state->u.same_p = 0;
return 0; goto pop;
/* Common exit path for types that are compatible. */ /* Common exit path for types that are compatible. */
same_types: same_types:
p->same_p = 1; state->u.same_p = 1;
return 1; goto pop;
}
pop:
if (state->low == state->dfsnum)
{
type_pair_t x;
/* Pop off the SCC and set its cache values. */
do
{
struct sccs *cstate;
x = VEC_pop (type_pair_t, *sccstack);
cstate = (struct sccs *)*pointer_map_contains (sccstate, x);
cstate->on_sccstack = false;
x->same_p = cstate->u.same_p;
}
while (x != p);
}
return state->u.same_p;
}
/* Per pointer state for the SCC finding. The on_sccstack flag /* Return true iff T1 and T2 are structurally identical. When
is not strictly required, it is true when there is no hash value FOR_MERGING_P is true the an incomplete type and a complete type
recorded for the type and false otherwise. But querying that are considered different, otherwise they are considered compatible. */
is slower. */
struct sccs bool
gimple_types_compatible_p (tree t1, tree t2, bool for_merging_p)
{ {
unsigned int dfsnum; VEC(type_pair_t, heap) *sccstack = NULL;
unsigned int low; struct pointer_map_t *sccstate;
bool on_sccstack; struct obstack sccstate_obstack;
hashval_t hash; type_pair_t p = NULL;
}; bool res;
/* Before starting to set up the SCC machinery handle simple cases. */
/* Check first for the obvious case of pointer identity. */
if (t1 == t2)
return true;
/* Check that we have two types to compare. */
if (t1 == NULL_TREE || t2 == NULL_TREE)
return false;
/* If the types have been previously registered and found equal
they still are. */
if (TYPE_CANONICAL (t1)
&& TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2))
return true;
/* Can't be the same type if the types don't have the same code. */
if (TREE_CODE (t1) != TREE_CODE (t2))
return false;
/* Can't be the same type if they have different CV qualifiers. */
if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
return false;
/* Void types are always the same. */
if (TREE_CODE (t1) == VOID_TYPE)
return true;
/* Do some simple checks before doing three hashtable queries. */
if (INTEGRAL_TYPE_P (t1)
|| SCALAR_FLOAT_TYPE_P (t1)
|| FIXED_POINT_TYPE_P (t1)
|| TREE_CODE (t1) == VECTOR_TYPE
|| TREE_CODE (t1) == COMPLEX_TYPE
|| TREE_CODE (t1) == OFFSET_TYPE)
{
/* Can't be the same type if they have different alignment,
sign, precision or mode. */
if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2)
|| TYPE_PRECISION (t1) != TYPE_PRECISION (t2)
|| TYPE_MODE (t1) != TYPE_MODE (t2)
|| TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
return false;
if (TREE_CODE (t1) == INTEGER_TYPE
&& (TYPE_IS_SIZETYPE (t1) != TYPE_IS_SIZETYPE (t2)
|| TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)))
return false;
/* That's all we need to check for float and fixed-point types. */
if (SCALAR_FLOAT_TYPE_P (t1)
|| FIXED_POINT_TYPE_P (t1))
return true;
/* For integral types fall thru to more complex checks. */
}
else if (AGGREGATE_TYPE_P (t1) || POINTER_TYPE_P (t1))
{
/* Can't be the same type if they have different alignment or mode. */
if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2)
|| TYPE_MODE (t1) != TYPE_MODE (t2))
return false;
}
/* If the hash values of t1 and t2 are different the types can't
possibly be the same. This helps keeping the type-pair hashtable
small, only tracking comparisons for hash collisions. */
if (gimple_type_hash (t1) != gimple_type_hash (t2))
return false;
/* If we've visited this type pair before (in the case of aggregates
with self-referential types), and we made a decision, return it. */
p = lookup_type_pair (t1, t2,
for_merging_p ? &gtc_visited : &gtc_visited2,
for_merging_p ? &gtc_ob : &gtc_ob2);
if (p->same_p == 0 || p->same_p == 1)
{
/* We have already decided whether T1 and T2 are the
same, return the cached result. */
return p->same_p == 1;
}
/* Now set up the SCC machinery for the comparison. */
gtc_next_dfs_num = 1;
sccstate = pointer_map_create ();
gcc_obstack_init (&sccstate_obstack);
res = gimple_types_compatible_p_1 (t1, t2, for_merging_p,
&sccstack, sccstate, &sccstate_obstack);
VEC_free (type_pair_t, heap, sccstack);
pointer_map_destroy (sccstate);
obstack_free (&sccstate_obstack, NULL);
return res;
}
static unsigned int next_dfs_num;
static hashval_t static hashval_t
iterative_hash_gimple_type (tree, hashval_t, VEC(tree, heap) **, iterative_hash_gimple_type (tree, hashval_t, VEC(tree, heap) **,
...@@ -3950,7 +4139,7 @@ iterative_hash_gimple_type (tree type, hashval_t val, ...@@ -3950,7 +4139,7 @@ iterative_hash_gimple_type (tree type, hashval_t val,
} }
/* Record hash for us. */ /* Record hash for us. */
state->hash = v; state->u.hash = v;
/* See if we found an SCC. */ /* See if we found an SCC. */
if (state->low == state->dfsnum) if (state->low == state->dfsnum)
...@@ -3966,7 +4155,7 @@ iterative_hash_gimple_type (tree type, hashval_t val, ...@@ -3966,7 +4155,7 @@ iterative_hash_gimple_type (tree type, hashval_t val,
cstate = (struct sccs *)*pointer_map_contains (sccstate, x); cstate = (struct sccs *)*pointer_map_contains (sccstate, x);
cstate->on_sccstack = false; cstate->on_sccstack = false;
slot = pointer_map_insert (type_hash_cache, x); slot = pointer_map_insert (type_hash_cache, x);
*slot = (void *) (size_t) cstate->hash; *slot = (void *) (size_t) cstate->u.hash;
} }
while (x != type); while (x != type);
} }
......
2010-07-22 Richard Guenther <rguenther@suse.de> 2010-07-22 Richard Guenther <rguenther@suse.de>
PR lto/42451
* gcc.dg/lto/20100720-3_0.c: New testcase.
* gcc.dg/lto/20100720-3_1.c: Likewise.
2010-07-22 Richard Guenther <rguenther@suse.de>
* lib/target-supports-dg.exp (dg-require-linker-plugin): New proc. * lib/target-supports-dg.exp (dg-require-linker-plugin): New proc.
* lib/target-supports.exp (check_linker_plugin_available): Likewise. * lib/target-supports.exp (check_linker_plugin_available): Likewise.
......
/* { dg-lto-do run } */
struct X {
int a;
};
struct link {
struct list_node *next;
};
struct list_node {
struct link lnk;
struct X *value;
};
void f(struct list_node *lst)
{
lst->lnk.next = 0;
}
int main(void)
{
return 0;
}
struct X {
int b;
};
struct link {
struct list_node *next;
};
struct list_node {
struct link lnk;
struct X *value;
};
void g(struct list_node *lst)
{
lst->lnk.next = 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment