Re: [PATCH 4/4] Explicitly type void* pointers

Subject: Re: [PATCH 4/4] Explicitly type void* pointers

Date: Tue, 10 Apr 2012 00:31:34 +0300

To: Vladimir Marek, Notmuch Mail


From: Jani Nikula

Vladimir Marek <Vladimir.Marek@Oracle.COM> writes:

> Hi,
>> Hi, does notmuch not compile without this? IIRC talloc_steal is a macro
>> that's supposed to provide type safety (at least with GCC), and I'd be
>> hesitant about adding the casts. Please look in your talloc.h.
> It does not compile. It might be that I'm using Sun/Oracle CC instead of
> gcc. The error looks like this:
> "lib/", line 1368: Error: Cannot assign void* to const char*.

In general, that's not a difference in the C++ compilers. You can't
assign 'void *' to 'T *' in C++.

> When looking into talloc documentation, the definition seems to be:
> void* talloc_steal ( const void * new_ctx, const void * ptr )
> When looking into talloc.h, it says:
> /* try to make talloc_set_destructor() and talloc_steal() type safe,
>    if we have a recent gcc */

It just so happens that the trick for type safety fixes the problem for
recent GCC by having an explicit cast.

> So, maybe the way to satisfy everyone would be:
> notmuch_message_t *tmp_message = message;
> talloc_steal(notmuch, tmp_message);
> return(tmp_message);
> Or alternatively,
> #if (__GNUC__ >= 3)
>        return talloc_steal (notmuch, message);
> #else
>        return (notmuch_message_t*) talloc_steal (notmuch, message);
> #fi
> Of course I'm happy either way :)

I'm throwing in a third alternative below. Does it work for you? I think
it's both prettier and uglier than the above at the same time! ;)

A middle ground would be to change the callers to use
"notmuch_talloc_steal", and just #define notmuch_talloc_steal
talloc_steal if __GNUC__ >= 3.

One could argue upstream talloc should have this, but OTOH it's a C


diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
index ea836f7..83b46e8 100644
--- a/lib/notmuch-private.h
+++ b/lib/notmuch-private.h
@@ -499,4 +499,22 @@ _notmuch_filenames_create (const void *ctx,
+#ifdef __cplusplus
+/* Implicit typecast from 'void *' to 'T *' is okay in C, but not in
+ * C++. In talloc_steal, an explicit cast is provided for type safety
+ * in some GCC versions. Otherwise, a cast is required. Provide a
+ * template function for this to maintain type safety, and redefine
+ * talloc_steal to use it.
+ */
+#if !(__GNUC__ >= 3)
+template <class T>
+T *notmuch_talloc_steal(const void *new_ctx, const T *ptr)
+    return static_cast<T*>(talloc_steal(new_ctx, ptr));
+#undef talloc_steal
+#define talloc_steal notmuch_talloc_steal