From 848994323e6d929029a96b7872cf6d582e6a658a Mon Sep 17 00:00:00 2001
From: Bill Currie <bill@taniwha.org>
Date: Thu, 3 Mar 2011 10:36:43 +0900
Subject: [PATCH] Support enums in expressions that support scalar types.

---
 tools/qfcc/source/constfold.c | 43 ++++++++++++++++++++++++-----------
 1 file changed, 30 insertions(+), 13 deletions(-)

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