From 7f79abec3f1ebc368c24aa885578a3f85ce7c0bc Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Sun, 4 Jul 2021 00:01:00 +0200 Subject: [PATCH] Fix issue with INIT_WITH of array/list/.... combined with tuple: _push_back_raw was used within an expanded macro and as a consequence was expanded multiple times, resulting in adding a new term in the sequence for each field of the tuple. --- m-core.h | 9 +++++++-- tests/test-malgo.c | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/m-core.h b/m-core.h index 77e30643..93a85352 100644 --- a/m-core.h +++ b/m-core.h @@ -3655,9 +3655,14 @@ m_core_parse2_enum (const char str[], const char **endptr) #define M_INIT_WITH_VAI22_FUNC(pair, a) \ M_INIT_WITH_VAI23_FUNC(M_PAIR_1 pair, M_PAIR_2 pair, a) +/* We first push a raw new item, and then we get back its pointer using _back. + _back (contrary to _push_raw) has no side effect, and so is safe to be used + in a macro */ #define M_INIT_WITH_VAI23_FUNC(d, op, a) \ - M_IF(M_PARENTHESIS_P( a ))(M_CALL_INIT_WITH, M_CALL_INIT_SET)(M_GET_OPLIST op, *M_C( M_GET_NAME op , _push_raw)(d), M_REMOVE_PARENTHESIS (a)) - + ( \ + (void) M_C(M_GET_NAME op, _push_raw)(d), \ + M_IF(M_PARENTHESIS_P( a ))(M_CALL_INIT_WITH, M_CALL_INIT_SET)(M_GET_OPLIST op, *M_C( M_GET_NAME op , _back)(d), M_REMOVE_PARENTHESIS (a)) \ + ) /* Initialize the container 'dest' as per 'oplist' INIT operator and fill it with the given VA argument diff --git a/tests/test-malgo.c b/tests/test-malgo.c index 44a96c58..e884fd7d 100644 --- a/tests/test-malgo.c +++ b/tests/test-malgo.c @@ -26,6 +26,7 @@ #include "m-string.h" #include "m-deque.h" #include "m-dict.h" +#include "m-tuple.h" #include "m-algo.h" #include "test-obj.h" @@ -51,6 +52,11 @@ DICT_DEF2(dict_int, string_t, int) ARRAY_DEF(array_uint, unsigned int) #define M_OPL_array_uint_t() ARRAY_OPLIST(array_uint) +TUPLE_DEF2(person, (age, int), (name, string_t) ) +#define M_OPL_person_t() TUPLE_OPLIST(person, M_DEFAULT_OPLIST, STRING_OPLIST) +ARRAY_DEF(array_person, person_t) +#define M_OPL_array_person_t() ARRAY_OPLIST(array_person, M_OPL_person_t() ) + #include "coverage.h" START_COVERAGE ALGO_DEF(algo_array, array_int_t) @@ -493,6 +499,14 @@ static void test_string(void) string_clear(s); list_string_clear(l); + + M_LET( (a, (13, ("Jean") ),(14, ("Michael"))), array_person_t ) { + assert( array_person_size(a) == 2); + assert( (*array_person_get(a, 0))->age == 13 ); + assert( string_equal_str_p( (*array_person_get(a, 0))->name, "Jean") ); + assert( (*array_person_get(a, 1))->age == 14 ); + assert( string_equal_str_p( (*array_person_get(a, 1))->name, "Michael") ); + } } static void test_extract(void)