summaryrefslogtreecommitdiff
path: root/gcc/java/expr.c
diff options
context:
space:
mode:
authorPer Bothner <bothner@gcc.gnu.org>1999-02-19 08:33:18 -0800
committerPer Bothner <bothner@gcc.gnu.org>1999-02-19 08:33:18 -0800
commit742855605950c43419bed950f7f0866cfbbc1c5d (patch)
treef91030069f52afee0467bda834f76d3f91ecf256 /gcc/java/expr.c
parentc60ca7db2a2b90250208144231af8928acaf8adb (diff)
downloadgcc-742855605950c43419bed950f7f0866cfbbc1c5d.tar.gz
Force left-to-right evaluation of binary operations etc.
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
Diffstat (limited to 'gcc/java/expr.c')
-rw-r--r--gcc/java/expr.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/gcc/java/expr.c b/gcc/java/expr.c
index aeded3a4181..0848806ac5b 100644
--- a/gcc/java/expr.c
+++ b/gcc/java/expr.c
@@ -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;
+}