-#define ALLOC(ptr, size) do { \
- (ptr) = malloc(size); \
- if (!(ptr)) { \
- cdecl__errmsg(CDECL__ENOMEM); \
+/*
+ * Allocate a parse tree node via cdecl__alloc_item.
+ *
+ * - m1 specifies the item's union member to assign to ptr, which selects the
+ * type of node to allocate.
+ *
+ * - m2 specifies the "next" or "child" member, which is initialized to a null
+ * pointer. The cdecl__alloc_item function sets the declarator.child member
+ * to null; we explicitly copy this null pointer to the returned union member
+ * to avoid type punning. It is hoped that compilers will notice that these
+ * pointers are at the same offset therefore the assignment can be elided.
+ *
+ * The resulting pointer can be passed directly to free, as the union is the
+ * first member of the parse_item structure.
+ *
+ * Use the wrapper macros below instead of this one.
+ */
+#define ALLOC_ITEM(ptr, m1, m2) do { \
+ struct parse_item *item; \
+ if (!(item = cdecl__alloc_item(0))) \