khouri - 2021-03-26

When unleashing cppcheck on third party sources today of an embedded application, I encountered an issue with the use of unions in this code. The code below is an isolated, simplified example of what is happening.

// cppcheck_union_error.c
#include <stdio.h>

typedef struct {
   unsigned short msword_16;
   unsigned short lsword_16;
} TWO_SHORTS;

typedef struct {
  union {
     TWO_SHORTS     two_shorts;
     unsigned int   word_32;
  } u;
} WORDX_TYPE;


int main(void)
{
    volatile unsigned int    *reg;
    unsigned int   fake_reg;
    WORDX_TYPE     wordx;

    reg = &fake_reg;

    wordx.u.two_shorts.msword_16 = (1 << 5);
    wordx.u.two_shorts.lsword_16 = (1 << 4);
    *reg = wordx.u.word_32;
    printf("0x%08x\n", *reg);                // <== uninitialised var warning

    wordx.u.two_shorts.msword_16 = (1 << 3); // <== redundant assignment warning
    wordx.u.two_shorts.lsword_16 = (1 << 2); // <== redundant assignment warning
    *reg = wordx.u.word_32;
    printf("0x%08x\n", *reg);                // <== uninitialised var warning

    return 0;
}

Program Output:

0x00100020
0x00040008

Running cppcheck v2.3 on these sources:
cppcheck --enable=all cppcheck_union_error.c

This yields a number of incorrect redundantAssignment warnings on the second time the wordx.u.two_shorts members of the union are written. Cppcheck seems to miss that the union members (two shorts and the 32-bit integer) overlap.

Additionally, the printf statements yield an incorrect uninitvar warning.