Search code examples
cenumsmisraerror-checking

Why does an anonymous enum fails MISRA C 2012 rule 10.3 and a named enum doesn't?


In question:

Why do I have to cast an enum element when assigning it to a same enum variable type in C?

I was having problems with this code for failing the MISRA C 2012 rule 10.3 that states:

The value of an expression shall not be assigned to an object with a narrower essential type or of a different essential type category

The code is this:

typedef enum
{
   FLS_PROG_SUCCESS,
   FLS_PROG_FAIL,
   FLS_ERASE_SUCCESS2U,
   FLS_ERASE_FAIL,
   FLS_READ_SUCCESS,
   FLS_READ_FAIL,
   FLS_FORMAT_SUCCESS,
   FLS_FORMAT_FAIL
}FLS_JobResult_t;

void Foo(void)
{
   FLS_JobResult_t ProgramStatus;

   /* Then I try to initialize the variable value */
   ProgramStatus = FLS_PROG_SUCCESS;

   ...
}

And I accepted an answer that suggest that the tool may be flawed. I still do believe that but fooling around trying to fix that I put a name to the typedef enum declaration which now is:

typedef enum FLS_JobResult_tag
{
   FLS_PROG_SUCCESS,
   FLS_PROG_FAIL,
   FLS_ERASE_SUCCESS2U,
   FLS_ERASE_FAIL,
   FLS_READ_SUCCESS,
   FLS_READ_FAIL,
   FLS_FORMAT_SUCCESS,
   FLS_FORMAT_FAIL
}FLS_JobResult_t;

And as far as I know both are exactly the same. But then, surprise! The error went away! The rules checker is no longer flagging that as an error!!

Then doing some research I found this two questions:

What are the differences between these two typedef styles in C?

and

What's the difference between these two enum declarations - C?

And I realized that there are subtle differences between an anonymous enum and a named enum. But nothing that makes clear what could be the reason for the rule checker to complaint about one form of the other.

So the question is: What is the difference from an anonymous enum vs named enum that may break rule 10.3 from MISRA c 2012?


Solution

  • Both examples are compliant, and both for the same reasons: they are not assigning an object of a different essential type.

    Let's clear up the confusion.

    C grants developers/compilers a lot of freedom in its type system, but it also can lead to unintended results, with the potential for loss of value, sign or precision. MISRA-C:2012 helps enforce safer typing with its essential type model, which provides the rational basis for its rule definitions in controlling the use of type conversions and promoting awareness of implementation specific behavior (the 10.x Rules).

    The essential type model replaces the MISRA-C:2004 standard’s “underlying type” model (which caused a lot of programmer grief enforcing unnecessary casts for one reason).

    I suspect your tool is confused, and/or partially stuck with the older model.

    The essential type rules that pertain to enumerations recognizes two different programming uses:

    1. an object of an enum type intended to be distinct from an object with a different enum type.
    2. enums are a common way of holding a set of integer constants.

    The C standard does not give a way of distinguishing between these uses. Therefore MISRA-C:2012 added the following distinct essential types of enumeration (while not affecting C behavior):

    1. Named enum type - enumeration defined in this is identified either by a tag or a typedef or used in the definition of any object, function or type; A cast must be used if the integer value of the enumeration constant is required.
    2. Anonymous enum type - an enumeration which is not used in the definition of any object, function or type. This will typically be used to define a set of constants, which may or may not be related, but avoids the need for casting.

    An example of an anonymous enum type:

    enum {D = 10, E = 20, F = 30};
    

    Both your examples are named enum types (and they are compliant because they are the same essential type). Other examples are:

    enum JOHN {A, B, C};
    enum PAUL {E, F, G} PAUL;
    

    Thus, an example of a real 10.3 violation would be:

    enum PAUL bar = B;
    

    Reference: MISRA-C:2012 Appendix D.5 "The essential type of enumerations” amplifies this very well with other examples.