diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 68662b030..361f47fd3 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -53,6 +53,8 @@ static __attribute__ ((used)) const char rcsid[] = #include "type.h" #include "qc-parse.h" +typedef expr_t *(*operation_t) (int op, expr_t *e, expr_t *e1, expr_t *e2); + static expr_t * cf_cast_expr (type_t *type, expr_t *e) { @@ -824,25 +826,40 @@ do_op_compound (int op, expr_t *e, expr_t *e1, expr_t *e2) return error (e1, "invalid operand for compound"); } +static operation_t *do_op[ev_type_count]; static expr_t * do_op_invalid (int op, expr_t *e, expr_t *e1, expr_t *e2) { - dstring_t *t1 = dstring_newstr (); - dstring_t *t2 = dstring_newstr (); + type_t *t1 = get_type (e1); + type_t *t2 = get_type (e2); + if (is_scalar (t1) && is_scalar (t2)) { + // one or both expressions are an enum, and the other is one of + // int, float or short. Treat the enum as the other type, or as + // the default type if both are enum. + etype_t t; + if (!is_enum (t1)) + t = t1->type; + else if (!is_enum (t2)) + t = t2->type; + else + t = type_default->type; + return do_op[t][t] (op, e, e1, e2); + } else { + dstring_t *enc1 = dstring_newstr (); + dstring_t *enc2 = dstring_newstr (); - print_type_str (t1, get_type (e1)); - print_type_str (t2, get_type (e2)); + print_type_str (enc1, t1); + print_type_str (enc2, t2); - //print_expr (e); - e1 = error (e1, "invalid operands for binary %s: %s %s", - get_op_string (op), t1->str, t2->str); - dstring_delete (t1); - dstring_delete (t2); - return e1; + //print_expr (e); + e1 = error (e1, "invalid operands for binary %s: %s %s", + get_op_string (op), enc1->str, enc2->str); + dstring_delete (enc1); + dstring_delete (enc2); + return e1; + } } -typedef expr_t *(*operation_t) (int op, expr_t *e, expr_t *e1, expr_t *e2); - static operation_t op_void[ev_type_count] = { do_op_invalid, // ev_void do_op_invalid, // ev_string @@ -1099,6 +1116,6 @@ fold_constants (expr_t *e) if (t1 < 0 || t1 >= ev_type_count || t2 < 0 || t2 >= ev_type_count || !do_op[t1] || !do_op[t1][t2]) - internal_error (e, 0); + internal_error (e, "invalid type"); return do_op[t1][t2] (op, e, e1, e2); }