diff --git a/src/libnml/nml/stat_msg.cc b/src/libnml/nml/stat_msg.cc index 7e1301c2875..c5b3b7d305d 100644 --- a/src/libnml/nml/stat_msg.cc +++ b/src/libnml/nml/stat_msg.cc @@ -35,7 +35,7 @@ int RCS_STAT_MSG_format(NMLTYPE t, void *buf, CMS * cms) { cms->update(((RCS_STAT_MSG *) buf)->command_type); cms->update(((RCS_STAT_MSG *) buf)->echo_serial_number); - cms->update((int&)(((RCS_STAT_MSG *) buf)->status)); + cms->update(((RCS_STAT_MSG *) buf)->status_int); cms->update(((RCS_STAT_MSG *) buf)->state); switch (t) { diff --git a/src/libnml/nml/stat_msg.hh b/src/libnml/nml/stat_msg.hh index a432c8d9151..55e48183b00 100644 --- a/src/libnml/nml/stat_msg.hh +++ b/src/libnml/nml/stat_msg.hh @@ -23,7 +23,22 @@ class RCS_STAT_MSG:public NMLmsg { RCS_STAT_MSG(NMLTYPE t, size_t sz); NMLTYPE command_type; int echo_serial_number; - RCS_STATUS status; + // The anonymous union is provided to allow for RCS_STAT_MSG_format() in + // nml/stat_msg.cc to call cms->update() with an integer reference. Member + // 'status' is normally accessed. Casting the 'status' member to int& in + // the cms->update() call will give a 'type-punned pointer dereference' + // warning. We sidestep this problem with the union where we can address + // either field and get the same value. + // The union is necessary because the update() call implementation checks + // the address of its argument to be in a specific memory region, which + // excludes using a temporary. Now, with the union, both members 'status' + // and 'status_int' share the same memory location. The 'RCS_STATUS' enum + // in rcs/rcs.hh explicitly declares the enum's underlying type as int. + // Therefore, both union members are of same underlying type. + union { + RCS_STATUS status; + int status_int; + }; int state; }; diff --git a/src/libnml/rcs/rcs.hh b/src/libnml/rcs/rcs.hh index d56361fcd7e..a81600aa392 100644 --- a/src/libnml/rcs/rcs.hh +++ b/src/libnml/rcs/rcs.hh @@ -28,7 +28,10 @@ class RCS_TIMER; class RCS_CMD_MSG; class RCS_STAT_MSG; -enum class RCS_STATUS { /* Originally from nml_mod.hh */ +// The underlying type specifier of int is meant to stress that it +// is of paramount importance that the underlying type of the +// RCS_STATUS enum is int. See nml/stat_msg.hh for more details. +enum class RCS_STATUS : int { /* Originally from nml_mod.hh */ UNINITIALIZED = -1, DONE = 1, EXEC = 2,