Re: C++11: GLIBMM_INITIALIZE_STRUCT



2013-07-08 10:46, Reece Dunn skrev:
On 8 July 2013 08:49, Murray Cumming <murrayc murrayc com> wrote:
It would be nice to have some general fix for this warning when using
--std=c++11 with g++:

optiongroup.cc: In member function 'void
Glib::OptionGroup::add_entry(const Glib::OptionEntry&)':
optiongroup.cc:320:3: error: missing initializer for member
'_GOptionEntry::short_name' [-Werror=missing-field-initializers]
optiongroup.cc:320:3: error: missing initializer for member
'_GOptionEntry::flags' [-Werror=missing-field-initializers]
optiongroup.cc:320:3: error: missing initializer for member
'_GOptionEntry::arg' [-Werror=missing-field-initializers]
optiongroup.cc:320:3: error: missing initializer for member
'_GOptionEntry::arg_data' [-Werror=missing-field-initializers]
optiongroup.cc:320:3: error: missing initializer for member
'_GOptionEntry::description' [-Werror=missing-field-initializers]
optiongroup.cc:320:3: error: missing initializer for member
'_GOptionEntry::arg_description' [-Werror=missing-field-initializers]

It's caused by the GLIBMM_INITIALIZE_STRUCT macro definition using the
second possibility rather than the first, because __STRICT_ANSI__ is not
defined, but I don't know why that would have been defined before, but
not with C++11.
https://git.gnome.org/browse/glibmm/tree/glib/glibmm/utility.h#n28

I found http://stackoverflow.com/questions/5580921/how-can-i-make-c0x-and-strict-ansi-get-along. It looks like -- from this and other websites -- that gcc defines __STRICT_ANSI__ if --std=c++11 is defined.

With:

     $ g++ --version
     g++ (Debian 4.7.3-4) 4.7.3

and:

    $ touch empty.c
    $ touch empty.cpp

I get:

    $ gcc -std=c99 -E -dM empty.c | grep -P "(__STRICT|__cplusplus)"
    #define __STRICT_ANSI__ 1

    $ gcc -std=gnu99 -E -dM empty.c | grep -P "(__STRICT|__cplusplus)"

    $ gcc -std=c++98 -E -dM empty.cpp | grep -P "(__STRICT|__cplusplus)"
    #define __STRICT_ANSI__ 1
    #define __cplusplus 199711L

    $ gcc -std=gnu++98 -E -dM empty.cpp | grep -P "(__STRICT|__cplusplus)"
    #define __cplusplus 199711L

    $ gcc -std=c++11 -E -dM empty.cpp | grep -P "(__STRICT|__cplusplus)"
    #define __STRICT_ANSI__ 1
    #define __cplusplus 201103L

    $ gcc -std=gnu++11 -E -dM empty.cpp | grep -P "(__STRICT|__cplusplus)"
    #define __cplusplus 201103L

    $ gcc -std=c++0x -E -dM empty.cpp | grep -P "(__STRICT|__cplusplus)"
    #define __STRICT_ANSI__ 1
    #define __cplusplus 201103L

    $ gcc-4.4 -std=c++0x -E -dM empty.cpp | grep -P "(__STRICT|__cplusplus)"
    #define __STRICT_ANSI__ 1
    #define __cplusplus 1

So:

__STRICT_ANSI__ checks for ISO/ANSI compliance vs GNU extensions (C or C++).

__cplusplus checks for C++ vs C (with 199711L for C++98, 1 for C++0x (pre-standardisation) and 201103L for C++11).

HTH,
- Reece

Some info copied from the description of gcc 4.7.0:

-Wmissing-field-initializers
  This warning is included in ‘-Wextra’. To get other ‘-Wextra’ warnings without
  this one, use ‘-Wextra -Wno-missing-field-initializers’.

GCC normally defines __STDC__ to be 1, and in addition defines __STRICT_ANSI__ if
you specify the ‘-ansi’ option, or a ‘-std’ option for strict conformance to some version
of ISO C.

-----------------
GLIBMM_INITIALIZE_STRUCT chooses the second alternative when __STRICT_ANSI__ is defined.

More tests with gcc:

$ gcc-4.7 -E -dM empty.cpp | grep STRICT

$ gcc-4.7 -std=c++11 -E -dM empty.cpp | grep STRICT
#define __STRICT_ANSI__ 1

$ gcc-4.7 -pedantic -Wextra -E -dM empty.cpp | grep STRICT

$ gcc-4.7 -pedantic -Wextra -std=c++11 -E -dM empty.cpp | grep STRICT
#define __STRICT_ANSI__ 1

$ gcc-4.7 -pedantic -Wextra -std=gnu++11 -E -dM empty.cpp | grep STRICT

When no -std option is given, __STRICT_ANSI__ is not defined, and GLIBMM_INITIALIZE_STRUCT
chooses the first alternative. The default value is -std=gnu++98.


Solution? Why not use std::memset() in GLIBMM_INITIALIZE_STRUCT?
Probable answer: Because it requires #include <cstring>.

The glib macros G_GNUC_BEGIN_IGNORE_DEPRECATIONS and G_GNUC_END_IGNORE_DEPRECATIONS contain a trick that temporarily suppresses a particular warning.

#if    __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#define G_GNUC_BEGIN_IGNORE_DEPRECATIONS        \
  _Pragma ("GCC diagnostic push")            \
  _Pragma ("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
#define G_GNUC_END_IGNORE_DEPRECATIONS            \
  _Pragma ("GCC diagnostic pop")
#else
#define G_GNUC_BEGIN_IGNORE_DEPRECATIONS
#define G_GNUC_END_IGNORE_DEPRECATIONS
#endif

I don't know exactly what kind of preprocessor directive _Pragma is. It might be useful in GLIBMM_INITIALIZE_STRUCT.

Do we really need GLIBMM_INITIALIZE_STRUCT? There are 3 uses in glibmm and 6 in gtkmm. They can easily be replaced by std::memset().

Kjell



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]