Hi,

On Sunday, September 16, 2012 04:23:14 PM Andres Freund wrote:
> What do you think about something like:
> 
> typedef struct dlist_iter
> {
>       /*
>        * Use a union with equivalent storage as dlist_node to make it possible
> to * initialize the struct inside a macro without multiple evaluation. */
>       union {
>               struct {
>                       dlist_node *cur;
>                       dlist_node *end;
>               };
>               dlist_node init;
>       };
> } dlist_iter;
> 
> typedef struct dlist_mutable_iter
> {
>       union {
>               struct {
>                       dlist_node *cur;
>                       dlist_node *end;
>               };
>               dlist_node init;
>       };
>       dlist_node *next;
> } dlist_mutable_iter;
> 
> #define dlist_iter_foreach(iter, ptr)                                         
>                              \
>       for (iter.init = (ptr)->head; iter.cur != iter.end;                     
>  \
>            iter.cur = iter.cur->next)
> 
> #define dlist_iter_foreach_modify(iter, ptr)                                  
>                          
\
>       for (iter.init = (ptr)->head, iter.next = iter.cur->next;               
>  \
>            iter.cur != iter.end                                               
>  \
>            iter.cur = iter.next, iter.next = iter.cur->next)
> 
> With that and some trivial changes *all* multiple evaluation possibilities
> are gone.
> 
> (_iter_ in there would go, thats just so I can have both in the same file
> for now).

I am thinking whether a macro like:

#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#define assert_compatible_types(a, b) _Static_assert(            \
                __builtin_types_compatible_p(a, __typeof__ (b) ), \
                "variable `" #b "` is not compatible to type `" #a "`" )
#else
#define assert_compatible_types(a, b) (void)0
#endif

used like:

#define dlist_iter_foreach(iter, ptr)                                           
                             \
        assert_compatible_types(dlist_iter, iter);                              
 \
        for (iter.init = (ptr)->head; iter.cur != iter.end;                     
 \
             iter.cur = iter.cur->next)

would be useful.

If you use the wrong type you get an error like:

error: static assertion failed: "variable `iter` is not compatible to type 
`dlist_iter`"

Do people think this is something worthwile for some of the macros in pg? At 
times the compiler errors that get generated in larger macros can be a bit 
confusing and something like that would make it easier to see the originating 
error.

I found __builtin_types_compatible while perusing the gcc docs to find whether 
there is something like __builtin_constant_p for checking the pureness of an 
expression ;)

Andres
-- 
 Andres Freund                     http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to