Make it compatible with C++
authorOlivier Dion <odion@efficios.com>
Mon, 19 Aug 2024 17:35:41 +0000 (13:35 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 23 Oct 2024 15:29:36 +0000 (11:29 -0400)
The main change are for initialization order of compound literal.  Other
changes include:

  - Initialization of zero size member (char end [0]),

  - Declaration of events in anonymous namespace for circular dependency
    of static variables.

Change-Id: Icb99c22a7df313ecb0e31a8d96ea6e9ec00cffed
Signed-off-by: Olivier Dion <odion@efficios.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
configure.ac
include/side/abi/type-description.h
include/side/abi/visitor.h
include/side/instrumentation-c-api.h
include/side/macros.h

index 6142c90d39e071d4c6c967bf499b42826fe59225..2af34dd3c209746a991f185e8b9877617efd3a23 100644 (file)
@@ -122,8 +122,12 @@ AE_IF_FEATURE_ENABLED([Werror], [WARN_CXXFLAGS="${WARN_CXXFLAGS} -Werror"])
 ## C++ compiler checks ##
 ##                     ##
 
-# Require a C++11 compiler without GNU extensions (-std=c++11)
-AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory])
+# Require a C++11 compiler with GNU extensions (-std=gnu++11).
+#
+# A compiler with GNU extensions is mandatory because of the usage of
+# preprocessor `##' comma deletion with empty `__VA_ARGS__' in the public header
+# files.
+AX_CXX_COMPILE_STDCXX([11], [ext], [mandatory])
 
 
 ##               ##
index 66ac9f4d58a92860afbaadf742794752930ab769..60868570c5835fd79701b7867d0beb8a5a70494d 100644 (file)
@@ -154,10 +154,6 @@ enum side_type_label {
        _NR_SIDE_TYPE_LABEL,    /* Last entry. */
 };
 
