re PR lto/44889 (Bogus "type of ‘nsLayoutModule_NSModule’ does not match original declaration" waning compiling Mozilla)

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

	PR lto/44889
	* gimple.c (gimple_fixup_complete_and_incomplete_subtype_p): New
	helper function.
	(gimple_types_compatible_p): Similar to pointed-to
	types allow and merge a mix of complete and incomplete aggregate.
	Use gimple_fixup_complete_and_incomplete_subtype_p for that.
	(iterative_hash_gimple_type): Adjust for that.

	* gcc.dg/lto/20100709-1_0.c: New testcase.
	* gcc.dg/lto/20100709-1_1.c: Likewise.

From-SVN: r162032
This commit is contained in:
Richard Guenther 2010-07-10 08:39:46 +00:00 committed by Richard Biener
parent 7e9b96974a
commit bcee752ee5
5 changed files with 120 additions and 50 deletions

View File

@ -1,3 +1,13 @@
2010-07-10 Richard Guenther <rguenther@suse.de>
PR lto/44889
* gimple.c (gimple_fixup_complete_and_incomplete_subtype_p): New
helper function.
(gimple_types_compatible_p): Similar to pointed-to
types allow and merge a mix of complete and incomplete aggregate.
Use gimple_fixup_complete_and_incomplete_subtype_p for that.
(iterative_hash_gimple_type): Adjust for that.
2010-07-10 Richard Sandiford <r.sandiford@uk.ibm.com>
* tree.h (DECL_REPLACEABLE_P): Strengthen check for weak symbols.

View File

