Force left-to-right evaluation of binary operations etc.
authorPer Bothner <bothner@gcc.gnu.org>
Fri, 19 Feb 1999 16:33:18 +0000 (08:33 -0800)
committerPer Bothner <bothner@gcc.gnu.org>
Fri, 19 Feb 1999 16:33:18 +0000 (08:33 -0800)
Force left-to-right evaluation of binary operations etc.
* expr.c (force_evaluation_order), java-tree.h:  New function.
* parse.y (java_complete_lhs):  Pass binary operations, procedure
calls, and ARRAY_REFs to force_evaluation_order.
(various):  Set TREE_SIDE_EFFECTS more carefully.
Tolerate random (non-UTF8) encoding in comments without complaining.
* lex.c (java_read_char):  Return 0xFFFE if bad UTF8 encoding.
(java_is_eol):  Handle '\r' followed by '\n' instead of vice versa.
* parse.y (resolve_qualified_expression_name):  Handle error_mark.
(java_complete_node case EXPR_WITH_FILE_LOCATION):  Likewise.
* parse.y (java_complete_lhs):  Ignore an empty statement in a
COMPOUND_EXPR.  Don't complain about empty statement after return.

From-SVN: r25326

gcc/java/expr.c

index aeded3a..0848806 100644 (file)
@@ -29,6 +29,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #include "tree.h"
 #include "real.h"
 #include "rtl.h"
+#include "flags.h"
 #include "expr.h"
 #include "java-tree.h"
 #include "javaop.h"
@@ -2470,3 +2471,49 @@ process_jvm_instruction (PC, byte_ops, length)
   }
   return PC;
 }
+
+/* Force the (direct) sub-operands of NODE to be evaluated in left-to-right
+   order, as specified by Java Language Specification.
+
+   The problem is that while expand_expr will evaluate its sub-operands in
+   left-to-right order, for variables it will just return an rtx (i.e.
+   an lvalue) for the variable (rather than an rvalue).  So it is possible
+   that a later sub-operand will change the register, and when the
+   actual operation is done, it will use the new value, when it should
+   have used the original value.
+
+   We fix this by using save_expr.  This forces the sub-operand to be
+   copied into a fresh virtual register,
+*/
+
+tree
+force_evaluation_order (node)
+     tree  node;
+{
+  if (flag_syntax_only)
+    return node;
+  if (TREE_CODE_CLASS (TREE_CODE (node)) == '2'
+      && TREE_CODE (node) == ARRAY_REF)
+    {
+      if (TREE_SIDE_EFFECTS (TREE_OPERAND (node, 1)))
+       TREE_OPERAND (node, 0) = save_expr (TREE_OPERAND (node, 0));
+    }
+  else if (TREE_CODE (node) == CALL_EXPR || TREE_CODE (node) == NEW_CLASS_EXPR)
+    {
+      tree last_side_effecting_arg = NULL_TREE;
+      tree arg = TREE_OPERAND (node, 1);
+      for (; arg != NULL_TREE; arg = TREE_CHAIN (arg))
+       {
+         if (TREE_SIDE_EFFECTS (TREE_VALUE (arg)))
+           last_side_effecting_arg = arg;
+       }
+      arg = TREE_OPERAND (node, 1);
+      for (; arg != NULL_TREE;  arg = TREE_CHAIN (arg))
+       {
+         if (arg == last_side_effecting_arg)
+           break;
+         TREE_VALUE (arg) = save_expr (TREE_VALUE (arg)); 
+       }
+    }
+  return node;
+}