-enum side_visitor_status {
-       SIDE_VISITOR_STATUS_OK = 0,
-       SIDE_VISITOR_STATUS_ERROR = -1,
-};
 
 enum side_type_gather_access_mode {
        SIDE_TYPE_GATHER_ACCESS_DIRECT,
index a0ce76e2271be1c998935d029bdee3495b247ee6..88d442609ae0140680b4a2f9267e5a22163707ed 100644 (file)
@@ -28,6 +28,11 @@ struct side_arg_dynamic_field;
 struct side_tracer_visitor_ctx;
 struct side_tracer_dynamic_struct_visitor_ctx;
 
+enum side_visitor_status {
+       SIDE_VISITOR_STATUS_OK = 0,
+       SIDE_VISITOR_STATUS_ERROR = -1,
+};
+
 typedef enum side_visitor_status (*side_write_elem_func)(
                const struct side_tracer_visitor_ctx *tracer_ctx,
                const struct side_arg *elem);
index f57a44a2d8bf36f17213aea38456d0e2218aa4a3..6f4ab0613d13a541097036d6b69a2f2f8de483ca 100644 (file)
 #define side_type_dynamic() \
        { \
                .type = SIDE_ENUM_INIT(SIDE_TYPE_DYNAMIC), \
+               .u = { }                                   \
        }
 
 #define _side_type_integer(_type, _signedness, _byte_order, _integer_size, _len_bits, _attr) \
 #define side_field_variant(_name, _variant) \
        _side_field(_name, side_type_variant(SIDE_PARAM(_variant)))
 
-#define _side_type_variant_define(_selector, _options, _attr) \
-       { \
-               .selector = _selector, \
-               .options = SIDE_PTR_INIT(_options), \
-               .attr = SIDE_PTR_INIT(_attr), \
+#define _side_type_variant_define(_selector, _options, _attr)       \
+       {                                                            \
+               .options = SIDE_PTR_INIT(_options),                  \
+               .attr = SIDE_PTR_INIT(_attr),                        \
                .nr_options = SIDE_ARRAY_SIZE(SIDE_PARAM(_options)), \
-               .nr_attr  = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
+               .nr_attr  = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)),      \
+               .selector = _selector,                               \
        }
 
 #define side_define_variant(_identifier, _selector, _options, _attr...) \
                                .u = { \
                                        .side_bool = { \
                                                .offset = _offset, \
+                                               .offset_bits = _offset_bits, \
                                                .access_mode = SIDE_ENUM_INIT(_access_mode), \
                                                .type = { \
                                                        .attr = SIDE_PTR_INIT(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
                                                        .len_bits = _len_bits, \
                                                        .byte_order = SIDE_ENUM_INIT(_byte_order), \
                                                }, \
-                                               .offset_bits = _offset_bits, \
                                        }, \
                                }, \
                        }, \
                                .u = { \
                                        .side_integer = { \
                                                .offset = _offset, \
+                                               .offset_bits = _offset_bits, \
                                                .access_mode = SIDE_ENUM_INIT(_access_mode), \
                                                .type = { \
                                                        .attr = SIDE_PTR_INIT(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
                                                        .signedness = _signedness, \
                                                        .byte_order = SIDE_ENUM_INIT(_byte_order), \
                                                }, \
-                                               .offset_bits = _offset_bits, \
                                        }, \
                                }, \
                        }, \
                        .side_gather = { \
                                .u = { \
                                        .side_struct = { \
+                                               .type = SIDE_PTR_INIT(_struct_gather), \
                                                .offset = _offset, \
                                                .access_mode = SIDE_ENUM_INIT(_access_mode), \
-                                               .type = SIDE_PTR_INIT(_struct_gather), \
                                                .size = _size, \
                                        }, \
                                }, \
 
 /* Stack-copy field arguments */
 
-#define side_arg_null(_val)            { .type = SIDE_ENUM_INIT(SIDE_TYPE_NULL), .flags = 0, }
+#define side_arg_null(_val)            { .type = SIDE_ENUM_INIT(SIDE_TYPE_NULL), .flags = 0, .u = { .side_static = {  } } }
 #define side_arg_bool(_val)            { .type = SIDE_ENUM_INIT(SIDE_TYPE_BOOL), .flags = 0, .u = { .side_static = { .bool_value = { .side_bool8 = !!(_val) } } } }
 #define side_arg_byte(_val)            { .type = SIDE_ENUM_INIT(SIDE_TYPE_BYTE), .flags = 0, .u = { .side_static = { .byte_value = (_val) } } }
 #define side_arg_string(_val)          { .type = SIDE_ENUM_INIT(SIDE_TYPE_STRING_UTF8), .flags = 0, .u = { .side_static = { .string_value = SIDE_PTR_INIT(_val) } } }
 #define side_statedump_event_call_variadic(_identifier, _key, _sav, _var_fields, _attr...) \
        _side_statedump_event_call_variadic(side_statedump_call_variadic, _identifier, _key, SIDE_PARAM(_sav), SIDE_PARAM(_var_fields), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
 
-#define _side_define_event(_linkage, _identifier, _provider, _event, _loglevel, _fields, _flags, _attr...) \
-       _linkage struct side_event_description __attribute__((section("side_event_description"))) \
-                       _identifier; \
+
+/*
+ * The forward declaration linkage is always the same in C. In C++ however, it
+ * is necessary to not use the same linkage as the declaration.
+ */
+#define _side_define_event(_forward_decl_linkage, _linkage, _identifier, _provider, _event, _loglevel, _fields, _flags, _attr...) \
+       _forward_decl_linkage struct side_event_description __attribute__((section("side_event_description"))) \
+               _identifier;                                                    \
+       _forward_decl_linkage struct side_event_state_0 __attribute__((section("side_event_state"))) \
+               side_event_state__##_identifier;                                \
        _linkage struct side_event_state_0 __attribute__((section("side_event_state"))) \
-                       side_event_state__##_identifier = { \
-               .parent = { \
-                       .version = SIDE_EVENT_STATE_ABI_VERSION, \
-               }, \
-               .nr_callbacks = 0, \
-               .enabled = 0, \
+               side_event_state__##_identifier = {                     \
+               .parent = {                                             \
+                       .version = SIDE_EVENT_STATE_ABI_VERSION,        \
+               },                                                      \
+               .nr_callbacks = 0,                                      \
+               .enabled = 0,                                           \
                .callbacks = (const struct side_callback *) &side_empty_callback[0], \
-               .desc = &(_identifier), \
-       }; \
+               .desc = &(_identifier),                                 \
+       };                                                              \
        _linkage struct side_event_description __attribute__((section("side_event_description"))) \
