[PATCH wayland] make wl_fixed_t a safe type

Pekka Paalanen ppaalanen at gmail.com
Mon Jun 4 07:48:16 PDT 2012


Turn wl_fixed_t into a struct type, so that it will no longer implicitly
cast into any other type.

Silent implicit casts between wl_fixed_t and all integer types have
hidden many bugs, that the compiler could have easily cought.

Signed-off-by: Pekka Paalanen <ppaalanen at gmail.com>
---
 src/connection.c        |    7 ++++---
 src/wayland-util.h      |   39 +++++++++++++++++++++++++++++++--------
 tests/connection-test.c |   19 ++++++++++---------
 tests/fixed-benchmark.c |   14 +++++++-------
 tests/fixed-test.c      |   42 +++++++++++++++++++++---------------------
 5 files changed, 73 insertions(+), 48 deletions(-)

diff --git a/src/connection.c b/src/connection.c
index 5b7965e..dce22d4 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -434,7 +434,7 @@ wl_closure_vmarshal(struct wl_closure *closure,
 			closure->args[i] = p;
 			if (end - p < 1)
 				goto err;
-			*p++ = va_arg(ap, wl_fixed_t);
+			*p++ = (va_arg(ap, wl_fixed_t)).raw;
 			break;
 		case 'u':
 			closure->types[i] = &ffi_type_uint32;
@@ -825,6 +825,7 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send)
 {
 	union wl_value *value;
 	int32_t si;
+	wl_fixed_t fixed;
 	int i;
 	struct timespec tp;
 	unsigned int time;
@@ -852,8 +853,8 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send)
 			fprintf(stderr, "%d", si);
 			break;
 		case 'f':
-			si = (int32_t) value->uint32;
-			fprintf(stderr, "%f", wl_fixed_to_double(si));
+			fixed.raw = (int32_t) value->uint32;
+			fprintf(stderr, "%f", wl_fixed_to_double(fixed));
 			break;
 		case 's':
 			fprintf(stderr, "\"%s\"", value->string);
diff --git a/src/wayland-util.h b/src/wayland-util.h
index 8447640..b3495fe 100644
--- a/src/wayland-util.h
+++ b/src/wayland-util.h
@@ -167,17 +167,19 @@ void wl_array_release(struct wl_array *array);
 void *wl_array_add(struct wl_array *array, size_t size);
 void wl_array_copy(struct wl_array *array, struct wl_array *source);
 
-typedef int32_t wl_fixed_t;
+typedef struct {
+	int32_t raw;
+} wl_fixed_t;
 
 static inline double
-wl_fixed_to_double (wl_fixed_t f)
+wl_fixed_to_double(wl_fixed_t f)
 {
 	union {
 		double d;
 		int64_t i;
 	} u;
 
-	u.i = ((1023LL + 44LL) << 52) + (1LL << 51) + f;
+	u.i = ((1023LL + 44LL) << 52) + (1LL << 51) + f.raw;
 
 	return u.d - (3LL << 43);
 }
@@ -185,23 +187,44 @@ wl_fixed_to_double (wl_fixed_t f)
 static inline wl_fixed_t
 wl_fixed_from_double(double d)
 {
+	wl_fixed_t f;
 	union {
 		double d;
 		int64_t i;
 	} u;
 
 	u.d = d + (3LL << (51 - 8));
+	f.raw = u.i;
 
-	return u.i;
+	return f;
 }
 
-static inline int wl_fixed_to_int(wl_fixed_t f)
+static inline int
+wl_fixed_to_int(wl_fixed_t f)
 {
-	return f / 256;
+	return f.raw / 256;
 }
