I'm writing a vapi file for a non-gobject API. One of the object types is
reference-counted, but rather than a function, unref is a macro of the form:

#define Tcl_DecrRefCount(objPtr) do { ... } while(0)

As an unref_function, Vala wants to put this in an expression like so:

#define _Tcl_DecrRefCount0(var) \
    ((var == NULL) ? NULL : (var = (Tcl_DecrRefCount (var), NULL)))

The problem here is that the `do` construct is not an exact substitute for
a function call. It's a statement rather than an expression, so you can't
have it in a comma sequence like that. GCC fails with the following error:

error: expected expression before 'do'
 #define _Tcl_DecrRefCount0(var) ((var == NULL) ? NULL : (var =
(Tcl_DecrRefCount (var), NULL)))
                                                                 ^
note: in expansion of macro '_Tcl_DecrRefCount0'
    _Tcl_DecrRefCount0 (obj);
    ^~~~~~~~~~~~~~~~~~

This bug would only arise with an API where an object's unref_function is a
macro, and that macro uses the `do` idiom. I don't know how common that is,
but I've at least seen it in both the Python and Tcl APIs.

I suspect that the practical solution is to wrap the macro in a function
and call it a day. But (since this is for a hobby project) I took a look
through the compiler internals instead. This is what I found:

The macro is generated in Vala.CCodeBaseModule, by destroy_value, which
returns a CCodeExpression. Everywhere destroy_value is called, the
expression is wrapped in a CCodeExpressionStatement, the result of which is
discarded. I can't figure out any reason why destroy_value needs to be an
expression, rather than a sequence of statements. If I were to convert this
function to output statements instead, the `do` macro would be legit.

I kind of want to give it a shot - does anybody have any objections or
suggestions?

- dpk
_______________________________________________
vala-list mailing list
vala-list@gnome.org
https://mail.gnome.org/mailman/listinfo/vala-list

Reply via email to