[gnu.gcc.bug] A fix to fold "foo"[2] into a constant

juha@tds.kth.se (Juha Sarlin) (06/16/89)

gcc 1.35 gives an error message: "case label does not reduce to an
integer constant" for the following code:

#define	CTRL(c)	(#c[0]&037)

foo(c)
{
  switch (c)
    {
    case CTRL(z):
      break;
    }
}

Below is my fix. Note that I didn't bother to handle similar cases,
like *"foo" for example.

*** /tmp/,RCSt1a00595	Thu Jun 16 14:03:59 1989
--- fold-const.c	Wed Jun 15 18:40:33 1989
***************
*** 981,986 ****
--- 981,1001 ----
  #endif
  	}
  #endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
+       else if (TREE_CODE (arg1) == ARRAY_REF)
+ 	{
+ 	  tree array = TREE_OPERAND (arg1, 0);
+ 	  tree index = TREE_OPERAND (arg1, 1);
+ 	  int i;
+ 
+ 	  /* Fold an expression like: "foo"[2] */
+ 	  if (TREE_CODE (array) == STRING_CST
+ 	      && TREE_CODE (index) == INTEGER_CST
+ 	      && !TREE_INT_CST_HIGH (index)
+ 	      && (i = TREE_INT_CST_LOW (index)) < TREE_STRING_LENGTH (array))
+ 	    t = build_int_2 (TREE_STRING_POINTER (array)[i], 0);
+ 	  else	/* Cannot fold this ARRAY_REF; return original expression */
+ 	    return t;
+ 	}
        TREE_TYPE (t) = type;
      }
    else if (TREE_CODE (type) == REAL_TYPE)
***************
*** 1090,1095 ****
--- 1105,1113 ----
  #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
  	      && TREE_CODE (TREE_OPERAND (t, i)) != REAL_CST
  #endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
+ 	      && !(TREE_CODE (TREE_OPERAND (t, i)) == ARRAY_REF
+ 		   && TREE_LITERAL (TREE_OPERAND (TREE_OPERAND (t, i), 0))
+ 		   && TREE_LITERAL (TREE_OPERAND (TREE_OPERAND (t, i), 1)))
  	      )
  	    /* Note that TREE_LITERAL isn't enough:
  	       static var addresses are constant but we can't

--
Juha Sarlin	juha@tds.kth.se