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]

fix g++.dg/ext/vla1.C


The problem here is that we'd not copy enough things before mangling
them.  Which clobbers the trees of the function being inlined.  Fixing
just that broke some C vla test case, which required more hackery.

Ho hum.


r~


        * tree-inline.c (remap_type): New.
        (remap_decl): Use it.  Remap DECL_SIZE*.
        (copy_body_r): Use it.
        (walk_tree): Walk TREE_TYPE too.
        (copy_tree_r): Don't walk subtrees of types.
        * tree.c (variably_modified_type_p): Restructure.  Consider integer
        types with non-const bounds variably modified.

Index: tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.82
diff -c -p -d -r1.82 tree-inline.c
*** tree-inline.c	3 Oct 2003 00:23:29 -0000	1.82
--- tree-inline.c	5 Oct 2003 19:03:24 -0000
*************** static void expand_calls_inline (tree *,
*** 121,126 ****
--- 121,127 ----
  static bool inlinable_function_p (tree);
  static int limits_allow_inlining (tree, inline_data *);
  static tree remap_decl (tree, inline_data *);
+ static tree remap_type (tree, inline_data *);
  #ifndef INLINER_FOR_JAVA
  static tree initialize_inlined_parameters (inline_data *, tree, tree);
  static void remap_block (tree, tree, inline_data *);
*************** remap_decl (tree decl, inline_data *id)
*** 146,151 ****
--- 147,153 ----
  
    /* See if we have remapped this declaration.  */
    n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl);
+ 
    /* If we didn't already have an equivalent for this declaration,
       create one now.  */
    if (!n)
*************** remap_decl (tree decl, inline_data *id)
*** 153,181 ****
        tree t;
  
        /* Make a copy of the variable or label.  */
!       t = copy_decl_for_inlining (decl, fn,
! 				  VARRAY_TREE (id->fns, 0));
  
