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 to function pointer attribute handling


Forcing memory variables to be copied into regs before use on the tree-ssa
branch broke gcc.dg/sibcall-5.c because we used 

  build_type_variant (type, 0, 0)

to generate the (function pointer) type of the temporary, which stripped
the regparm attribute from the pointed-to type.  This is wrong;

  int (*)(int, int)

and

  int (*)(int, int) __attribute__ ((regparm (2)))

should not have the same TYPE_MAIN_VALUE, any more than "int *" and "const
int *" do.  Fixed by the decl_attributes change below.

The get_qualified_type change was my first attempt to fix this failure; it
isn't necessary, but also seems correct.  Changing the cv-quals of a type
should not also change the attributes.

Tested athlon-pc-linux-gnu, applied to tree-ssa.  Currently testing on the
trunk.

2003-08-19  Jason Merrill  <jason@redhat.com>

	* attribs.c (decl_attributes): Rebuild the function pointer type after
	changing the target type.
	* tree.c (get_qualified_type): Also check that the attributes match.

*** ./tree.c.~1~	Tue Aug 19 14:38:35 2003
--- ./tree.c	Tue Aug 19 17:07:43 2003
*************** get_qualified_type (tree type, int type_
*** 2846,2852 ****
       preserve the TYPE_NAME, since there is code that depends on this.  */
    for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
      if (TYPE_QUALS (t) == type_quals && TYPE_NAME (t) == TYPE_NAME (type)
!         && TYPE_CONTEXT (t) == TYPE_CONTEXT (type))
        return t;
  
    return NULL_TREE;
--- 2846,2853 ----
       preserve the TYPE_NAME, since there is code that depends on this.  */
    for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
      if (TYPE_QUALS (t) == type_quals && TYPE_NAME (t) == TYPE_NAME (type)
!         && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
! 	&& attribute_list_equal (TYPE_ATTRIBUTES (t), TYPE_ATTRIBUTES (type)))
        return t;
  
    return NULL_TREE;
*** ./attribs.c.~1~	Tue Aug 19 14:38:34 2003
--- ./attribs.c	Tue Aug 19 17:07:44 2003
*************** decl_attributes (tree *node, tree attrib
*** 162,167 ****
--- 162,168 ----
        tree *anode = node;
        const struct attribute_spec *spec = NULL;
        bool no_add_attrs = 0;
+       tree fn_ptr_tmp = NULL_TREE;
        size_t i;
  
        for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
*************** decl_attributes (tree *node, tree attrib
*** 230,238 ****
  	      && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE
  		  || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE))
  	    {
! 	      if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
! 		*anode = build_type_copy (*anode);
! 	      anode = &TREE_TYPE (*anode);
  	    }
  	  else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
  	    {
--- 231,248 ----
  	      && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE
  		  || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE))
  	    {
! 	      /* OK, this is a bit convoluted.  We can't just make a copy
! 		 of the pointer type and modify its TREE_TYPE, because if
! 		 we change the attributes of the target type the pointer
! 		 type needs to have a different TYPE_MAIN_VARIANT.  So we
! 		 pull out the target type now, frob it as appropriate, and
! 		 rebuild the pointer type later.
! 
! 	         This would all be simpler if attributes were part of the
! 	         declarator, grumble grumble.  */
! 	      fn_ptr_tmp = TREE_TYPE (*anode);
! 	      anode = &fn_ptr_tmp;
! 	      flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
  	    }
  	  else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
  	    {
*************** decl_attributes (tree *node, tree attrib
*** 299,304 ****
--- 309,327 ----
  								  old_attrs));
  	    }
  	}
+ 
+       if (fn_ptr_tmp)
+ 	{
+ 	  /* Rebuild the function pointer type and put it in the
+ 	     appropriate place.  */
+ 	  fn_ptr_tmp = build_pointer_type (fn_ptr_tmp);
+ 	  if (DECL_P (*node))
+ 	    TREE_TYPE (*node) = fn_ptr_tmp;
+ 	  else if (TREE_CODE (*node) == POINTER_TYPE)
+ 	    *node = fn_ptr_tmp;
+ 	  else
+ 	    abort ();
+ 	}
      }
  
    return returned_attrs;

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