title: Is there a MISRA-compliant way to use enum flags in C99?
body: <p>I have a project I'm developing in C99 and I'm trying to make it compliant with the MISRA 2012 standard.</p>
  
  <p>In one file I define an enum where each value should be treated as a flag:</p>
  
  <pre><code>/**
   * Enumerates the configurable options for performing calibration.
   */
  typedef enum
  {
    CALIBRATION_DEFAULT_OPTIONS=0,  /**&lt; Calibrate with default options */
    CALIBRATION_RESET_POSITION=1,   /**&lt; Ensure window is fully open and motor re-homed */
    CALIBRATION_FORCE_RECALIBRATE=2 /**&lt; Force recalibration even if calibration data exists */
  } CALIBRATION_OPTIONS_T;
  </code></pre>
  
  <p>I'd like to be able to declare something like:</p>
  
  <pre><code>CALIBRATION_OPTIONS_T options = CALIBRATION_RESET_POSITION | CALIBRATION_FORCE_RECALIBRATE;
  </code></pre>
  
  <p>I also define one function that accepts a <code>CALIBRATION_OPTIONS_T</code> parameter and performs different logic depending on which flags are set:</p>
  
  <pre><code>// If forced to recalibrate, do so regardless of whether metrics exist in
  // EEPROM or not.
  if ((options &amp; CALIBRATION_FORCE_RECALIBRATE) != 0U)
  {
    MOTION_ResetCalibrationData();
    calibration = performCalibrationRoutine();
  }
  
  // Otherwise try fetching existing metrics from EEPROM. If they exist, return
  // these metrics.
  else if (tryFetchStoredMetrics(&amp;calibration))
  {
    if ((options &amp; CALIBRATION_RESET_POSITION) != 0U)
    {
      calibration.lastPosition = 0;
      resetMotorPosition();
      storeMetrics(calibration);
    }
  }
  </code></pre>
  
  <p>However, when I lint my project with PC-lint Plus I get the following output explaining that this code violates MISRA 2012 Rule 10.1:</p>
  
  <pre><code>  if ((options &amp; CALIBRATION_FORCE_RECALIBRATE) != 0U)
         ~~~~~~~ ^
  *** LINT: src\c\motionCalibrator.c(645) note 9027: an enum value is not an appropriate left operand to &amp; [MISRA 2012 Rule 10.1, required]
  
    if ((options &amp; CALIBRATION_FORCE_RECALIBRATE) != 0U)
                 ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *** LINT: src\c\motionCalibrator.c(645) note 9027: an enum value is not an appropriate right operand to &amp; [MISRA 2012 Rule 10.1, required]
  
    if ((options &amp; CALIBRATION_FORCE_RECALIBRATE) != 0U)
         ^
  *** LINT: src\c\motionCalibrator.c(645) warning 641: implicit conversion of enum 'CALIBRATION_OPTIONS_T' to integral type 'unsigned int'
  
      if ((options &amp; CALIBRATION_RESET_POSITION) != 0U)
           ~~~~~~~ ^
  *** LINT: src\c\motionCalibrator.c(655) note 9027: an enum value is not an appropriate left operand to &amp; [MISRA 2012 Rule 10.1, required]
  
      if ((options &amp; CALIBRATION_RESET_POSITION) != 0U)
                   ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~
  *** LINT: src\c\motionCalibrator.c(655) note 9027: an enum value is not an appropriate right operand to &amp; [MISRA 2012 Rule 10.1, required]
  
      if ((options &amp; CALIBRATION_RESET_POSITION) != 0U)
           ^
  *** LINT: src\c\motionCalibrator.c(655) warning 641: implicit conversion of enum 'CALIBRATION_OPTIONS_T' to integral type 'unsigned int'
  </code></pre>
  
  <p>In particular, the MISRA 2012 standard advises against using <code>&amp;</code> with enums for these two reasons:</p>
  
  <blockquote>
    <ol start="5">
    <li><p>An operand of essentially enum type should not be used in an
    arithmetic operation because an enum object uses an
    implementation-defined integer type.  An operation  involving an enum
    object may therefore yield a result with an unexpected type. Note that
    an enumeration constant from an anonymous enum has essentially signed
    type.</p></li>
    <li><p>Shift and bitwise operations should only be performed on operands of
    essentially unsigned type. The numeric value resulting from their use
    on essentially signed types is implementation-defined.</p></li>
    </ol>
  </blockquote>
  
  <p>I'd like to know if there's a MISRA-compliant way I can use flag-like enums and test that specific flags are set.</p>