!       /* The decl T could be a dynamic array or other variable size type,
! 	 in which case some fields need to be remapped because they may
! 	 contain SAVE_EXPRs.  */
!       if (TREE_TYPE (t) && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE
! 	  && TYPE_DOMAIN (TREE_TYPE (t)))
! 	{
! 	  TREE_TYPE (t) = copy_node (TREE_TYPE (t));
! 	  TYPE_DOMAIN (TREE_TYPE (t))
! 	    = copy_node (TYPE_DOMAIN (TREE_TYPE (t)));
! 	  walk_tree (&TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (t))),
! 		     copy_body_r, id, NULL);
! 	}
  
  #ifndef INLINER_FOR_JAVA
        if (! DECL_NAME (t) && TREE_TYPE (t)
  	  && (*lang_hooks.tree_inlining.anon_aggr_type_p) (TREE_TYPE (t)))
  	{
  	  /* For a VAR_DECL of anonymous type, we must also copy the
! 	     member VAR_DECLS here and rechain the
! 	     DECL_ANON_UNION_ELEMS.  */
  	  tree members = NULL;
  	  tree src;
  
--- 155,180 ----
        tree t;
  
        /* Make a copy of the variable or label.  */
!       t = copy_decl_for_inlining (decl, fn, VARRAY_TREE (id->fns, 0));
  
!       /* Remap types, if necessary.  */
!       TREE_TYPE (t) = remap_type (TREE_TYPE (t), id);
!       if (TREE_CODE (t) == TYPE_DECL)
!         DECL_ORIGINAL_TYPE (t) = remap_type (DECL_ORIGINAL_TYPE (t), id);
!       else if (TREE_CODE (t) == PARM_DECL)
!         DECL_ARG_TYPE_AS_WRITTEN (t)
! 	  = remap_type (DECL_ARG_TYPE_AS_WRITTEN (t), id);
! 
!       /* Remap sizes as necessary.  */
!       walk_tree (&DECL_SIZE (t), copy_body_r, id, NULL);
!       walk_tree (&DECL_SIZE_UNIT (t), copy_body_r, id, NULL);
  
  #ifndef INLINER_FOR_JAVA
        if (! DECL_NAME (t) && TREE_TYPE (t)
  	  && (*lang_hooks.tree_inlining.anon_aggr_type_p) (TREE_TYPE (t)))
  	{
  	  /* For a VAR_DECL of anonymous type, we must also copy the
! 	     member VAR_DECLS here and rechain the DECL_ANON_UNION_ELEMS.  */
  	  tree members = NULL;
  	  tree src;
  
*************** remap_decl (tree decl, inline_data *id)
*** 202,207 ****
--- 201,311 ----
    return (tree) n->value;
  }
  
+ static tree
+ remap_type (tree type, inline_data *id)
+ {
+   splay_tree_node node;
+   tree new, t;
+ 
+   if (type == NULL)
+     return type;
+ 
+   /* See if we have remapped this type.  */
+   node = splay_tree_lookup (id->decl_map, (splay_tree_key) type);
+   if (node)
+     return (tree) node->value;
+ 
+   /* The type only needs remapping if it's variably modified.  */
+   if (! variably_modified_type_p (type))
+     {
+       splay_tree_insert (id->decl_map, (splay_tree_key) type,
+ 			 (splay_tree_value) type);
+       return type;
+     }
+   
+   /* We do need a copy.  build and register it now.  */
+   new = copy_node (type);
+   splay_tree_insert (id->decl_map, (splay_tree_key) type,
+ 		     (splay_tree_value) new);
+ 
+   /* This is a new type, not a copy of an old type.  Need to reassociate
+      variants.  We can handle everything except the main variant lazily.  */
+   t = TYPE_MAIN_VARIANT (type);
+   if (type != t)
+     {
+       t = remap_type (t, id);
+       TYPE_MAIN_VARIANT (new) = t;
+       TYPE_NEXT_VARIANT (new) = TYPE_MAIN_VARIANT (t);
+       TYPE_NEXT_VARIANT (t) = new;
+     }
+   else
+     {
+       TYPE_MAIN_VARIANT (new) = new;
+       TYPE_NEXT_VARIANT (new) = NULL;
+     }
+ 
+   /* Lazily create pointer and reference types.  */
+   TYPE_POINTER_TO (new) = NULL;
+   TYPE_REFERENCE_TO (new) = NULL;
+ 
+   switch (TREE_CODE (new))
+     {
+     case INTEGER_TYPE:
+     case REAL_TYPE:
+     case ENUMERAL_TYPE:
+     case BOOLEAN_TYPE:
+     case CHAR_TYPE:
+       t = TYPE_MIN_VALUE (new);
+       if (t && TREE_CODE (t) != INTEGER_CST)
+         walk_tree (&TYPE_MIN_VALUE (new), copy_body_r, id, NULL);
+       t = TYPE_MAX_VALUE (new);
+       if (t && TREE_CODE (t) != INTEGER_CST)
+         walk_tree (&TYPE_MAX_VALUE (new), copy_body_r, id, NULL);
+       return new;
+     
+     case POINTER_TYPE:
+       TREE_TYPE (new) = t = remap_type (TREE_TYPE (new), id);
+       if (TYPE_MODE (new) == ptr_mode)
+         TYPE_POINTER_TO (t) = new;
+       return new;
+ 
+     case REFERENCE_TYPE:
+       TREE_TYPE (new) = t = remap_type (TREE_TYPE (new), id);
+       if (TYPE_MODE (new) == ptr_mode)
+         TYPE_REFERENCE_TO (t) = new;
+       return new;
+ 
+     case METHOD_TYPE:
+     case FUNCTION_TYPE:
+       TREE_TYPE (new) = remap_type (TREE_TYPE (new), id);
+       walk_tree (&TYPE_ARG_TYPES (new), copy_body_r, id, NULL);
+       return new;
+ 
+     case ARRAY_TYPE:
+       TREE_TYPE (new) = remap_type (TREE_TYPE (new), id);
+       TYPE_DOMAIN (new) = remap_type (TYPE_DOMAIN (new), id);
+       break;
+ 
+     case RECORD_TYPE:
+     case UNION_TYPE:
+     case QUAL_UNION_TYPE:
+       walk_tree (&TYPE_FIELDS (new), copy_body_r, id, NULL);
+       break;
+ 
+     case FILE_TYPE:
+     case SET_TYPE:
+     case OFFSET_TYPE:
+     default:
+       /* Shouldn't have been thought variable sized.  */
+       abort ();
+     }
+ 
+   walk_tree (&TYPE_SIZE (new), copy_body_r, id, NULL);
+   walk_tree (&TYPE_SIZE_UNIT (new), copy_body_r, id, NULL);
+ 
+   return new;
+ }
+ 
  #ifndef INLINER_FOR_JAVA
  /* Copy the SCOPE_STMT_BLOCK associated with SCOPE_STMT to contain
     remapped versions of the variables therein.  And hook the new block
*************** copy_body_r (tree *tp, int *walk_subtree
*** 525,530 ****
--- 629,638 ----
        TREE_OPERAND (*tp, 0) = (tree) n->value;
      }
  #endif /* INLINER_FOR_JAVA */
+   /* Types may need remapping as well.  */
+   else if (TYPE_P (*tp))
+     *tp = remap_type (*tp, id);
+ 
    /* Otherwise, just copy the node.  Note that copy_tree_r already
       knows not to copy VAR_DECLs, etc., so this is safe.  */
    else
*************** copy_body_r (tree *tp, int *walk_subtree
*** 576,581 ****
--- 684,691 ----
  
        copy_tree_r (tp, walk_subtrees, NULL);
  
+       TREE_TYPE (*tp) = remap_type (TREE_TYPE (*tp), id);
+ 
        /* The copied TARGET_EXPR has never been expanded, even if the
  	 original node was expanded already.  */
        if (TREE_CODE (*tp) == TARGET_EXPR && TREE_OPERAND (*tp, 3))
*************** walk_tree (tree *tp, walk_tree_fn func, 
*** 1787,1792 ****
--- 1897,1903 ----
  	      WALK_SUBTREE (DECL_INITIAL (DECL_STMT_DECL (*tp)));
  	      WALK_SUBTREE (DECL_SIZE (DECL_STMT_DECL (*tp)));
  	      WALK_SUBTREE (DECL_SIZE_UNIT (DECL_STMT_DECL (*tp)));
+ 	      WALK_SUBTREE (TREE_TYPE (*tp));
  	    }
  
  	  /* This can be tail-recursion optimized if we write it this way.  */
*************** copy_tree_r (tree *tp, int *walk_subtree
*** 1968,1975 ****
  	TREE_CHAIN (*tp) = chain;
  #endif /* INLINER_FOR_JAVA */
      }
!   else if (TREE_CODE_CLASS (code) == 't' && !variably_modified_type_p (*tp))
!     /* Types only need to be copied if they are variably modified.  */
      *walk_subtrees = 0;
  
    return NULL_TREE;
--- 2079,2085 ----
  	TREE_CHAIN (*tp) = chain;
  #endif /* INLINER_FOR_JAVA */
      }
!   else if (TREE_CODE_CLASS (code) == 't')
      *walk_subtrees = 0;
  
    return NULL_TREE;
Index: tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.331
diff -c -p -d -r1.331 tree.c
*** tree.c	3 Oct 2003 21:33:52 -0000	1.331
--- tree.c	5 Oct 2003 19:03:25 -0000
*************** int_fits_type_p (tree c, tree type)
*** 4273,4278 ****
--- 4273,4280 ----
  bool
  variably_modified_type_p (tree type)
  {
+   tree t;
+ 
    if (type == error_mark_node)
      return false;
  
*************** variably_modified_type_p (tree type)
*** 4281,4319 ****
       We do not yet have a representation of the C99 '[*]' syntax.
       When a representation is chosen, this function should be modified
       to test for that case as well.  */
!   if (TYPE_SIZE (type)
!       && TYPE_SIZE (type) != error_mark_node
!       && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
      return true;
  
!   /* If TYPE is a pointer or reference, it is variably modified if
!      the type pointed to is variably modified.  */
!   if ((TREE_CODE (type) == POINTER_TYPE
!        || TREE_CODE (type) == REFERENCE_TYPE)
!       && variably_modified_type_p (TREE_TYPE (type)))
!     return true;
  
!   /* If TYPE is an array, it is variably modified if the array
!      elements are.  (Note that the VLA case has already been checked
!      above.)  */
!   if (TREE_CODE (type) == ARRAY_TYPE
!       && variably_modified_type_p (TREE_TYPE (type)))
!     return true;
  
!   /* If TYPE is a function type, it is variably modified if any of the
!      parameters or the return type are variably modified.  */
!   if (TREE_CODE (type) == FUNCTION_TYPE
!       || TREE_CODE (type) == METHOD_TYPE)
!     {
!       tree parm;
  
!       if (variably_modified_type_p (TREE_TYPE (type)))
  	return true;
!       for (parm = TYPE_ARG_TYPES (type);
! 	   parm && parm != void_list_node;
! 	   parm = TREE_CHAIN (parm))
! 	if (variably_modified_type_p (TREE_VALUE (parm)))
! 	  return true;
      }
  
    /* The current language may have other cases to check, but in general,
--- 4283,4332 ----
       We do not yet have a representation of the C99 '[*]' syntax.
       When a representation is chosen, this function should be modified
       to test for that case as well.  */
!   t = TYPE_SIZE (type);
!   if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
      return true;
  
!   switch (TREE_CODE (type))
!     {
!     case POINTER_TYPE:
!     case REFERENCE_TYPE:
!     case ARRAY_TYPE:
!       /* If TYPE is a pointer or reference, it is variably modified if
! 	 the type pointed to is variably modified.  Similarly for arrays;
! 	 note that VLAs are handled by the TYPE_SIZE check above.  */
!       return variably_modified_type_p (TREE_TYPE (type));
  
!     case FUNCTION_TYPE:
!     case METHOD_TYPE:
!       /* If TYPE is a function type, it is variably modified if any of the
!          parameters or the return type are variably modified.  */
!       {
! 	tree parm;
  
! 	if (variably_modified_type_p (TREE_TYPE (type)))
! 	  return true;
! 	for (parm = TYPE_ARG_TYPES (type);
! 	     parm && parm != void_list_node;
! 	     parm = TREE_CHAIN (parm))
! 	  if (variably_modified_type_p (TREE_VALUE (parm)))
! 	    return true;
!       }
!       break;
  
!     case INTEGER_TYPE:
!       /* Scalar types are variably modified if their end points
! 	 aren't constant.  */
!       t = TYPE_MIN_VALUE (type);
!       if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
  	return true;
!       t = TYPE_MAX_VALUE (type);
!       if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
! 	return true;
!       return false;
! 
!     default:
!       break;
      }
  
    /* The current language may have other cases to check, but in general,


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