This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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)
+ {
+ }
+ 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]