depending on the constancy of the operands.
*/
-#define commutative_binop(expp, oper, expr) mk_binop(expp, oper, expr, 1)
+/*
+ * Although the relational operators are generally not commutative, we can
+ * switch the arguments if the operator is adapted (e.g. < becomes >)
+ */
#define non_commutative_binop(expp, oper, expr) mk_binop(expp, oper, expr, 0)
+#define commutative_binop(expp, oper, expr) mk_binop(expp, oper, expr, 1)
+#define non_commutative_relop(expp, oper, expr) mk_binop(expp, oper, expr, 1)
ch3bin(expp, oper, expr)
register struct expr **expp;
case EQUAL:
case NOTEQUAL:
relbalance(expp, oper, &expr);
- non_commutative_binop(expp, oper, expr);
+ non_commutative_relop(expp, oper, expr);
(*expp)->ex_type = int_type;
break;
if (int_size != pointer_size) (*expp)->ex_flags |= EX_PTRDIFF;
}
+/*
+ * The function arg_switched() returns the operator that should be used
+ * when the arguments are switched. This is special for some relational
+ * operators.
+ */
+int
+arg_switched(oper)
+{
+ switch (oper) {
+ case '<': return '>';
+ case '>': return '<';
+ case LESSEQ: return GREATEREQ;
+ case GREATEREQ: return LESSEQ;
+ default: return oper;
+ }
+}
+
mk_binop(expp, oper, expr, commutative)
struct expr **expp;
register struct expr *expr;
cstbin(expp, oper, expr);
else if (is_fp_cst(expr) && is_fp_cst(ex))
fltcstbin(expp, oper, expr);
- else {
- *expp = (commutative &&
- ! (ex->ex_flags & EX_VOLATILE) &&
- ( expr->ex_depth > ex->ex_depth ||
- (expr->ex_flags & EX_SIDEEFFECTS) ||
- is_cp_cst(ex)))
- ? new_oper(ex->ex_type, expr, oper, ex)
- : new_oper(ex->ex_type, ex, oper, expr);
+ else {
+ *expp = (commutative
+ && !(ex->ex_flags & EX_VOLATILE)
+ && ( expr->ex_depth > ex->ex_depth
+ || is_cp_cst(ex)))
+ ? new_oper(ex->ex_type, expr, arg_switched(oper), ex)
+ : new_oper(ex->ex_type, ex, oper, expr);
}
}
DfaEndFunction();
#endif DATAFLOW
C_df_ilb(return2_label);
- if (return_expr_occurred) C_asp(-func_size);
+ if (return_expr_occurred && func_res_label == 0) {
+ C_asp(-func_size);
+ }
C_df_ilb(return_label);
prc_exit();
#ifndef LINT
if (return_expr_occurred) {
if (func_res_label != 0) {
- C_lae_dlb(func_res_label, (arith)0);
- store_block(func_size, func_type->tp_align);
C_lae_dlb(func_res_label, (arith)0);
C_ret(pointer_size);
}
*/
ch3cast(&expr, RETURN, func_type);
code_expr(expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
+ if (func_res_label != 0) {
+ C_lae_dlb(func_res_label, (arith)0);
+ store_block(func_size, func_type->tp_align);
+ }
C_bra(return_label);
return_expr_occurred = 1;
}
short typedef yepp;
makes all hope of writing a specific grammar for typedefs illusory.
*/
-/* Accept a single declaration specifier. Then accept zero or more
- type-specifiers. There can be a conflict on both TYPE_IDENTIFIER
- and IDENTIFIER.
+/* Accept a single declaration specifier. Then accept zero or more
+ declaration specifiers. There can be a conflict on both
+ TYPE_IDENTIFIER and IDENTIFIER.
The following rule is used:
- When we see a TYPE_IDENTIFIER, we accept it if no type-specifier
- was given, and it is not directly followed by an identifier.
- If no type-dpecifier was given, it is taken as the identifier being
+ When we see a TYPE_IDENTIFIER, we accept it if no type-specifier was
+ given, and it is not directly followed by an identifier. If a
+ type-specifier was given, it is taken as the identifier being
declared. If it is followed by an identifier, we assume that an
error has been made, (e.g. unsigned typedeffed_int x;) and that
this will be detected later on.