3

The MISRA-C++ rule 8-5-2 requires that C++ structures are initialized with the correct braces. I have a structure with unions and I connot find the correct combination of braces to satisfy this rule. I am not sure if my code is incorrect or false positive warning from the static code analyser tool.

This is the structure:

typedef struct XMC_VADC_RESULT_CONFIG
{
    union
    {
       struct
       {
          uint32_t                         : 16;
          uint32_t data_reduction_control  : 4;  /**< Configures the data reduction stages */
          uint32_t post_processing_mode    : 2;  /**< Result data processing mode. Uses @ref  XMC_VADC_DMM_t
                                                      For normal operation select
                                                      XMC_VADC_DMM_t::XMC_VADC_DMM_REDUCTION_MODE
                                                      and data_reduction_control as 0*/
          uint32_t                         : 2;
          uint32_t wait_for_read_mode      : 1;  /**< Allow the conversion only after previous results are read*/
          uint32_t part_of_fifo            : 2;  /**< Make the result register a part of Result FIFO? */
          uint32_t                         : 4;
          uint32_t event_gen_enable        : 1;  /**< Generates an event on availability of new result. */
       };
       uint32_t g_rcr;
    };
} XMC_VADC_RESULT_CONFIG_t;

This is my initialization code:

    const XMC_VADC_RESULT_CONFIG_t resultConfig = 
{
  {
    {
    .data_reduction_control     = 0U,                                                   // No Accumulation
    .post_processing_mode       = static_cast<uint32_t>(XMC_VADC_DMM_REDUCTION_MODE),
    .wait_for_read_mode         = 0U,                                                   // Disabled
    .part_of_fifo               = 0U,                                                   // No FIFO
    .event_gen_enable           = 0U                                                    // Disable Result event
    }
  }
};

I have also tried removing one set of braces, but that didn't help. What is the correct number of braces?

amanning
  • 31
  • 4
  • Note that rule 9-5-1 of MISRA C++:2008 states that unions should not be used at all (_"**(Required)** Unions shall not be used._"); so be aware that this rule needs to be formally deviated from if you want to continue using unions. – dfrib Sep 29 '20 at 06:47
  • Yes, I have seen this. My problem is that the structure definition is in a library provided by the microcontroller manufacture. I have to use this library. In this case it also makes sense to use a union to be able to access the whole register or the individual bits. – amanning Sep 29 '20 at 07:32
  • I assume that MISRA forbids unions because type-punning through unions is generally undefined behaviour in C++ – Caleth Sep 29 '20 at 09:07
  • @amanning Most likely the library assumes non-MISRA C. Not MISRA-C++. Why do you have to use C++? It isn't a suitable language for declaring register maps. – Lundin Sep 29 '20 at 09:19
  • The library is C, but our application is C++, so the initialization is in C++. – amanning Sep 29 '20 at 09:49

2 Answers2

2
  • Correct, compliant brace placement would be const XMC_VADC_RESULT_CONFIG_t resultConfig = { 0u };
  • MISRA-C++ requires C++03 so you can't use anything else.
  • Designated initializers (the .name syntax) is a C thing that only existed from C99 and beyond. They aren't allowed in MISRA-C:2004, but in MISRA-C:2012 (with some special rules). In C++ they have only been introduced recently, in a version of C++ that you are not allowed to use in MISRA compliant applications.
  • union type punning is in general not allowed in any MISRA, particularly not in C++ where it is undefined behavior. A few exceptions to the rule exist in C, but not in C++.
  • The presence of bit-fields in any critical application, MISRA or not, is highly questionable practice since they are so poorly standardized.

Summary: you can't use this code in any form of MISRA application. Drop the union and bit-field both and replace them with bitwise operators and bit masking.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • And yes, this is a huge problem when you get handed a sloppy register map by your sloppy MCU silicon vendor, who's been living underneath a rock (or a QFP?) since 1998 and never wrote a single, professional line of code in the past 20 years. So for strict MISRA compliance you have to roll out a register map of your own, in most cases. I wrote some advise for how to do this here: [How to access a hardware register from firmware?](https://electrical.codidact.com/questions/276290) – Lundin Sep 29 '20 at 09:16
  • If you are lucky, some commercial tool chains may have actual MISRA compliant libraries, but I have yet to encounter one personally. – Lundin Sep 29 '20 at 09:16
  • Our code does not have to be MISRA conpliant, we just use the MISRA settings in the static code analyser to catch as many bugs as possible. – amanning Sep 29 '20 at 09:54
  • @amanning Ok congrats then, you found one. C++ doesn't allow union type punning (unlike C) so you can't use this register map in C++. – Lundin Sep 29 '20 at 10:05
0

C++ doesn't have designated initializers until C++20, so you will have drop those.

const XMC_VADC_RESULT_CONFIG_t resultConfig = 
{
  {
    {
      0U,                                                   // No Accumulation
      static_cast<uint32_t>(XMC_VADC_DMM_REDUCTION_MODE),
      0U,                                                   // Disabled
      0U,                                                   // No FIFO
      0U                                                    // Disable Result event
    }
  }
};
Caleth
  • 52,200
  • 2
  • 44
  • 75
  • Our Clang compiler is set to C++14, but it accepts designated initializers, which I find very good as it makes reading the code much easier, you can see what is being initialized without having to add any comments. – amanning Sep 29 '20 at 09:57