-static inline wl_fixed_t wl_fixed_from_int(int i)
+
+static inline wl_fixed_t
+wl_fixed_from_int(int i)
+{
+	wl_fixed_t f;
+	f.raw = i * 256;
+	return f;
+}
+
+static inline wl_fixed_t
+wl_fixed_add(wl_fixed_t a, wl_fixed_t b)
+{
+	wl_fixed_t result = { a.raw + b.raw };
+	return result;
+}
+
+static inline wl_fixed_t
+wl_fixed_sub(wl_fixed_t a, wl_fixed_t b)
 {
-	return i * 256;
+	wl_fixed_t result = { a.raw - b.raw };
+	return result;
 }
 
 typedef void (*wl_log_func_t)(const char *, va_list);
diff --git a/tests/connection-test.c b/tests/connection-test.c
index 14a58e6..b219981 100644
--- a/tests/connection-test.c
+++ b/tests/connection-test.c
@@ -152,6 +152,7 @@ struct marshal_data {
 	union {
 		uint32_t u;
 		int32_t i;
+		wl_fixed_t f;
 		const char *s;
 		int h;
 	} value;
@@ -292,7 +293,7 @@ static void
 validate_demarshal_f(struct marshal_data *data,
 		     struct wl_object *object, wl_fixed_t f)
 {
-	assert(data->value.i == f);
+	assert(data->value.f.raw == f.raw);
 }
 
 static void
@@ -343,10 +344,10 @@ TEST(connection_demarshal)
 	memcpy(&msg[3], data.value.s, msg[2]);
 	demarshal(&data, "s", msg, (void *) validate_demarshal_s);
 
-	data.value.i = wl_fixed_from_double(-90000.2390);
+	data.value.f = wl_fixed_from_double(-90000.2390);
 	msg[0] = 400200;
 	msg[1] = 12;
-	msg[2] = data.value.i;
+	msg[2] = data.value.f.raw;
 	demarshal(&data, "f", msg, (void *) validate_demarshal_f);
 
 	release_marshal_data(&data);
@@ -414,17 +415,17 @@ TEST(connection_marshal_demarshal)
 	marshal_demarshal(&data, (void *) validate_demarshal_h,
 			  8, "h", data.value.h);
 
-	data.value.i = wl_fixed_from_double(1234.5678);
+	data.value.f = wl_fixed_from_double(1234.5678);
 	marshal_demarshal(&data, (void *) validate_demarshal_f,
-	                  12, "f", data.value.i);
+	                  12, "f", data.value.f);
 
-	data.value.i = wl_fixed_from_double(-90000.2390);
+	data.value.f = wl_fixed_from_double(-90000.2390);
 	marshal_demarshal(&data, (void *) validate_demarshal_f,
-	                  12, "f", data.value.i);
+	                  12, "f", data.value.f);
 
-	data.value.i = wl_fixed_from_double((1 << 23) - 1 + 0.0941);
+	data.value.f = wl_fixed_from_double((1 << 23) - 1 + 0.0941);
 	marshal_demarshal(&data, (void *) validate_demarshal_f,
-	                  12, "f", data.value.i);
+	                  12, "f", data.value.f);
 
 	release_marshal_data(&data);
 }
diff --git a/tests/fixed-benchmark.c b/tests/fixed-benchmark.c
index 0d7abd0..9374c65 100644
--- a/tests/fixed-benchmark.c
+++ b/tests/fixed-benchmark.c
@@ -38,8 +38,8 @@ noop_conversion(void)
 		double d;
 	} u;
 
-	for (f = 0; f < INT32_MAX; f++) {
-		u.i = f;
+	for (f.raw = 0; f.raw < INT32_MAX; f.raw++) {
+		u.i = f.raw;
 		global_d = u.d;
 	}
 }
@@ -49,7 +49,7 @@ magic_conversion(void)
 {
 	wl_fixed_t f;
 
-	for (f = 0; f < INT32_MAX; f++)
+	for (f.raw = 0; f.raw < INT32_MAX; f.raw++)
 		global_d = wl_fixed_to_double(f);
 }
 
@@ -59,8 +59,8 @@ mul_conversion(void)
 	wl_fixed_t f;
 
 	/* This will get optimized into multiplication by 1/256 */
