1

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?

jww
  • 97,681
  • 90
  • 411
  • 885

1 Answers1

3

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

  • Thank you very much. I've already got a branch setup for testing any changes here. *"... but note that this trick of using unions to access different parts of a variable..."* - yeah, that worries me. We ran into the same at [Initializing an __m128 type from a 64-bit unsigned int](http://stackoverflow.com/a/38547909/608639). I *really* wish C++ were more relaxed in the "active union member access" area. Any C++ program that includes C code could be at risk because its such a common pattern. – jww Sep 15 '16 at 13:22
  • @M.M: Oops. You are quite right, it is the latest draft of the C++17 standard. I have fixed the text (and put in a link). – Martin Bonner supports Monica Sep 15 '16 at 14:55
  • @MartinBonner - For what its worth, SunCC 12.3 was released in November 2012. Its C++ compiler does not support `-std=c++03` or `-std=c++11`; I believe C++03 is baked in. Sun Studio 12.4 C++ compiler was the first to provide C++11. Oracle has not yet provided C++14 or C++17 support. I'm guessing (an its purely a guess), C++14 support will arrive in the next couple of years. C++17 might be available in 2020 or so... – jww Sep 15 '16 at 18:29
  • N4296 was the first C++17 draft... the latest that I'm aware of is N4606 – M.M Sep 15 '16 at 20:59
  • Hmmph. I got to that document from https://isocpp.org/std/the-standard where it is described under "Where To Get the Current Standard (C++14)". – Martin Bonner supports Monica Sep 16 '16 at 05:41
  • I wonder if the text has been added to C++17 because it wasn't clear whether embedded types were allowed, and different vendors handled it differently. Forbidding them means that they can be offered as an extension, but requiring them may be a significant load on those vendors that don't currently implement them. (Pure guesswork here) – Martin Bonner supports Monica Sep 16 '16 at 05:43