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
This commit is contained in:
Per Bothner 1999-02-19 08:33:18 -08:00
parent c60ca7db2a
commit 7428556059

View 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;
}