Parser tests: Make LIST_* macros type safe

With the varargs approach that was used before, it was very easy to add a
list item of the wrong type, which would (hopefully) result in an assertion
violation, because va_arg() then read some senseless data.
This commit is contained in:
Laria 2021-12-18 16:34:09 +01:00
parent 5712d7f4ff
commit 3759813ed9

View file

@ -1,5 +1,4 @@
#include <assert.h>
#include <stdarg.h>
#include "apfl.h"
#include "resizable.h"
@ -125,48 +124,42 @@ enum listbuilder_cmd {
};
#define LISTBUILDER_NAME(n) listbuilder_##n
#define LISTBUILDER_ITEM_NAME(n) listbuilder_item_##n
#define MKLISTBUILDER(name, listtype, itemtype, items_memb, len_memb) \
struct LISTBUILDER_ITEM_NAME(name) { \
bool has_item; \
itemtype item; \
}; \
listtype \
LISTBUILDER_NAME(name)(struct parser_test *pt, ...) \
{ \
LISTBUILDER_NAME(name)( \
struct parser_test *pt, \
struct LISTBUILDER_ITEM_NAME(name) items[] \
) { \
listtype body; \
size_t cap = 0; \
\
apfl_resizable_init((void **)&body.items_memb, &body.len_memb, &cap); \
\
va_list ap; \
va_start(ap, pt); \
\
for (;;) { \
enum listbuilder_cmd cmd = va_arg(ap, enum listbuilder_cmd); \
if (cmd == LISTBUILDER_STOP) { \
break; \
} \
assert(cmd == LISTBUILDER_ADD); \
itemtype item = va_arg(ap, itemtype); \
\
for (items++; items->has_item; items++) { \
if (!apfl_resizable_append( \
sizeof(itemtype), \
(void **)&body.items_memb, \
&body.len, \
&cap, \
&item, \
&items->item, \
1 \
)) { \
va_end(ap); \
test_fatalf(pt->t, "Failed appending"); \
assert(false); \
} \
} \
\
va_end(ap); \
\
return body; \
} \
#define LIST_BEGIN(pt, builder) (LISTBUILDER_NAME(builder)(pt,
#define LIST_END LISTBUILDER_STOP))
#define LIST_ADD LISTBUILDER_ADD,
#define LIST_BEGIN(pt, builder) (LISTBUILDER_NAME(builder)(pt, (struct LISTBUILDER_ITEM_NAME(builder)[]) {{.has_item=false
#define LIST_END }, {.has_item = false}}))
#define LIST_ADD }, {.has_item = true, .item =
MKLISTBUILDER(list, struct apfl_expr_list, struct apfl_expr_list_item, items, len)
MKLISTBUILDER(body, struct apfl_expr_body, struct apfl_expr, items, len)