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/TM4C129CNCZAD: error #1836: designator may not specify a non-POD subobject

Part Number: TM4C129CNCZAD

Tool/software: TI C/C++ Compiler

I have this definition:

const int32_t ACCELERATION_DEFAULT = 0;
const int32_t VELOCITY_DEFAULT = 0;
const uint32_t SUBROUTINE_DEFAULT = 0U;

struct MotorCmd {
  MotorCmd_E motor_cmd;
  int position;
  int32_t acceleration = ACCELERATION_DEFAULT;
  int32_t velocity = VELOCITY_DEFAULT;
  uint32_t subroutine = SUBROUTINE_DEFAULT;
  int32_t torque;
};

I then instantiate this struct in a C++ file like so:

MotorCmd motorHome = {
  .motor_cmd = MOTOR_CMD_HOME,                                 
  .position = 0,
  .torque = 0
};

And the compiler errors out with 1836 for the line with `.torque = 0`.  If I comment that single line out, everything is fine.  Is this a bug?  I don't see why this wouldn't be allowed.  As far as I know, `0` is not a non-POD.

  • I'm not sure why, but if you initialize all the struct members, in order, then it builds clean.

    MotorCmd motorHome = {
      .motor_cmd = MOTOR_CMD_HOME,                                 
      .position = 0,
      .acceleration = ACCELERATION_DEFAULT,
      .velocity = VELOCITY_DEFAULT,
      .subroutine = SUBROUTINE_DEFAULT,
      .torque = 0
    };

    Thanks and regards,

    -George

  • That doesn't explain why it doesn't the way I originally posted it. It's following the language standard. Can you file a bug against the compiler? We're using version 18.1.3.
  • I disagree, and don't believe it follows the C++ standard.

    This construct, called out-of-order designated initialization, is not part of the C++ standard. See: Information on aggregate initialization

    "Note: out-of-order designated initialization, nested designated initialization, mixing of designated initializers and regular initializers, and designated initialization of arrays are all supported in the C programming language, but are not allowed in C++."

    Your original sample code initializes both 'motor_cmd' and 'position', which are the first and second fields of the 'MotorCmd' class. Then, it initializes 'torque', the sixth field of the 'MotorCmd' class. Since the third, fourth, and fifth fields were not also initialized, it is out-of-order designated initialization, and is therefore ill-formed.

    This explains why the error goes away when you do not initialize 'torque'. It also explains why George Mock noticed that the error also goes away when all six fields are initialized.

    The reason the compiler mentioned non-POD is because 'MotorCmd' itself is not a POD class type. Due to the default member initializers of the 'acceleration', 'velocity', and 'subroutine' fields, an implicit, non-trivial default constructor is generated for the 'MotorCmd' class. Your class declaration is functionally identical to:

    const int32_t ACCELERATION_DEFAULT = 0;
    const int32_t VELOCITY_DEFAULT = 0;
    const uint32_t SUBROUTINE_DEFAULT = 0U;
    
    struct MotorCmd {
      MotorCmd_E motor_cmd;
      int position;
      int32_t acceleration;
      int32_t velocity;
      uint32_t subroutine;
      int32_t torque;
    
      MotorCmd() : acceleration(ACCELERATION_DEFAULT),
                   velocity(VELOCITY_DEFAULT),
                   subroutine(SUBROUTINE_DEFAULT) { /* empty */ }
    };

    One requirement for a class to be considered POD is that is has no non-trivial constructor, even if it's implicitly defined. clang agrees with this assessment

    If you're using C++, the best way to solve this would be to define and use a constructor to initialize a 'MotorCmd' object, rather than designated initialization. Our compiler does not support out-of-order designated initialization of non-POD types.

  • Interesting. This is a very nuanced behavior, and I appreciate your explanation.