-	for (f = 0; f < INT32_MAX; f++)
-		global_d = f / 256.0;
+	for (f.raw = 0; f.raw < INT32_MAX; f.raw++)
+		global_d = f.raw / 256.0;
 }
 
 double factor = 256.0;
@@ -70,8 +70,8 @@ div_conversion(void)
 {
 	wl_fixed_t f;
 
-	for (f = 0; f < INT32_MAX; f++)
-		global_d = f / factor;
+	for (f.raw = 0; f.raw < INT32_MAX; f.raw++)
+		global_d = f.raw / factor;
 }
 
 static void
diff --git a/tests/fixed-test.c b/tests/fixed-test.c
index 16fa5ff..76955ba 100644
--- a/tests/fixed-test.c
+++ b/tests/fixed-test.c
@@ -33,38 +33,38 @@ TEST(fixed_double_conversions)
 
 	d = 62.125;
 	f = wl_fixed_from_double(d);
-	fprintf(stderr, "double %lf to fixed %x\n", d, f);
-	assert(f == 0x3e20);
+	fprintf(stderr, "double %lf to fixed %x\n", d, f.raw);
+	assert(f.raw == 0x3e20);
 
 	d = -1200.625;
 	f = wl_fixed_from_double(d);
-	fprintf(stderr, "double %lf to fixed %x\n", d, f);
-	assert(f == -0x4b0a0);
+	fprintf(stderr, "double %lf to fixed %x\n", d, f.raw);
+	assert(f.raw == -0x4b0a0);
 
-	f = random();
+	f.raw = random();
 	d = wl_fixed_to_double(f);
-	fprintf(stderr, "fixed %x to double %lf\n", f, d);
-	assert(d == f / 256.0);
+	fprintf(stderr, "fixed %x to double %lf\n", f.raw, d);
+	assert(d == f.raw / 256.0);
 
-	f = 0x012030;
+	f.raw = 0x012030;
 	d = wl_fixed_to_double(f);
-	fprintf(stderr, "fixed %x to double %lf\n", f, d);
+	fprintf(stderr, "fixed %x to double %lf\n", f.raw, d);
 	assert(d == 288.1875);
 
-	f = 0x70000000;
+	f.raw = 0x70000000;
 	d = wl_fixed_to_double(f);
-	fprintf(stderr, "fixed %x to double %lf\n", f, d);
-	assert(d == f / 256);
+	fprintf(stderr, "fixed %x to double %lf\n", f.raw, d);
+	assert(d == f.raw / 256);
 
-	f = -0x012030;
+	f.raw = -0x012030;
 	d = wl_fixed_to_double(f);
-	fprintf(stderr, "fixed %x to double %lf\n", f, d);
+	fprintf(stderr, "fixed %x to double %lf\n", f.raw, d);
 	assert(d == -288.1875);
 
-	f = 0x80000000;
+	f.raw = 0x80000000;
 	d = wl_fixed_to_double(f);
-	fprintf(stderr, "fixed %x to double %lf\n", f, d);
-	assert(d == f / 256);
+	fprintf(stderr, "fixed %x to double %lf\n", f.raw, d);
+	assert(d == f.raw / 256);
 }
 
 TEST(fixed_int_conversions)
@@ -74,17 +74,17 @@ TEST(fixed_int_conversions)
 
 	i = 62;
 	f = wl_fixed_from_int(i);
-	assert(f == 62 * 256);
+	assert(f.raw == 62 * 256);
 
 	i = -2080;
 	f = wl_fixed_from_int(i);
-	assert(f == -2080 * 256);
+	assert(f.raw == -2080 * 256);
 
-	f = 0x277013;
+	f.raw = 0x277013;
 	i = wl_fixed_to_int(f);
 	assert(i == 0x2770);
 
-	f = -0x5044;
+	f.raw = -0x5044;
 	i = wl_fixed_to_int(f);
 	assert(i == -0x50);
 }
-- 
1.7.3.4



More information about the wayland-devel mailing list