This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler/MSP430FR5994: Compiler flag --enum_type and attribute(packed) are ignored in C++

Part Number: MSP430FR5994

Tool/software: TI C/C++ Compiler

I compiled the program below with the compiler option --enum_type=unpacked, --enum_type=packed and --enum_type=int.

But the size of enum_class with the compiler option --enum_type=packed is 2 bytes instead of 1 byte as expected.

In the same way, the size of enum_class_attribute_packed is always 2 bytes instead of 1 byte.

The size of enum_class_unsigned_char is always 1 byte as expected. But in this case I have a problem with the operator static_cast<enum>(int). See details here:

https://e2e.ti.com/support/tools/ccs/f/81/t/746141

Then how can I make to have an "enum class" with a size of 1 byte ?


#include <stdio.h>
#include <msp430.h>

/**
 * hello.cpp
 */

enum class enum_class { red, green, blue };
enum class enum_class_attribute_packed { red, green, blue } __attribute__((__packed__));
enum class enum_class_unsigned_char: unsigned char { red, green, blue };

int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;    // stop watchdog timer

    printf("sizeof(enum_class) = %d\r\n", sizeof(enum_class));
    printf("sizeof(enum_class_attribute_packed) = %d\r\n", sizeof(enum_class_attribute_packed));
    printf("sizeof(enum_class_unsigned_char) = %d\r\n", sizeof(enum_class_unsigned_char));

    return 0;
}

/*
--enum_type=unpacked

Console:

sizeof(enum_class) = 2
sizeof(enum_class_attribute_packed) = 2
sizeof(enum_class_unsigned_char) = 1
*/

/*
--enum_type=packed

Console:

sizeof(enum_class) = 2
sizeof(enum_class_attribute_packed) = 2
sizeof(enum_class_unsigned_char) = 1
*/

/*
--enum_type=int

Console:

sizeof(enum_class) = 2
sizeof(enum_class_attribute_packed) = 2
sizeof(enum_class_unsigned_char) = 1
*/

/*
Compiler version: TI v18.1.4.LTS

Compiler flags:

-vmspx
--data_model=restricted
--use_hw_mpy=F5
--include_path="${CCS_BASE_ROOT}/msp430/include"
--include_path="${PROJECT_ROOT}"
--include_path="${CG_TOOL_ROOT}/include"
--advice:power="1,2,3,4,5.1,5.2,6,7,8,9,10,11,12,13,14,15"
--advice:hw_config=all
--define=__MSP430FR5994__
--define=_MPU_ENABLE
-g
--printf_support=minimal
--diag_warning=225
--diag_wrap=off
--display_error_number
--enum_type=unpacked
--silicon_errata=CPU21
--silicon_errata=CPU22
--silicon_errata=CPU40
*/

