zephyrproject-rtos / zephyr

Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
https://docs.zephyrproject.org
Apache License 2.0
9.99k stars 6.15k forks source link

Witnessing -Wc99-designator with xt-clang (clang-10) with enabling -Wall, -Werror #64754

Open aisri opened 8 months ago

aisri commented 8 months ago

Introduction

Extension to the discussion filed here: https://github.com/zephyrproject-rtos/zephyr/issues/33549

Problem description

The following MACROs to init a struct are mixing designated and non-designated initializers. Note, the initialization of {.obj = _event_obj}

This triggers -Wc99-designator error.

#define K_POLL_EVENT_INITIALIZER(_event_type, _event_mode, _event_obj) \
    { \
    .poller = NULL, \
    .type = _event_type, \
    .state = K_POLL_STATE_NOT_READY, \
    .mode = _event_mode, \
    .unused = 0, \
    { \
        .obj = _event_obj, \
    }, \
    }

#define K_POLL_EVENT_STATIC_INITIALIZER(_event_type, _event_mode, _event_obj, \
                    event_tag) \
    { \
    .tag = event_tag, \
    .type = _event_type, \
    .state = K_POLL_STATE_NOT_READY, \
    .mode = _event_mode, \
    .unused = 0, \
    { \
        .obj = _event_obj, \
    }, \
    }

Proposed change

The error can be fixed up by explicitly introducing a concrete variable for anonymous union and initialize with designated initializer

Detailed RFC

With this the union in new struct k_poll_event can now be

struct k_poll_event {
// ignoring other variables ...... 

    /** per-type data */
    union {
        void *obj;
        struct k_poll_signal *signal;
        struct k_sem *sem;
        struct k_fifo *fifo;
        struct k_queue *queue;
        struct k_msgq *msgq;
#ifdef CONFIG_PIPES
        struct k_pipe *pipe;
#endif
    } k_obj;
};

So the macros will now be:

#define K_POLL_EVENT_INITIALIZER(_event_type, _event_mode, _event_obj) \
    { \
    .poller = NULL, \
    .type = _event_type, \
    .state = K_POLL_STATE_NOT_READY, \
    .mode = _event_mode, \
    .unused = 0, \
    .k_obj = { \
        .obj = _event_obj, \
    }, \
    }

#define K_POLL_EVENT_STATIC_INITIALIZER(_event_type, _event_mode, _event_obj, \
                    event_tag) \
    { \
    .tag = event_tag, \
    .type = _event_type, \
    .state = K_POLL_STATE_NOT_READY, \
    .mode = _event_mode, \
    .unused = 0, \
    .k_obj = { \
        .obj = _event_obj, \
    }, \
    }

Dependencies

None

Concerns and Unresolved Questions

Alternatives

Directly initialize anonymous .obj variable. c99 allows this way since, the nest .obj is unique in global struct k_poll_event struct.

mkaranki commented 2 months ago

With GCC 11.3.0 and -std=c++20 this error occurs:

.../include/zephyr/kernel.h:5707:9: error: either all initializer clauses should be designated or none of them should be
 5707 |         { \
      |         ^
...file.cpp:325:9: note: in expansion of macro ‘K_POLL_EVENT_STATIC_INITIALIZER’
  325 |         K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_MSGQ_DATA_AVAILABLE, K_POLL_MODE_NOTIFY_ONLY,

Code example:

void does_not_compile()
{
    struct k_poll_event events[] = {
        K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_MSGQ_DATA_AVAILABLE, K_POLL_MODE_NOTIFY_ONLY,
                                        nullptr, 0),
    };
}

And the error is valid, since C++ does not allow mixing the initializes.

For C++, using __cplusplus #define to strip the extra brackets out could do it. But that would not be a fix for clang -Wc99-designator error. Is there some xt-xcc define which could be utilized instead?