-                       _identifier = { \
+               _identifier = {                                         \
                .struct_size = offsetof(struct side_event_description, end), \
-               .version = SIDE_EVENT_DESCRIPTION_ABI_VERSION, \
+               .version = SIDE_EVENT_DESCRIPTION_ABI_VERSION,          \
                .state = SIDE_PTR_INIT(&(side_event_state__##_identifier.parent)), \
-               .provider_name = SIDE_PTR_INIT(_provider), \
-               .event_name = SIDE_PTR_INIT(_event), \
-               .fields = SIDE_PTR_INIT(_fields), \
+               .provider_name = SIDE_PTR_INIT(_provider),              \
+               .event_name = SIDE_PTR_INIT(_event),                    \
+               .fields = SIDE_PTR_INIT(_fields),                       \
                .attr = SIDE_PTR_INIT(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
-               .flags = (_flags), \
-               .nr_side_type_label = _NR_SIDE_TYPE_LABEL, \
-               .nr_side_attr_type = _NR_SIDE_ATTR_TYPE, \
-               .loglevel = SIDE_ENUM_INIT(_loglevel), \
-               .nr_fields = SIDE_ARRAY_SIZE(SIDE_PARAM(_fields)), \
+               .flags = (_flags),                                      \
+               .nr_side_type_label = _NR_SIDE_TYPE_LABEL,              \
+               .nr_side_attr_type = _NR_SIDE_ATTR_TYPE,                \
+               .loglevel = SIDE_ENUM_INIT(_loglevel),                  \
+               .nr_fields = SIDE_ARRAY_SIZE(SIDE_PARAM(_fields)),      \
                .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
-       }; \
-       static const struct side_event_description *side_event_ptr__##_identifier \
-               __attribute__((section("side_event_description_ptr"), used)) = &(_identifier);
+               .end = {}                                               \
+       };                                                              \
+       static const struct side_event_description __attribute__((section("side_event_description_ptr"), used)) \
+                       *side_event_ptr__##_identifier = &(_identifier)
+
+/*
+ * In C++, it is not possible to forward declare a static variable.  Use
+ * anonymous namespace with external linkage instead.
+ */
+#ifdef __cplusplus
+#define _side_cxx_define_event(_namespace, _linkage, _identifier, _provider, _event, _loglevel, _fields, _flags, _attr...) \
+       _namespace {                                                    \
+               _side_define_event(extern, _linkage, _identifier, _provider, _event, _loglevel, \
+                               SIDE_PARAM(_fields), _flags, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())); \
+       }
+
+#define side_static_event(_identifier, _provider, _event, _loglevel, _fields, _attr...) \
+       _side_cxx_define_event(namespace, , _identifier, _provider, _event, _loglevel, SIDE_PARAM(_fields), \
+                       0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+
+#define side_static_event_variadic(_identifier, _provider, _event, _loglevel, _fields, _attr...) \
+       _side_cxx_define_event(namespace, , _identifier, _provider, _event, _loglevel, SIDE_PARAM(_fields), \
+                       SIDE_EVENT_FLAG_VARIADIC, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+
+#define side_hidden_event(_identifier, _provider, _event, _loglevel, _fields, _attr...) \
+       _side_cxx_define_event(extern "C", __attribute__((visibility("hidden"))), _identifier, _provider, _event, \
+                       _loglevel, SIDE_PARAM(_fields), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+
+#define side_hidden_event_variadic(_identifier, _provider, _event, _loglevel, _fields, _attr...) \
+       _side_cxx_define_event(extern "C", __attribute__((visibility("hidden"))), _identifier, _provider, _event, \
+                       _loglevel, SIDE_PARAM(_fields), SIDE_EVENT_FLAG_VARIADIC, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+
+#define side_export_event(_identifier, _provider, _event, _loglevel, _fields, _attr...) \
+       _side_cxx_define_event(extern "C", __attribute__((visibility("default"))), _identifier, _provider, _event, \
+                       _loglevel, SIDE_PARAM(_fields), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+
+#define side_export_event_variadic(_identifier, _provider, _event, _loglevel, _fields, _attr...) \
+       _side_cxx_define_event(extern "C", __attribute__((visibility("default"))), _identifier, _provider, _event, \
+                       _loglevel, SIDE_PARAM(_fields), SIDE_EVENT_FLAG_VARIADIC, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+
+#define side_declare_event(_identifier)                                        \
+       extern "C" struct side_event_description _identifier;           \
+       extern "C" struct side_event_state_0 side_event_state_##_identifier
+#else
+
 
 #define side_static_event(_identifier, _provider, _event, _loglevel, _fields, _attr...) \
-       _side_define_event(static, _identifier, _provider, _event, _loglevel, SIDE_PARAM(_fields), \
-                       0, ##_attr)
+       _side_define_event(static, static, _identifier, _provider, _event, _loglevel, SIDE_PARAM(_fields), \
+                       0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
 
 #define side_static_event_variadic(_identifier, _provider, _event, _loglevel, _fields, _attr...) \
-       _side_define_event(static, _identifier, _provider, _event, _loglevel, SIDE_PARAM(_fields), \
+       _side_define_event(static, static, _identifier, _provider, _event, _loglevel, SIDE_PARAM(_fields), \
                        SIDE_EVENT_FLAG_VARIADIC, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
 
 #define side_hidden_event(_identifier, _provider, _event, _loglevel, _fields, _attr...) \
-       _side_define_event(__attribute__((visibility("hidden"))), _identifier, _provider, _event, \
+       _side_define_event(__attribute__((visibility("hidden"))), __attribute__((visibility("hidden"))), \
+                          _identifier, _provider, _event,              \
                        _loglevel, SIDE_PARAM(_fields), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
 
 #define side_hidden_event_variadic(_identifier, _provider, _event, _loglevel, _fields, _attr...) \
-       _side_define_event(__attribute__((visibility("hidden"))), _identifier, _provider, _event, \
+       _side_define_event(__attribute__((visibility("hidden"))), __attribute__((visibility("hidden"))), \
+                          _identifier, _provider, _event,              \
                        _loglevel, SIDE_PARAM(_fields), SIDE_EVENT_FLAG_VARIADIC, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
 
 #define side_export_event(_identifier, _provider, _event, _loglevel, _fields, _attr...) \
-       _side_define_event(__attribute__((visibility("default"))), _identifier, _provider, _event, \
+       _side_define_event(__attribute__((visibility("default"))), __attribute__((visibility("default"))), \
+                          _identifier, _provider, _event,              \
                        _loglevel, SIDE_PARAM(_fields), 0, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
 
 #define side_export_event_variadic(_identifier, _provider, _event, _loglevel, _fields, _attr...) \
-       _side_define_event(__attribute__((visibility("default"))), _identifier, _provider, _event, \
+       _side_define_event(__attribute__((visibility("default"))), __attribute__((visibility("default"))), \
+                          _identifier, _provider, _event,              \
                        _loglevel, SIDE_PARAM(_fields), SIDE_EVENT_FLAG_VARIADIC, SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
 
 #define side_declare_event(_identifier) \
        extern struct side_event_state_0 side_event_state_##_identifier; \
        extern struct side_event_description _identifier
+#endif /* __cplusplus */
 
 #endif /* SIDE_INSTRUMENTATION_C_API_H */
index e23dcae1aacd523f3350007c210447eb31acea9f..0c078abea875da5b0d587cce56763764a31cf833 100644 (file)
 #define side_ptr_t(_type)      side_raw_ptr_t(_type *)
 #define side_func_ptr_t(_type) side_raw_ptr_t(_type)
 
+/*
+ * In C++, it is not possible to declare types in expressions within a sizeof.
+ */
+#ifdef __cplusplus
+namespace side {
+       namespace macros {
+               using side_ptr_t_int = side_ptr_t(int);
+               side_static_assert(sizeof(side_ptr_t_int) == 16,
+                               "Unexpected size for side_ptr_t",
+                               unexpected_size_side_ptr_t);
+       };
+};
+#else
 side_static_assert(sizeof(side_ptr_t(int)) == 16,
        "Unexpected size for side_ptr_t",
        unexpected_size_side_ptr_t);
+#endif
 
 /*
  * side_enum_t allows defining fixed-sized enumerations while preserving
This page took 0.029392 seconds and 4 git commands to generate.