/*
Linker flags:

-m"${ProjName}.map"
--heap_size=300
--stack_size=160
--cinit_hold_wdt=on
-i"${CCS_BASE_ROOT}/msp430/include"
-i"${CCS_BASE_ROOT}/msp430/lib/5xx_6xx_FRxx"
-i"${CCS_BASE_ROOT}/msp430/lib/FR59xx"
-i"${CG_TOOL_ROOT}/lib"
-i"${CG_TOOL_ROOT}/include"
--priority
--reread_libs
--define=_MPU_ENABLE
--diag_wrap=off
--display_error_number
--warn_sections
--xml_link_info="${ProjName}_linkInfo.xml"
--use_hw_mpy=F5
--rom_model
*/

  • The attribute packed is not supported for C++ scoped enum types (which use the enum class syntax).  While the compiler is not required to issue a diagnostic in this case, it would be good to let the user know.  So, I filed CODEGEN-5547 in the SDOWP system not to report a bug, but to request that the compiler be changed to issue a diagnostic whenever __attribute__((__packed__)) is applied to a enum class type.You are welcome to follow it with the SDOWP link below in my signature.

    Thanks and regards,

    -George

  • Thank you, it is a good idea to issue a diagnostic when __attribute__((__packed__)) is not supported.

    Do you have any news about the compiler flag --enum_type=packed that doesn't work ?

    /*

    --enum_type=packed

    Console:

    sizeof(enum_class) = 2

    sizeof(enum_class_attribute_packed) = 2

    sizeof(enum_class_unsigned_char) = 1

    */

    Best regards.

  • user435003 said:
    Do you have any news about the compiler flag --enum_type=packed that doesn't work ?

    The command line option --enum_type does not affect scoped enum types (written enum class user_defined_name), only the older style un-scoped enum types (written enum  user_defined_name).

    Thanks and regards,

    -George

  • Hi,

    I have a question regarding your post here. How did you read out the sizeof value? I have been trying and searching on google and e2e forums, but I could not find any answer.

    I do not have a target processor available at this time, but would need to know the details around how enums are packed in different scenarios. Of course I could study the post link map file, but I feel there should be an easier way to do this.


    Best regards,
    Johan
  • I used static_assert() and printf(), see below.

    Best regards.


    /*
     * enum_class.hpp
     */
    #ifndef ENUM_CLASS_HPP_
    #define ENUM_CLASS_HPP_
    #include <cstdint>
    
    enum       enum_                           {D, E, F};
    enum       enum_packed                     {G, H, I} __attribute__((packed));
    enum class enum_class                      {W, X, Y};
    enum class enum_class_packed               {W, X, Y} __attribute__((packed));
    
    enum       enum_u8              : uint8_t  {J, K, L};
    enum       enum_packed_u8       : uint8_t  {M, O, P} __attribute__((packed));
    enum class enum_class_u8        : uint8_t  {W, X, Y};
    enum class enum_class_packed_u8 : uint8_t  {W, X, Y} __attribute__((packed));
    
    enum       enum_u16             : uint16_t {Q, R, S};
    enum       enum_packed_u16      : uint16_t {T, U, A} __attribute__((packed));
    enum class enum_class_u16       : uint16_t {W, X, Y};
    enum class enum_class_packed_u16: uint16_t {W, X, Y} __attribute__((packed));
    
    static_assert(sizeof(enum_) == 1, "");      // With --enum_type=packed
    static_assert(sizeof(enum_) == 2, "");      // With --enum_type=unpacked|int
    static_assert(sizeof(enum_packed) == 1, "");      // Independent of --enum_type
    static_assert(sizeof(enum_class) == 2, "");       // Independent of --enum_type
    static_assert(sizeof(enum_class_packed) == 2, "");// Independent of --enum_type
    
    static_assert(sizeof(enum_u8) == 1, "");
    static_assert(sizeof(enum_packed_u8) == 1, "");
    static_assert(sizeof(enum_class_u8) == 1, "");
    static_assert(sizeof(enum_class_packed_u8) == 1, "");
    
    static_assert(sizeof(enum_u16) == 2, "");
    static_assert(sizeof(enum_packed_u16) == 2, "");
    static_assert(sizeof(enum_class_u16) == 2, "");
    static_assert(sizeof(enum_class_packed_u16) == 2, "");
    
    void Print_enum_class();
    
    #endif /* ENUM_CLASS_HPP_ */
    

    /*
     * enum_class.cpp
     */
    #include <cstdio>
    #include "enum_class.hpp"
    
    void Print_enum_class()
    {
        printf("\r\nenum_class\r\n\r\n");
        printf("enum       x           { }       ;    %u\r\n", sizeof(enum_));
        printf("enum       x           { } PACKED;    %u\r\n", sizeof(enum_packed));
        printf("enum class x           { }       ;    %u\r\n", sizeof(enum_class));
        printf("enum class x           { } PACKED;    %u\r\n", sizeof(enum_class_packed));
    
        printf("enum       x: uint8_t  { }       ;    %u\r\n", sizeof(enum_u8));
        printf("enum       x: uint8_t  { } PACKED;    %u\r\n", sizeof(enum_packed_u8));
        printf("enum class x: uint8_t  { }       ;    %u\r\n", sizeof(enum_class_u8));
        printf("enum class x: uint8_t  { } PACKED;    %u\r\n", sizeof(enum_class_packed_u8));
    
        printf("enum       x: uint16_t { }       ;    %u\r\n", sizeof(enum_u16));
        printf("enum       x: uint16_t { } PACKED;    %u\r\n", sizeof(enum_packed_u16));
        printf("enum class x: uint16_t { }       ;    %u\r\n", sizeof(enum_class_u16));
        printf("enum class x: uint16_t { } PACKED;    %u\r\n", sizeof(enum_class_packed_u16));
    }
    
    /*                                        sizeof(x)
    enum_class           --enum_type= unpacked  packed   int
    
    enum       x           { }       ;    2       1       2
    enum       x           { } PACKED;    1       1       1
    enum class x           { }       ;    2      *2*      2
    enum class x           { } PACKED;   *2*     *2*     *2*
    enum       x: uint8_t  { }       ;    1       1       1
    enum       x: uint8_t  { } PACKED;    1       1       1
    enum class x: uint8_t  { }       ;    1       1       1
    enum class x: uint8_t  { } PACKED;    1       1       1
    enum       x: uint16_t { }       ;    2       2       2
    enum       x: uint16_t { } PACKED;    2       2       2
    enum class x: uint16_t { }       ;    2       2       2
    enum class x: uint16_t { } PACKED;    2       2       2
    */
    

  • Johan Eriksson50 said:
    How did you read out the sizeof value?

    There is no standard way to do it.  The method I describe presumes you cannot run the code. It also presumes you use a TI compiler.

    Write a small source file similar to ...

    enum class enum_class { red, green, blue };
    
    int see_sizeof_enum_class()
    {
       return sizeof(enum_class);
    }

    Compile as you would any other source file in your CCS project.  But add one additional build option: --src_interlist.  This option causes the compiler to keep the generated assembly file (it is deleted by default), and add comments to it which make it easier to understand.  The assembly file has the same name as the source file, with the extension changed to .asm.  The core of this assembly file has these lines ...

    ;*****************************************************************************
    ;* FUNCTION NAME: see_sizeof_enum_class()                                    *
    ;*                                                                           *
    ;*   Regs Modified     : A1                                                  *
    ;*   Regs Used         : A1,LR                                               *
    ;*   Local Frame Size  : 0 Args + 0 Auto + 0 Save = 0 byte                   *
    ;*****************************************************************************
    _Z21see_sizeof_enum_classv:
    ;* --------------------------------------------------------------------------*
    ;** 5   -----------------------    return 4;
            MOV       A1, #4                ; [] |5|
            BX        LR                    ; []
            ; BRANCH OCCURS                  ; []

    It is pretty clear this sizeof is 4.  

    To do a similar thing with GCC compilers, use the switch -S.

    Thanks and regards,

    -George