@ -3343,6 +3343,45 @@ gimple_queue_type_fixup (tree context, tree *incomplete, tree complete)
VEC_safe_push (type_fixup, heap, gimple_register_type_fixups, &f);
}
/* If the type *T1P and the type *T2P are a complete and an incomplete
variant of the same type return true and queue a fixup for the
incomplete one and its CONTEXT. Return false otherwise. */
static bool
gimple_fixup_complete_and_incomplete_subtype_p (tree context1, tree *t1p,
tree context2, tree *t2p)
{
tree t1 = *t1p;
tree t2 = *t2p;
/* If one pointer points to an incomplete type variant of
the other pointed-to type they are the same. */
if (TREE_CODE (t1) == TREE_CODE (t2)
&& RECORD_OR_UNION_TYPE_P (t1)
&& (!COMPLETE_TYPE_P (t1)
|| !COMPLETE_TYPE_P (t2))
&& TYPE_QUALS (t1) == TYPE_QUALS (t2)
&& compare_type_names_p (TYPE_MAIN_VARIANT (t1),
TYPE_MAIN_VARIANT (t2), true))
{
/* Replace the pointed-to incomplete type with the complete one.
??? This simple name-based merging causes at least some
of the ICEs in canonicalizing FIELD_DECLs during stmt
read. For example in GCC we have two different struct deps
and we mismatch the use in struct cpp_reader in sched-int.h
vs. mkdeps.c. Of course the whole exercise is for TBAA
with structs which contain pointers to incomplete types
in one unit and to complete ones in another. So we
probably should merge these types only with more context. */
if (COMPLETE_TYPE_P (t2))
gimple_queue_type_fixup (context1, t1p, t2);
else
gimple_queue_type_fixup (context2, t2p, t1);
return true;
}
return false;
}
/* Return 1 iff T1 and T2 are structurally identical.
Otherwise, return 0. */
@ -3507,33 +3546,35 @@ gimple_types_compatible_p (tree t1, tree t2)
case FUNCTION_TYPE:
/* Function types are the same if the return type and arguments types
are the same. */
if (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
if (!gimple_fixup_complete_and_incomplete_subtype_p
(t1, &TREE_TYPE (t1), t2, &TREE_TYPE (t2))
&& !gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
goto different_types;
if (!targetm.comp_type_attributes (t1, t2))
goto different_types;
if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2))
goto same_types;
else
{
if (!targetm.comp_type_attributes (t1, t2))
tree parms1, parms2;
for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2);
parms1 && parms2;
parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
{
if (!gimple_fixup_complete_and_incomplete_subtype_p
(t1, &TREE_VALUE (parms1), t2, &TREE_VALUE (parms2))
&& !gimple_types_compatible_p (TREE_VALUE (parms1),
TREE_VALUE (parms2)))
goto different_types;
}
if (parms1 || parms2)
goto different_types;
if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2))
goto same_types;
else
{
tree parms1, parms2;
for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2);
parms1 && parms2;
parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
{
if (!gimple_types_compatible_p (TREE_VALUE (parms1),
TREE_VALUE (parms2)))
goto different_types;
}
if (parms1 || parms2)
goto different_types;
goto same_types;
}
goto same_types;
}
case OFFSET_TYPE:
@ -3556,30 +3597,9 @@ gimple_types_compatible_p (tree t1, tree t2)
/* If one pointer points to an incomplete type variant of
the other pointed-to type they are the same. */
if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2))
&& RECORD_OR_UNION_TYPE_P (TREE_TYPE (t1))
&& (!COMPLETE_TYPE_P (TREE_TYPE (t1))
|| !COMPLETE_TYPE_P (TREE_TYPE (t2)))
&& TYPE_QUALS (TREE_TYPE (t1)) == TYPE_QUALS (TREE_TYPE (t2))
&& compare_type_names_p (TYPE_MAIN_VARIANT (TREE_TYPE (t1)),
TYPE_MAIN_VARIANT (TREE_TYPE (t2)), true))
{
/* Replace the pointed-to incomplete type with the
complete one.
??? This simple name-based merging causes at least some
of the ICEs in canonicalizing FIELD_DECLs during stmt
read. For example in GCC we have two different struct deps
and we mismatch the use in struct cpp_reader in sched-int.h
vs. mkdeps.c. Of course the whole exercise is for TBAA
with structs which contain pointers to incomplete types
in one unit and to complete ones in another. So we
probably should merge these types only with more context. */
if (COMPLETE_TYPE_P (TREE_TYPE (t2)))
gimple_queue_type_fixup (t1, &TREE_TYPE (t1), TREE_TYPE (t2));
else
gimple_queue_type_fixup (t2, &TREE_TYPE (t2), TREE_TYPE (t1));
goto same_types;
}
if (gimple_fixup_complete_and_incomplete_subtype_p
(t1, &TREE_TYPE (t1), t2, &TREE_TYPE (t2)))
goto same_types;
/* Otherwise, pointer and reference types are the same if the
pointed-to types are the same. */
@ -3900,13 +3920,29 @@ iterative_hash_gimple_type (tree type, hashval_t val,
v = visit (TYPE_METHOD_BASETYPE (type), state, v,
sccstack, sccstate, sccstate_obstack);
v = visit (TREE_TYPE (type), state, v,
sccstack, sccstate, sccstate_obstack);
/* For result types allow mismatch in completeness. */
if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
{
v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v);
v = iterative_hash_name
(TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (type))), v);
}
else
v = visit (TREE_TYPE (type), state, v,
sccstack, sccstate, sccstate_obstack);
for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p))
{
v = visit (TREE_VALUE (p), state, v,
sccstack, sccstate, sccstate_obstack);
/* For argument types allow mismatch in completeness. */
if (RECORD_OR_UNION_TYPE_P (TREE_VALUE (p)))
{
v = iterative_hash_hashval_t (TREE_CODE (TREE_VALUE (p)), v);
v = iterative_hash_name
(TYPE_NAME (TYPE_MAIN_VARIANT (TREE_VALUE (p))), v);
}
else
v = visit (TREE_VALUE (p), state, v,
sccstack, sccstate, sccstate_obstack);
na++;
}

View File

@ -1,3 +1,9 @@
2010-07-10 Richard Guenther <rguenther@suse.de>
PR lto/44889
* gcc.dg/lto/20100709-1_0.c: New testcase.
* gcc.dg/lto/20100709-1_1.c: Likewise.
2010-07-10 Richard Sandiford <r.sandiford@uk.ibm.com>
* gcc.dg/attr-weak-hidden-1.c, gcc.dg/attr-weak-hidden-1a.c: New test.

View File

@ -0,0 +1,7 @@
/* { dg-lto-do link } */
struct X;
struct Y {
struct X (*fnptr)(struct X);
};
struct Y foo;

View File

@ -0,0 +1,11 @@
struct X { int i; };
struct Y {
struct X (*fnptr)(struct X);
};
extern struct Y foo;
int main()
{
struct X x;
foo.fnptr(x);
return 0;
}