[3.4 PATCH] PR 17078: Problems in expand_unreachable_stmt

Roger Sayle roger@eyesopen.com
Tue Aug 24 02:39:00 GMT 2004


I was considering committing this patch directly, but on second
thoughts (i) the changes are technically to the C front-end not
the middle-end, (ii) the patch is against the gcc-3_4-branch and
(iii) how this fixes the problem might no be immediately obvious.

PR rtl-optimization/17078 is a wrong-code bug on the gcc 3.4
branch introduced by Geoff Keating's patch to limit the recursion
depth of expand_unreachable_stmt to avoid problems with Darwin's
limited stack size.

http://gcc.gnu.org/ml/gcc-patches/2003-04/msg02176.html

Prior to this patch expand_unreachable_stmt used to return a bool,
indicating whether control reached the end of the given statement
list.  After, the return value was converted to a "tree" with the
intention that the value NULL_TREE corresponds to false, and any
non-NULL value was equivalent to true.

As an example of the problem, consider the following hunk:

>  	case IF_STMT:
> 	  if (expand_unreachable_if_stmt (t))
> -	    {
> -	      expand_stmt (TREE_CHAIN (t));
> -	      return true;
> -	    }
> +	    return TREE_CHAIN (t);
> 	  break;

Previously, this always returned "true", but after the change we
now return "TREE_CHAIN (t)", which unfortunately may be NULL_TREE,
and in the example attached to the PR, it is.


The solution is to ensure that we always return a non-NULL pointer
wherever we originally returned true.  The cleverness is that the
actual return value is only ever passed to expand_stmt, which as
luck would have it does nothing if its argument is either NULL_TREE
or error_mark_node.  Hence we can return the value error_mark_node
to indicate that control can reach the end of the statement list,
but there are no remaining statements to be expanded.


The following has been tested on i686-pc-linux-gnu against the
gcc-3_4-branch with a full "make bootstrap", all default languages,
and regression tested with a top-level "make -k check" with no new
failures.  The new testcase passes with the patch but fails without.
None of the affected code is still present on mainline, but if
approved, I'll commit the test case there as well.  I've confirmed
that on mainline it passes as expected.

Ok for the gcc 3.4 branch?


2004-08-23  Roger Sayle  <roger@eyesopen.com>

	PR rtl-optimization/17078
	* c-semantics.c (expand_unreachable_if_stmt): If the end of the
	specified statement list is reachable, always return a non-NULL
	pointer.  If necessary, return error_mark_node.

	* gcc.c-torture/execute/pr17078-1.c: New test case.


Index: c-semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-semantics.c,v
retrieving revision 1.74.4.2
diff -c -3 -p -r1.74.4.2 c-semantics.c
*** c-semantics.c	23 Jan 2004 23:35:53 -0000	1.74.4.2
--- c-semantics.c	23 Aug 2004 21:47:05 -0000
*************** expand_unreachable_if_stmt (tree t)
*** 969,975 ****
  /* Expand an unreachable statement list.  This function skips all
     statements preceding the first potentially reachable label and
     then returns the label (or, in same cases, the statement after
!    one containing the label).  */
  static tree
  expand_unreachable_stmt (tree t, int warn)
  {
--- 969,977 ----
  /* Expand an unreachable statement list.  This function skips all
     statements preceding the first potentially reachable label and
     then returns the label (or, in same cases, the statement after
!    one containing the label).  This function returns NULL_TREE if
!    the end of the given statement list is unreachable, and a
!    non-NULL value, possibly error_mark_node, otherwise.  */
  static tree
  expand_unreachable_stmt (tree t, int warn)
  {
*************** expand_unreachable_stmt (tree t, int war
*** 1019,1025 ****

  	case IF_STMT:
  	  if (expand_unreachable_if_stmt (t))
! 	    return TREE_CHAIN (t);
  	  break;

  	case WHILE_STMT:
--- 1021,1027 ----

  	case IF_STMT:
  	  if (expand_unreachable_if_stmt (t))
! 	    return TREE_CHAIN (t) ? TREE_CHAIN (t) : error_mark_node;
  	  break;

  	case WHILE_STMT:
*************** expand_unreachable_stmt (tree t, int war
*** 1027,1033 ****
  	     no need to rotate the loop, instead the WHILE_STMT can be
  	     expanded like a DO_STMT.  */
  	  genrtl_do_stmt_1 (WHILE_COND (t), WHILE_BODY (t));
! 	  return TREE_CHAIN (t);

  	case COMPOUND_STMT:
  	  {
--- 1029,1035 ----
  	     no need to rotate the loop, instead the WHILE_STMT can be
  	     expanded like a DO_STMT.  */
  	  genrtl_do_stmt_1 (WHILE_COND (t), WHILE_BODY (t));
! 	  return TREE_CHAIN (t) ? TREE_CHAIN (t) : error_mark_node;

  	case COMPOUND_STMT:
  	  {
*************** expand_unreachable_stmt (tree t, int war
*** 1036,1042 ****
  	    if (n != NULL_TREE)
  	      {
  		expand_stmt (n);
! 		return TREE_CHAIN (t);
  	      }
  	    warn = false;
  	    break;
--- 1038,1044 ----
  	    if (n != NULL_TREE)
  	      {
  		expand_stmt (n);
! 		return TREE_CHAIN (t) ? TREE_CHAIN (t) : error_mark_node;
  	      }
  	    warn = false;
  	    break;



extern void abort(void);

void test(int *ptr)
{
  int i = 1;
  goto useless;
  if (0)
    {
      useless:
      i = 0;
    }
  else
    i = 1;
  *ptr = i;
}

int main()
{
  int i = 1;
  test(&i);
  if (i)
    abort ();
  return 0;
}



Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833



More information about the Gcc-patches mailing list