This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR45667
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 20 Oct 2010 15:27:27 +0200 (CEST)
- Subject: [PATCH] Fix PR45667
This fixes PR45667, we can end up with non-type correct ADDR_EXPRs
in the LTO gimple IL when we merge function or variable decls with
incompatible types. For memory accesses we transparently keep the
IL type correct by wrapping them in MEM_REFs (keeping the original
type available and turning ODR violations into effective
VIEW_CONVERT_EXPRs). For addresses we do not have an easy way
to do that. On the other hand since MEM_REF we do not require
type-correct ADDR_EXPRs neither for correctness nor to avoid
missed optimizations. So the following disables the ADDR_EXPR
type checking when inside LTO but keeps it otherwise as we really
want frontends and optimization passes to behave sane. Sounds like
a hack, but really is the best way to deal with the issue, also in
the context how the verifier is written (given it doesn't want to
create new types).
Bootstrap and regtest running on x86_64-unknown-linux-gnu, I'll commit
this after it finished.
Richard.
2010-10-20 Richard Guenther <rguenther@suse.de>
PR lto/45667
* lto-streamer-out.c (output_gimple_stmt): Fix typo.
* tree-cfg.c (verify_gimple_call): Properly get the call fndecl.
(verify_gimple_assign_single): Disable ADDR_EXPR type check
when in LTO.
* g++.dg/lto/20101020-1_0.h: New testcase.
* g++.dg/lto/20101020-1_0.C: Likewise.
* g++.dg/lto/20101020-1_1.C: Likewise.
Index: gcc/lto-streamer-out.c
===================================================================
*** gcc/lto-streamer-out.c (revision 165718)
--- gcc/lto-streamer-out.c (working copy)
*************** output_gimple_stmt (struct output_block
*** 1763,1769 ****
if (op)
{
tree *basep = &op;
! if (handled_component_p (*basep))
basep = &TREE_OPERAND (*basep, 0);
if (TREE_CODE (*basep) == VAR_DECL
&& !auto_var_in_fn_p (*basep, current_function_decl))
--- 1763,1769 ----
if (op)
{
tree *basep = &op;
! while (handled_component_p (*basep))
basep = &TREE_OPERAND (*basep, 0);
if (TREE_CODE (*basep) == VAR_DECL
&& !auto_var_in_fn_p (*basep, current_function_decl))
Index: gcc/tree-cfg.c
===================================================================
*** gcc/tree-cfg.c (revision 165718)
--- gcc/tree-cfg.c (working copy)
*************** verify_gimple_call (gimple stmt)
*** 3107,3114 ****
call, and the decl should have DECL_STATIC_CHAIN set. */
if (gimple_call_chain (stmt))
{
! if (TREE_CODE (fn) != ADDR_EXPR
! || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL)
{
error ("static chain in indirect gimple call");
return true;
--- 3180,3186 ----
call, and the decl should have DECL_STATIC_CHAIN set. */
if (gimple_call_chain (stmt))
{
! if (!gimple_call_fndecl (stmt))
{
error ("static chain in indirect gimple call");
return true;
*************** verify_gimple_assign_single (gimple stmt
*** 3698,3704 ****
return true;
}
! if (!types_compatible_p (TREE_TYPE (op), TREE_TYPE (TREE_TYPE (rhs1)))
&& !one_pointer_to_useless_type_conversion_p (TREE_TYPE (rhs1),
TREE_TYPE (op)))
{
--- 3799,3811 ----
return true;
}
! /* Technically there is no longer a need for matching types, but
! gimple hygiene asks for this check. In LTO we can end up
! combining incompatible units and thus end up with addresses
! of globals that change their type to a common one. */
! if (!in_lto_p
! && !types_compatible_p (TREE_TYPE (op),
! TREE_TYPE (TREE_TYPE (rhs1)))
&& !one_pointer_to_useless_type_conversion_p (TREE_TYPE (rhs1),
TREE_TYPE (op)))
{
Index: gcc/testsuite/g++.dg/lto/20101020-1_0.h
===================================================================
*** gcc/testsuite/g++.dg/lto/20101020-1_0.h (revision 0)
--- gcc/testsuite/g++.dg/lto/20101020-1_0.h (revision 0)
***************
*** 0 ****
--- 1,23 ----
+ struct A;
+ typedef void (A::*Am1) (void *);
+ typedef void (A::*Am2) ();
+
+ struct B
+ {
+ Am2 am2;
+ };
+
+ struct A
+ {
+ A ();
+ struct B b;
+ struct C *c;
+ struct D *d;
+ void foo (Am1);
+ void bar (void *);
+ };
+
+ struct C
+ {
+ };
+
Index: gcc/testsuite/g++.dg/lto/20101020-1_0.C
===================================================================
*** gcc/testsuite/g++.dg/lto/20101020-1_0.C (revision 0)
--- gcc/testsuite/g++.dg/lto/20101020-1_0.C (revision 0)
***************
*** 0 ****
--- 1,8 ----
+ // { dg-lto-do link }
+
+ #include "20101020-1_0.h"
+ A::A ()
+ {
+ foo (&A::bar);
+ }
+ int main() { return 0; }
Index: gcc/testsuite/g++.dg/lto/20101020-1_1.C
===================================================================
*** gcc/testsuite/g++.dg/lto/20101020-1_1.C (revision 0)
--- gcc/testsuite/g++.dg/lto/20101020-1_1.C (revision 0)
***************
*** 0 ****
--- 1,11 ----
+ #include "20101020-1_0.h"
+ struct D
+ {
+ };
+ void A::bar (void *)
+ {
+ }
+ void A::foo (Am1)
+ {
+ }
+