We are catching a compile warning under SunCC 5.12 through 5.14. Other compilers, like Clang, GCC, ICC and MSVC does not complain. I'm not sure about the diagnostic because I have not encountered it before.
The code in question is for a BigInteger
class and the problematic union follows. The class attempts to find the largest machine word that can accommodate adds-with-carries and multiplies that can be performed using hardware like umulx
.
class Dword
{
...
private:
320 union
321 {
322 #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
323 dword m_whole;
324 #endif
325 struct
326 {
327 #ifdef IS_LITTLE_ENDIAN
328 word low;
329 word high;
330 #else
331 word high;
332 word low;
333 #endif
334 } m_halfs;
335 };
336 };
Here's the warning:
[ 3%] Building CXX object CMakeFiles/cryptopp-object.dir/integer.cpp.o
/opt/solarisstudio12.3/bin/CC -fPIC -native -m64 -template=no%extdef -o CMakeFiles/cryptopp-object.dir/integer.cpp.o
-c /export/home/jwalton/cryptopp/integer.cpp
CC: Warning: -xchip=native detection failed, falling back to -xchip=generic
"/export/home/jwalton/cryptopp/integer.cpp", line 335: Warning: Types cannot be declared in anonymous union.
1 Warning(s) detected.
According to Microsoft at Anonymous Unions:
Simply omitting the class-name portion of the syntax does not make a union an anonymous union. For a union to qualify as an anonymous union, the declaration must not declare an object.
If I understand things correctly, we do have an anonymous struct because no one can instantiate the private member struct {...} m_halfs
starting at line 325. Then, SunCC is complaining the anonymous union has the member struct {...} m_halfs
. Is that correct?
If struct {...} m_halfs
is the problem, then how can we go about clearing it in a portable way?
If its not the problem, then what is SunCC complaining about?
I have to be careful about how this issue cleared. Performance is a top priority and the code is on the critical path. Also, we support GCC 3 and VC++ 6.0 to contemporary compilers; and C++03, C++11, C++14 and C++17.
A final question is, should we "do nothing" and live with it on Solaris?
N4296 (which is the firstdraft of the C++ 17 standard) says:
A union of the form
union { member-specification } ;
is called an anonymous union; it defines an unnamed object of unnamed type. Each member-declaration in the member-specification of an anonymous union shall either define a non-static data member or be a static_assert-declaration. [ Note: Nested types, anonymous unions, and functions cannot be declared within an anonymous union. — end note]
That is exactly what you have here - you don't have a class name or a member name, so you are not allowed to invent a new struct type for m_halfs
. I suggest moving the struct definition out of the union.
class Dword
{
...
private:
struct word_struct
{
#ifdef IS_LITTLE_ENDIAN
word low;
word high;
#else
word high;
word low;
#endif
};
union
{
#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
dword m_whole;
#endif
word_struct m_halfs;
};
};
This will have no impact on performance (but note that this trick of using unions to access different parts of a variable may fall foul of the strict aliasing rules - which means your program may have undefined behaviour.)