Introduce dynamic compound literal
authorOlivier Dion <odion@efficios.com>
Mon, 7 Oct 2024 16:11:42 +0000 (12:11 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 23 Oct 2024 15:34:40 +0000 (11:34 -0400)
In C++, compound literal are temporary objects which have a lifetime
bound to its expression.  To extend the lifetime of such objects, the
`SIDE_DYNAMIC_COMPOUND_LITERAL' macro is introduced.

In C, this macro expands to `SIDE_COMPOUND_LITERAL'.  In C++, it
allocates the necessary size to store the object onto the stack using
`alloca(3)'.  The memory is then initialized by copying the expression
to it.

This is necessary for attributes of dynamic fields.  However,
`SIDE_DYNAMIC_COMPOUND_LITERAL' only return a pointer to the object and
not its size.  To overcome this, the API is changed and the
`side_dynamic_attr_list()' macro must be used on dynamic arguments of
dynamic fields.  The macro itself is not defined by libside.  Instead,
macro dispatching is done to get the pointer to the object and its size.

Change-Id: Ieddaa6b2209c03031cef916033efd57564229db5
Signed-off-by: Olivier Dion <odion@efficios.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
include/side/instrumentation-c-api.h
include/side/macros.h
tests/unit/test.c

index 6f4ab0613d13a541097036d6b69a2f2f8de483ca..244b8412501e276015de1da94711422d43960649 100644 (file)
                .value = SIDE_PARAM(_value), \
        }
 
-#define side_attr_list(...) \
+#define side_attr_list(...)                                            \
+       SIDE_COMPOUND_LITERAL(const struct side_attr, __VA_ARGS__)
+
+/*
+ * `side_dynamic_attr_list()' is actually not defined.  Instead, macro
+ * dispatching is done to get the allocated array and its size independently.
+ *
+ * This is because C++ does not support well array compound literal that are not
+ * static.  See the comment of `SIDE_DYNAMIC_COMPOUND_LITERAL'.
+ *
+ * Dispatching is done by concatenating a prefix that will expand to a defined
+ * macro.
+ */
+
+/*
+ * Dispatch `_side_allocate_dynamic_' of `side_dynamic_attr_list()'.  Returns the
+ * dynamic allocation for the list of attributes.
+ *
+ * In C, it expands to a regular compound literal.  In C++, the compound literal
+ * is copied onto a `alloca(3)' buffer, thus bypassing the the lifetime of the
+ * expression.
+ *
+ * Because `SIDE_DYNAMIC_COMPOUND_LITERAL' uses `SIDE_CAT' internally, this
+ * dispatching must be done using `SIDE_CAT2'.
+ */
+#define _side_allocate_dynamic_side_dynamic_attr_list(...)             \
+       SIDE_DYNAMIC_COMPOUND_LITERAL(const struct side_attr, __VA_ARGS__)
+
+/*
+ * Dispatch `_side_allocate_static_' of `side_dynamic_attr_list()'.  Returns the
+ * static allocation of the list of attributes.
+ *
+ * This variant is fine to be used in C++ if the only goal is to determine the
+ * allocation size, since the lifetime of the allocation is bound to the
+ * expression.
+ *
+ * This dispatching can be either done with `SIDE_CAT' or `SIDE_CAT2'.
+ */
+#define _side_allocate_static_side_dynamic_attr_list(...)                      \
        SIDE_COMPOUND_LITERAL(const struct side_attr, __VA_ARGS__)
 
 #define side_attr_null(_val)           { .type = SIDE_ATTR_TYPE_NULL }
                .u = { \
                        .side_dynamic = { \
                                .side_null = { \
-                                       .attr = SIDE_PTR_INIT(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
-                                       .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
+                                       .attr = SIDE_PTR_INIT(SIDE_CAT2(_side_allocate_dynamic_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
+                                       .nr_attr = SIDE_ARRAY_SIZE(SIDE_CAT2(_side_allocate_static_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
                                }, \
                        }, \
                }, \
                        .side_dynamic = { \
                                .side_bool = { \
                                        .type = { \
-                                               .attr = SIDE_PTR_INIT(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
-                                               .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
+                                               .attr = SIDE_PTR_INIT(SIDE_CAT2(_side_allocate_dynamic_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
+                                               .nr_attr = SIDE_ARRAY_SIZE(SIDE_CAT2(_side_allocate_static_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
                                                .bool_size = sizeof(uint8_t), \
                                                .len_bits = 0, \
                                                .byte_order = SIDE_ENUM_INIT(SIDE_TYPE_BYTE_ORDER_HOST), \
                        .side_dynamic = { \
                                .side_byte = { \
                                        .type = { \
-                                               .attr = SIDE_PTR_INIT(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
-                                               .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
+                                               .attr = SIDE_PTR_INIT(SIDE_CAT2(_side_allocate_dynamic_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
+                                               .nr_attr = SIDE_ARRAY_SIZE(SIDE_CAT2(_side_allocate_static_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
                                        }, \
                                        .value = (_val), \
                                }, \
                        .side_dynamic = { \
                                .side_string = { \
                                        .type = { \
-                                               .attr = SIDE_PTR_INIT(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
-                                               .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
+                                               .attr = SIDE_PTR_INIT(SIDE_CAT2(_side_allocate_dynamic_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
+                                               .nr_attr = SIDE_ARRAY_SIZE(SIDE_CAT2(_side_allocate_static_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
                                                .unit_size = _unit_size, \
                                                .byte_order = SIDE_ENUM_INIT(_byte_order), \
                                        }, \
                }, \
        }
 #define side_arg_dynamic_string(_val, _attr...) \
-       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(uint8_t), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(uint8_t), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 #define side_arg_dynamic_string16(_val, _attr...) \
-       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(uint16_t), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+63u    _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(uint16_t), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 #define side_arg_dynamic_string16_le(_val, _attr...) \
-       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_LE, sizeof(uint16_t), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_LE, sizeof(uint16_t), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 #define side_arg_dynamic_string16_be(_val, _attr...) \
-       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_BE, sizeof(uint16_t), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_BE, sizeof(uint16_t), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 #define side_arg_dynamic_string32(_val, _attr...) \
-       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(uint32_t), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(uint32_t), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 #define side_arg_dynamic_string32_le(_val, _attr...) \
-       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_LE, sizeof(uint32_t), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_LE, sizeof(uint32_t), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 #define side_arg_dynamic_string32_be(_val, _attr...) \
-       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_BE, sizeof(uint32_t), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_BE, sizeof(uint32_t), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 
 #define _side_arg_dynamic_integer(_field, _val, _type, _signedness, _byte_order, _integer_size, _len_bits, _attr...) \
        { \
                        .side_dynamic = { \
                                .side_integer = { \
                                        .type = { \
-                                               .attr = SIDE_PTR_INIT(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
-                                               .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
+                                               .attr = SIDE_PTR_INIT(SIDE_CAT2(_side_allocate_dynamic_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
+                                               .nr_attr = SIDE_ARRAY_SIZE(SIDE_CAT2(_side_allocate_static_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
                                                .integer_size = _integer_size, \
                                                .len_bits = _len_bits, \
                                                .signedness = _signedness, \
        }
 
 #define side_arg_dynamic_u8(_val, _attr...) \
-       _side_arg_dynamic_integer(.side_u8, _val, SIDE_TYPE_DYNAMIC_INTEGER, false, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(uint8_t), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_integer(.side_u8, _val, SIDE_TYPE_DYNAMIC_INTEGER, false, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(uint8_t), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 #define side_arg_dynamic_s8(_val, _attr...) \
-       _side_arg_dynamic_integer(.side_s8, _val, SIDE_TYPE_DYNAMIC_INTEGER, true, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(int8_t), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_integer(.side_s8, _val, SIDE_TYPE_DYNAMIC_INTEGER, true, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(int8_t), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 
 #define _side_arg_dynamic_u16(_val, _byte_order, _attr...) \
-       _side_arg_dynamic_integer(.side_u16, _val, SIDE_TYPE_DYNAMIC_INTEGER, false, _byte_order, sizeof(uint16_t), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_integer(.side_u16, _val, SIDE_TYPE_DYNAMIC_INTEGER, false, _byte_order, sizeof(uint16_t), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 #define _side_arg_dynamic_u32(_val, _byte_order, _attr...) \
-       _side_arg_dynamic_integer(.side_u32, _val, SIDE_TYPE_DYNAMIC_INTEGER, false, _byte_order, sizeof(uint32_t), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_integer(.side_u32, _val, SIDE_TYPE_DYNAMIC_INTEGER, false, _byte_order, sizeof(uint32_t), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 #define _side_arg_dynamic_u64(_val, _byte_order, _attr...) \
-       _side_arg_dynamic_integer(.side_u64, _val, SIDE_TYPE_DYNAMIC_INTEGER, false, _byte_order, sizeof(uint64_t), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_integer(.side_u64, _val, SIDE_TYPE_DYNAMIC_INTEGER, false, _byte_order, sizeof(uint64_t), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 #define _side_arg_dynamic_u128(_val, _byte_order, _attr...) \
-       _side_arg_dynamic_integer(.side_u128, _val, SIDE_TYPE_DYNAMIC_INTEGER, false, _byte_order, sizeof(unsigned __int128), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_integer(.side_u128, _val, SIDE_TYPE_DYNAMIC_INTEGER, false, _byte_order, sizeof(unsigned __int128), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 
 #define _side_arg_dynamic_s16(_val, _byte_order, _attr...) \
-       _side_arg_dynamic_integer(.side_s16, _val, SIDE_TYPE_DYNAMIC_INTEGER, true, _byte_order, sizeof(int16_t), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_integer(.side_s16, _val, SIDE_TYPE_DYNAMIC_INTEGER, true, _byte_order, sizeof(int16_t), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 #define _side_arg_dynamic_s32(_val, _byte_order, _attr...) \
-       _side_arg_dynamic_integer(.side_s32, _val, SIDE_TYPE_DYNAMIC_INTEGER, true, _byte_order, sizeof(int32_t), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_integer(.side_s32, _val, SIDE_TYPE_DYNAMIC_INTEGER, true, _byte_order, sizeof(int32_t), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 #define _side_arg_dynamic_s64(_val, _byte_order, _attr...) \
-       _side_arg_dynamic_integer(.side_s64, _val, SIDE_TYPE_DYNAMIC_INTEGER, true, _byte_order, sizeof(int64_t), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_integer(.side_s64, _val, SIDE_TYPE_DYNAMIC_INTEGER, true, _byte_order, sizeof(int64_t), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 #define _side_arg_dynamic_s128(_val, _byte_order, _attr...) \
-       _side_arg_dynamic_integer(.side_s128, _val, SIDE_TYPE_DYNAMIC_INTEGER, true, _byte_order, sizeof(__int128), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_integer(.side_s128, _val, SIDE_TYPE_DYNAMIC_INTEGER, true, _byte_order, sizeof(__int128), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 
 #define _side_arg_dynamic_pointer(_val, _byte_order, _attr...) \
        _side_arg_dynamic_integer(.side_uptr, (uintptr_t) (_val), SIDE_TYPE_DYNAMIC_POINTER, false, _byte_order, \
-                       sizeof(uintptr_t), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+                       sizeof(uintptr_t), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 
 #define _side_arg_dynamic_float(_field, _val, _type, _byte_order, _float_size, _attr...) \
        { \
                        .side_dynamic = { \
                                .side_float = { \
                                        .type = { \
-                                               .attr = SIDE_PTR_INIT(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
-                                               .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
+                                               .attr = SIDE_PTR_INIT(SIDE_CAT2(_side_allocate_dynamic_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
+                                               .nr_attr = SIDE_ARRAY_SIZE(SIDE_CAT2(_side_allocate_static_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
                                                .float_size = _float_size, \
                                                .byte_order = SIDE_ENUM_INIT(_byte_order), \
                                        }, \
        }
 
 #define _side_arg_dynamic_float_binary16(_val, _byte_order, _attr...) \
-       _side_arg_dynamic_float(.side_float_binary16, _val, SIDE_TYPE_DYNAMIC_FLOAT, _byte_order, sizeof(_Float16), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_float(.side_float_binary16, _val, SIDE_TYPE_DYNAMIC_FLOAT, _byte_order, sizeof(_Float16), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 #define _side_arg_dynamic_float_binary32(_val, _byte_order, _attr...) \
-       _side_arg_dynamic_float(.side_float_binary32, _val, SIDE_TYPE_DYNAMIC_FLOAT, _byte_order, sizeof(_Float32), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_float(.side_float_binary32, _val, SIDE_TYPE_DYNAMIC_FLOAT, _byte_order, sizeof(_Float32), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 #define _side_arg_dynamic_float_binary64(_val, _byte_order, _attr...) \
-       _side_arg_dynamic_float(.side_float_binary64, _val, SIDE_TYPE_DYNAMIC_FLOAT, _byte_order, sizeof(_Float64), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_float(.side_float_binary64, _val, SIDE_TYPE_DYNAMIC_FLOAT, _byte_order, sizeof(_Float64), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 #define _side_arg_dynamic_float_binary128(_val, _byte_order, _attr...) \
-       _side_arg_dynamic_float(.side_float_binary128, _val, SIDE_TYPE_DYNAMIC_FLOAT, _byte_order, sizeof(_Float128), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_arg_dynamic_float(.side_float_binary128, _val, SIDE_TYPE_DYNAMIC_FLOAT, _byte_order, sizeof(_Float128), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 
 /* Host endian */
-#define side_arg_dynamic_u16(_val, _attr...)                   _side_arg_dynamic_u16(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_u32(_val, _attr...)                   _side_arg_dynamic_u32(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_u64(_val, _attr...)                   _side_arg_dynamic_u64(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_u128(_val, _attr...)                  _side_arg_dynamic_u128(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_s16(_val, _attr...)                   _side_arg_dynamic_s16(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_s32(_val, _attr...)                   _side_arg_dynamic_s32(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_s64(_val, _attr...)                   _side_arg_dynamic_s64(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_s128(_val, _attr...)                  _side_arg_dynamic_s128(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_pointer(_val, _attr...)               _side_arg_dynamic_pointer(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_float_binary16(_val, _attr...)                _side_arg_dynamic_float_binary16(_val, SIDE_TYPE_FLOAT_WORD_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_float_binary32(_val, _attr...)                _side_arg_dynamic_float_binary32(_val, SIDE_TYPE_FLOAT_WORD_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_float_binary64(_val, _attr...)                _side_arg_dynamic_float_binary64(_val, SIDE_TYPE_FLOAT_WORD_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_float_binary128(_val, _attr...)       _side_arg_dynamic_float_binary128(_val, SIDE_TYPE_FLOAT_WORD_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+#define side_arg_dynamic_u16(_val, _attr...)                   _side_arg_dynamic_u16(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_u32(_val, _attr...)                   _side_arg_dynamic_u32(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_u64(_val, _attr...)                   _side_arg_dynamic_u64(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_u128(_val, _attr...)                  _side_arg_dynamic_u128(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_s16(_val, _attr...)                   _side_arg_dynamic_s16(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_s32(_val, _attr...)                   _side_arg_dynamic_s32(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_s64(_val, _attr...)                   _side_arg_dynamic_s64(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_s128(_val, _attr...)                  _side_arg_dynamic_s128(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_pointer(_val, _attr...)               _side_arg_dynamic_pointer(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_float_binary16(_val, _attr...)                _side_arg_dynamic_float_binary16(_val, SIDE_TYPE_FLOAT_WORD_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_float_binary32(_val, _attr...)                _side_arg_dynamic_float_binary32(_val, SIDE_TYPE_FLOAT_WORD_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_float_binary64(_val, _attr...)                _side_arg_dynamic_float_binary64(_val, SIDE_TYPE_FLOAT_WORD_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_float_binary128(_val, _attr...)       _side_arg_dynamic_float_binary128(_val, SIDE_TYPE_FLOAT_WORD_ORDER_HOST, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 
 /* Little endian */
-#define side_arg_dynamic_u16_le(_val, _attr...)                _side_arg_dynamic_u16(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_u32_le(_val, _attr...)                _side_arg_dynamic_u32(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_u64_le(_val, _attr...)                _side_arg_dynamic_u64(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_u128_le(_val, _attr...)               _side_arg_dynamic_u128(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_s16_le(_val, _attr...)                _side_arg_dynamic_s16(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_s32_le(_val, _attr...)                _side_arg_dynamic_s32(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_s64_le(_val, _attr...)                _side_arg_dynamic_s64(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_s128_le(_val, _attr...)               _side_arg_dynamic_s128(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_pointer_le(_val, _attr...)            _side_arg_dynamic_pointer(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_float_binary16_le(_val, _attr...)     _side_arg_dynamic_float_binary16(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_float_binary32_le(_val, _attr...)     _side_arg_dynamic_float_binary32(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_float_binary64_le(_val, _attr...)     _side_arg_dynamic_float_binary64(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_float_binary128_le(_val, _attr...)    _side_arg_dynamic_float_binary128(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+#define side_arg_dynamic_u16_le(_val, _attr...)                _side_arg_dynamic_u16(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_u32_le(_val, _attr...)                _side_arg_dynamic_u32(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_u64_le(_val, _attr...)                _side_arg_dynamic_u64(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_u128_le(_val, _attr...)               _side_arg_dynamic_u128(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_s16_le(_val, _attr...)                _side_arg_dynamic_s16(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_s32_le(_val, _attr...)                _side_arg_dynamic_s32(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_s64_le(_val, _attr...)                _side_arg_dynamic_s64(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_s128_le(_val, _attr...)               _side_arg_dynamic_s128(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_pointer_le(_val, _attr...)            _side_arg_dynamic_pointer(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_float_binary16_le(_val, _attr...)     _side_arg_dynamic_float_binary16(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_float_binary32_le(_val, _attr...)     _side_arg_dynamic_float_binary32(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_float_binary64_le(_val, _attr...)     _side_arg_dynamic_float_binary64(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_float_binary128_le(_val, _attr...)    _side_arg_dynamic_float_binary128(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 
 /* Big endian */
-#define side_arg_dynamic_u16_be(_val, _attr...)                _side_arg_dynamic_u16(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_u32_be(_val, _attr...)                _side_arg_dynamic_u32(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_u64_be(_val, _attr...)                _side_arg_dynamic_u64(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_u128_be(_val, _attr...)               _side_arg_dynamic_u128(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_s16_be(_val, _attr...)                _side_arg_dynamic_s16(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_s32_be(_val, _attr...)                _side_arg_dynamic_s32(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_s64_be(_val, _attr...)                _side_arg_dynamic_s64(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_s128_be(_val, _attr...)               _side_arg_dynamic_s128(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_pointer_be(_val, _attr...)            _side_arg_dynamic_pointer(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_float_binary16_be(_val, _attr...)     _side_arg_dynamic_float_binary16(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_float_binary32_be(_val, _attr...)     _side_arg_dynamic_float_binary32(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_float_binary64_be(_val, _attr...)     _side_arg_dynamic_float_binary64(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
-#define side_arg_dynamic_float_binary128_be(_val, _attr...)    _side_arg_dynamic_float_binary128(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+#define side_arg_dynamic_u16_be(_val, _attr...)                _side_arg_dynamic_u16(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_u32_be(_val, _attr...)                _side_arg_dynamic_u32(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_u64_be(_val, _attr...)                _side_arg_dynamic_u64(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_u128_be(_val, _attr...)               _side_arg_dynamic_u128(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_s16_be(_val, _attr...)                _side_arg_dynamic_s16(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_s32_be(_val, _attr...)                _side_arg_dynamic_s32(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_s64_be(_val, _attr...)                _side_arg_dynamic_s64(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_s128_be(_val, _attr...)               _side_arg_dynamic_s128(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_pointer_be(_val, _attr...)            _side_arg_dynamic_pointer(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_float_binary16_be(_val, _attr...)     _side_arg_dynamic_float_binary16(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_float_binary32_be(_val, _attr...)     _side_arg_dynamic_float_binary32(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_float_binary64_be(_val, _attr...)     _side_arg_dynamic_float_binary64(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
+#define side_arg_dynamic_float_binary128_be(_val, _attr...)    _side_arg_dynamic_float_binary128(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 
 #define side_arg_dynamic_vla(_vla) \
        { \
        const struct side_arg _identifier##_vec[] = { _sav }; \
        const struct side_arg_dynamic_vla _identifier = { \
                .sav = SIDE_PTR_INIT(_identifier##_vec), \
-               .attr = SIDE_PTR_INIT(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
+               .attr = SIDE_PTR_INIT(SIDE_CAT2(_side_allocate_dynamic_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
                .len = SIDE_ARRAY_SIZE(_identifier##_vec), \
-               .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
+               .nr_attr = SIDE_ARRAY_SIZE(SIDE_CAT2(_side_allocate_static_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
        }
 
 #define side_arg_dynamic_define_struct(_identifier, _struct_fields, _attr...) \
        const struct side_arg_dynamic_field _identifier##_fields[] = { _struct_fields }; \
        const struct side_arg_dynamic_struct _identifier = { \
                .fields = SIDE_PTR_INIT(_identifier##_fields), \
-               .attr = SIDE_PTR_INIT(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
+               .attr = SIDE_PTR_INIT(SIDE_CAT2(_side_allocate_dynamic_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
                .len = SIDE_ARRAY_SIZE(_identifier##_fields), \
-               .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
+               .nr_attr = SIDE_ARRAY_SIZE(SIDE_CAT2(_side_allocate_static_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
        }
 
 #define side_arg_dynamic_define_struct_visitor(_identifier, _dynamic_struct_visitor, _ctx, _attr...) \
        struct side_arg_dynamic_struct_visitor _identifier = { \
                .visitor = SIDE_PTR_INIT(_dynamic_struct_visitor), \
                .app_ctx = SIDE_PTR_INIT(_ctx), \
-               .attr = SIDE_PTR_INIT(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
+               .attr = SIDE_PTR_INIT(SIDE_CAT2(_side_allocate_dynamic_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
                .cached_arg = SIDE_PTR_INIT(NULL), \
-               .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
+               .nr_attr = SIDE_ARRAY_SIZE(SIDE_CAT2(_side_allocate_static_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
        }
 
 #define side_arg_dynamic_define_vla_visitor(_identifier, _dynamic_vla_visitor, _ctx, _attr...) \
        struct side_arg_dynamic_vla_visitor _identifier = { \
                .visitor = SIDE_PTR_INIT(_dynamic_vla_visitor), \
                .app_ctx = SIDE_PTR_INIT(_ctx), \
-               .attr = SIDE_PTR_INIT(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
+               .attr = SIDE_PTR_INIT(SIDE_CAT2(_side_allocate_dynamic_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
                .cached_arg = SIDE_PTR_INIT(NULL), \
-               .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
+               .nr_attr = SIDE_ARRAY_SIZE(SIDE_CAT2(_side_allocate_static_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
        }
 
 #define side_arg_define_vec(_identifier, _sav) \
                const struct side_arg_dynamic_field side_fields[] = { _var_fields }; \
                const struct side_arg_dynamic_struct var_struct = { \
                        .fields = SIDE_PTR_INIT(side_fields), \
-                       .attr = SIDE_PTR_INIT(_attr), \
+                       .attr = SIDE_PTR_INIT(SIDE_CAT2(_side_allocate_dynamic_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
                        .len = SIDE_ARRAY_SIZE(side_fields), \
-                       .nr_attr = SIDE_ARRAY_SIZE(_attr), \
+                       .nr_attr = SIDE_ARRAY_SIZE(SIDE_CAT2(_side_allocate_static_, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))), \
                }; \
                _call(&(side_event_state__##_identifier.parent), &side_arg_vec, &var_struct); \
        }
 
 #define side_event_call_variadic(_identifier, _sav, _var_fields, _attr...) \
-       _side_event_call_variadic(side_call_variadic, _identifier, SIDE_PARAM(_sav), SIDE_PARAM(_var_fields), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       _side_event_call_variadic(side_call_variadic, _identifier, SIDE_PARAM(_sav), SIDE_PARAM(_var_fields), \
+                                 SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 
 #define side_event_variadic(_identifier, _sav, _var, _attr...) \
-       if (side_event_enabled(_identifier)) \
-               side_event_call_variadic(_identifier, SIDE_PARAM(_sav), SIDE_PARAM(_var), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+       if (side_event_enabled(_identifier))                            \
+               side_event_call_variadic(_identifier, SIDE_PARAM(_sav), SIDE_PARAM(_var), \
+                                        SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_dynamic_attr_list()))
 
 #define _side_statedump_event_call(_call, _identifier, _key, _sav) \
        { \
index 0c078abea875da5b0d587cce56763764a31cf833..84afe285eb2c58b99177aefbe788bb60f7dd259a 100644 (file)
 
 #define SIDE_ARRAY_SIZE(arr)   (sizeof(arr) / sizeof((arr)[0]))
 
+/* Stringify X after expansion. */
+#define SIDE_STR_PRIMITIVE(x...) #x
+#define SIDE_STR(x...) SIDE_STR_PRIMITIVE(x)
+
+/* Concatenate X with Y after expansion. */
+#define SIDE_CAT_PRIMITIVE(x, y...) x ## y
+#define SIDE_CAT(x, y...) SIDE_CAT_PRIMITIVE(x, y)
+
+/* Same as SIDE_CAT, but can expand SIDE_CAT within the expansion itself. */
+#define SIDE_CAT2_PRIMITIVE(x, y...) x ## y
+#define SIDE_CAT2(x, y...) SIDE_CAT2_PRIMITIVE(x, y)
+/*
+ * Define a unique identifier in the compilation unit.
+ */
+#define SIDE_MAKE_ID(prefix)                                   \
+    SIDE_CAT(libside_gensym_, SIDE_CAT(prefix, __COUNTER__))
 /*
  * Compound literals with static storage are needed by SIDE
  * instrumentation.
  */
 #define SIDE_COMPOUND_LITERAL(type, ...)   (type[]) { __VA_ARGS__ }
 
+/*
+ * Dynamic compound literals are used in function scopes, i.e., the storage is
+ * on the stack. C++ does not support them well.
+ *
+ * To overcome this issue, the compound literals is memcpy onto an allocated
+ * buffer on the stack using alloca(3).
+ *
+ * See the following paragraphes taken from GCC documentation for the rationale:
+ *
+ * In C, a compound literal designates an unnamed object with static or
+ * automatic storage duration. In C++, a compound literal designates a temporary
+ * object that only lives until the end of its full-expression. As a result,
+ * well-defined C code that takes the address of a subobject of a compound
+ * literal can be undefined in C++, so G++ rejects the conversion of a temporary
+ * array to a pointer. For instance, if the array compound literal example above
+ * appeared inside a function, any subsequent use of foo in C++ would have
+ * undefined behavior because the lifetime of the array ends after the
+ * declaration of foo.
+ *
+ * As an optimization, G++ sometimes gives array compound literals longer
+ * lifetimes: when the array either appears outside a function or has a
+ * const-qualified type. If foo and its initializer had elements of type char
+ * *const rather than char *, or if foo were a global variable, the array would
+ * have static storage duration. But it is probably safest just to avoid the use
+ * of array compound literals in C++ code.
+ */
+#ifdef __cplusplus
+
+#define SIDE_DYNAMIC_COMPOUND_LITERAL_PRIMITIVE(id, type, ...)         \
+       ({                                                              \
+               size_t SIDE_CAT(id, _size) = sizeof(SIDE_COMPOUND_LITERAL(type, __VA_ARGS__)); \
+               type *id = (type*)__builtin_alloca(SIDE_CAT(id, _size)); \
+               __builtin_memcpy((void*)id, (void*)SIDE_COMPOUND_LITERAL(type, __VA_ARGS__), \
+                               SIDE_CAT(id, _size));                   \
+               id;                                                     \
+       })
+
+#  define SIDE_DYNAMIC_COMPOUND_LITERAL(type, ...)     \
+       SIDE_DYNAMIC_COMPOUND_LITERAL_PRIMITIVE(SIDE_MAKE_ID(dynamic_compound_literal_), \
+                                               type, __VA_ARGS__)
+
+#else
+#  define SIDE_DYNAMIC_COMPOUND_LITERAL SIDE_COMPOUND_LITERAL
+#endif
+
 #define side_likely(x)         __builtin_expect(!!(x), 1)
 #define side_unlikely(x)       __builtin_expect(!!(x), 0)
 
index 493d6e5dc4e375c6236c64e31246bbec0c73ed06..e0df0951cb69305b646ee98ae11c9ae765b725b4 100644 (file)
@@ -734,7 +734,7 @@ void test_variadic_attr(void)
                side_arg_list(
                        side_arg_dynamic_field("a",
                                side_arg_dynamic_u32(55,
-                                       side_attr_list(
+                                       side_dynamic_attr_list(
                                                side_attr("user_attribute_c", side_attr_string("valX")),
                                                side_attr("user_attribute_d", side_attr_u8(55)),
                                        )
@@ -742,7 +742,7 @@ void test_variadic_attr(void)
                        ),
                        side_arg_dynamic_field("b",
                                side_arg_dynamic_s8(-4,
-                                       side_attr_list(
+                                       side_dynamic_attr_list(
                                                side_attr("X", side_attr_u8(1)),
                                                side_attr("Y", side_attr_s8(2)),
                                        )
@@ -763,7 +763,7 @@ void test_variadic_vla_attr(void)
        side_arg_dynamic_define_vec(myvla,
                side_arg_list(
                        side_arg_dynamic_u32(1,
-                               side_attr_list(
+                               side_dynamic_attr_list(
                                        side_attr("Z", side_attr_u8(0)),
                                        side_attr("A", side_attr_u8(123)),
                                )
@@ -771,7 +771,7 @@ void test_variadic_vla_attr(void)
                        side_arg_dynamic_u32(2),
                        side_arg_dynamic_u32(3),
                ),
-               side_attr_list(
+               side_dynamic_attr_list(
                        side_attr("X", side_attr_u8(1)),
                        side_attr("Y", side_attr_u8(2)),
                )
@@ -797,14 +797,14 @@ void test_variadic_struct_attr(void)
                        side_arg_list(
                                side_arg_dynamic_field("a",
                                        side_arg_dynamic_u32(43,
-                                               side_attr_list(
+                                               side_dynamic_attr_list(
                                                        side_attr("A", side_attr_bool(true)),
                                                )
                                        )
                                ),
                                side_arg_dynamic_field("b", side_arg_dynamic_u8(55)),
                        ),
-                       side_attr_list(
+                       side_dynamic_attr_list(
                                side_attr("X", side_attr_u8(1)),
                                side_attr("Y", side_attr_u8(2)),
                        )
This page took 0.035186 seconds and 4 git commands to generate.