[Pixman] [PATCH 3/4] Fix "malloc/calloc return values need explicit casts" C++ errors

Siarhei Siamashka siarhei.siamashka at gmail.com
Sat Dec 15 21:13:49 PST 2012


There are a number of places in pixman code which are using
functions malloc/calloc/pixman_malloc_ab/pixman_malloc_abc:

pixman-access.c:    argb8_pixels = pixman_malloc_ab (width, sizeof(uint32_t));
pixman-bits-image.c:	if ((alpha = malloc (width * sizeof (uint32_t))))
pixman-bits-image.c:	if ((alpha = malloc (width * sizeof (argb_t))))
pixman-bits-image.c:	return malloc (buf_size);
pixman.c:        boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects);
pixman-filter.c:    p = params = malloc (*width * n_phases * sizeof (pixman_fixed_t));
pixman-filter.c:    params = malloc (*n_values * sizeof (pixman_fixed_t));
pixman-general.c:	scanline_buffer = pixman_malloc_abc (width, 3, Bpp);
pixman-glyph.c:    if (!(cache = malloc (sizeof *cache)))
pixman-glyph.c:    if (!(glyph = malloc (sizeof *glyph)))
pixman-image.c:	pixman_malloc_ab (n_stops + 2, sizeof (pixman_gradient_stop_t));
pixman-image.c:    pixman_image_t *image = malloc (sizeof (pixman_image_t));
pixman-image.c:	common->transform = malloc (sizeof (pixman_transform_t));
pixman-image.c:	new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t));
pixman-implementation.c:    if ((imp = malloc (sizeof (pixman_implementation_t))))
pixman-region.c:    return malloc (sz);
pixman-region.c:                rit = malloc (data_size);
pixman-trap.c:    traps = pixman_malloc_ab (n_tris, 2 * sizeof (pixman_trapezoid_t));
pixman-utils.c:    return malloc (a * b);
pixman-utils.c:	return malloc (a * b * c);
pixman-utils.c:    boxes16 = pixman_malloc_ab (n_boxes, sizeof (pixman_box16_t));
pixman-utils.c:	boxes32 = pixman_malloc_ab (n_boxes, sizeof (pixman_box32_t));
pixman-bits-image.c:	return calloc (buf_size, 1);
pixman-compiler.h:        type *value = calloc (1, sizeof (type));
pixman-compiler.h:	type *value = calloc (1, sizeof (type));

Unfortunately they fail to compile in C++ mode because the compiler wants
explicit type casts for the returned pointers:
    http://stackoverflow.com/questions/3477741/why-does-c-require-a-cast-for-malloc-but-c-doesnt

This patch tries to solve the problem in a less invasive way by
adding some compatibility wrappers which allow compiling such
C code without modifications.
---
 pixman/pixman-private.h |   79 ++++++++++++++++++++++++++++++++++++++++++++--
 pixman/pixman-utils.c   |   23 -------------
 2 files changed, 75 insertions(+), 27 deletions(-)

diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 416d2a1..38e8b6c 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -28,6 +28,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <stddef.h>
+#include <stdlib.h>
 
 #include "pixman-compiler.h"
 
@@ -773,11 +774,29 @@ PIXMAN_EXPORT pixman_implementation_t *
 _pixman_internal_only_get_implementation (void);
 
 /* Memory allocation helpers */
-void *
-pixman_malloc_ab (unsigned int n, unsigned int b);
 
-void *
-pixman_malloc_abc (unsigned int a, unsigned int b, unsigned int c);
+static inline void *
+pixman_malloc_ab (unsigned int a,
+                  unsigned int b)
+{
+    if (a >= INT32_MAX / b)
+	return NULL;
+
+    return malloc (a * b);
+}
+
+static inline void *
+pixman_malloc_abc (unsigned int a,
+                   unsigned int b,
+                   unsigned int c)
+{
+    if (a >= INT32_MAX / b)
+	return NULL;
+    else if (a * b >= INT32_MAX / c)
+	return NULL;
+    else
+	return malloc (a * b * c);
+}
 
 pixman_bool_t
 _pixman_multiply_overflows_size (size_t a, size_t b);
@@ -1110,6 +1129,58 @@ void pixman_timer_register (pixman_timer_t *timer);
 
 #endif /* PIXMAN_TIMERS */
 
+/*
+ * C++ compatibility wrappers, which simulate implicit cast from void* to
+ * any pointer for the return value from malloc(), calloc() and friends.
+ */
+
+#ifdef __cplusplus
+
+class pixman_implicitly_castable_pointer
+{
+    void *data;
+public:
+    pixman_implicitly_castable_pointer (void *p) : data(p) { }
+    template<typename T> operator T * () const { return (T *)data; }
+};
+
+static inline pixman_implicitly_castable_pointer
+pixman_malloc (size_t size)
+{
+    return pixman_implicitly_castable_pointer (malloc (size));
+}
+
+static inline pixman_implicitly_castable_pointer
+pixman_calloc (size_t n, size_t size)
+{
+    return pixman_implicitly_castable_pointer (calloc (n, size));
+}
+
+static inline pixman_implicitly_castable_pointer
+pixman_malloc_ab_wrapper (unsigned int a, unsigned int b)
+{
+    return pixman_implicitly_castable_pointer (pixman_malloc_ab (a, b));
+}
+
+static inline pixman_implicitly_castable_pointer
+pixman_malloc_abc_wrapper (unsigned int a, unsigned int b, unsigned int c)
+{
+    return pixman_implicitly_castable_pointer (pixman_malloc_abc (a, b, c));
+}
+
+/*
+ * This is a hack to override malloc/calloc functions using defines. Because
+ * we have already included stdlib.h here, there should be no risk for these
+ * macros to conflict with the standard headers (as long as stdlib.h has proper
+ * safeguards against double inclusion).
+ */
+#define malloc(a) pixman_malloc(a)
+#define calloc(a, b) pixman_calloc((a), (b))
+#define pixman_malloc_ab(a, b) pixman_malloc_ab_wrapper((a), (b))
+#define pixman_malloc_abc(a, b, c) pixman_malloc_abc_wrapper((a), (b), (c))
+
+#endif
+
 #endif /* __ASSEMBLER__ */
 
 #endif /* PIXMAN_PRIVATE_H */
diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c
index b1e9fb6..9ed9697 100644
--- a/pixman/pixman-utils.c
+++ b/pixman/pixman-utils.c
@@ -48,29 +48,6 @@ _pixman_addition_overflows_int (unsigned int a, unsigned int b)
     return a > INT32_MAX - b;
 }
 
-void *
-pixman_malloc_ab (unsigned int a,
-                  unsigned int b)
-{
-    if (a >= INT32_MAX / b)
-	return NULL;
-
-    return malloc (a * b);
-}
-
-void *
-pixman_malloc_abc (unsigned int a,
-                   unsigned int b,
-                   unsigned int c)
-{
-    if (a >= INT32_MAX / b)
-	return NULL;
-    else if (a * b >= INT32_MAX / c)
-	return NULL;
-    else
-	return malloc (a * b * c);
-}
-
 static force_inline uint16_t
 float_to_unorm (float f, int n_bits)
 {
-- 
1.7.8.6



More information about the Pixman mailing list