c++structsolarisunionssunstudio

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 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?


Solution

  • 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.)