jww jww - 1 year ago 69
C++ Question

SunCC 5.12 through 5.14 and "Types cannot be declared in anonymous union"

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

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

class Dword
320 union
321 {
323 dword m_whole;
324 #endif
325 struct
326 {
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?

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?

Answer Source

N4296 (which is the latest draft 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
        struct word_struct
        #ifdef IS_LITTLE_ENDIAN
            word low;
            word high;
            word high;
            word low;
           dword m_whole;
           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.)