On 14 July 2006 18:22, Kaveh R. Ghazi wrote: > Now imagine if I change the type of __t to const_tree like so: > > typedef const union tree_node *const_tree; > #define TREE_CHECK(T, CODE) __extension__ \ > ({ const_tree const __t = (T); \ > if (TREE_CODE (__t) != (CODE)) \ > tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, (CODE), 0); > \ __t; })
> Now the problem is that the statement expression in the TREE_CHECK > macro uses __t as it's "return value". The TREE_CHECK macro is used > in both read and write situations of tree members. So the "return > value" of this statement expression cannot be const or all the write > cases barf. So just return T instead of _t. > Another solution might be to use the macro parameter as the return > type like so: Ah, I see you thought of that! > typedef const union tree_node *const_tree; > #define TREE_CHECK(T, CODE) __extension__ \ > ({ const_tree const __t = (T); \ > if (TREE_CODE (__t) != (CODE)) \ > tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, (CODE), 0); > \ (T); }) > > Then if "T" isn't already const you can write to it. But this > evaluates "T" twice so if there are side-effects potentially we get > hosed. > Any ideas? Use /two/ locals like this? typedef const union tree_node *const_tree; #define TREE_CHECK(T, CODE) __extension__ \ ({ \ __typeof__(T) __t = (T); \ const_tree const __ct = t; \ if (TREE_CODE (__ct) != (CODE)) \ tree_check_failed (__ct, __FILE__, __LINE__, __FUNCTION__, (CODE), 0); \ __t; }) So __ct is always const, and __t has the same const-ness as T. Hmm. The docs don't specify whether typeof preserves CV-qualification. We could always add a __qualified_typeof__ that did if ordinary __typeof__ doesn't, I suppose. cheers, DaveK -- Can't think of a witty .sigline today....