Bjarni Ingi Gislason wrote: > Debian testing (bookworm/sid) > > gcc (Debian 12.2.0-14) 12.2.0 > > GNU Make 4.4.0.90 > > > [...] > CXX src/roff/troff/env.o > In file included from /usr/include/c++/12/bits/stl_bvector.h:61, > from /usr/include/c++/12/vector:65, > from ../src/roff/troff/charinfo.h:20, > from ../src/roff/troff/env.cpp:31: > /usr/include/c++/12/bits/functional_hash.h:273:12: error: redefinition of > 'struct std::hash<long int>' > 273 | struct hash<nullptr_t> : public __hash_base<size_t, nullptr_t> > | ^~~~~~~~~~~~~~~ > /usr/include/c++/12/bits/functional_hash.h:157:3: note: previous definition > of 'struct std::hash<long int>' > 157 | _Cxx_hashtable_define_trivial_hash(long) > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > make[1]: *** [Makefile:10126: src/roff/troff/env.o] Error 1
Thanks for the report. I reproduce it with the just-added unit tests, with GCC 11 or 12, but not with other compilers (GCC 10 or older, clang, MSVC, AIX xlc, Solaris cc). But even when there is no error in the unit test, there could be errors in application code, if we define nullptr to some value that is inferior to what the C++ compiler already does. So, the guideline should be: If the C++ compiler already supports 'nullptr', leave it alone and don't define it as a macro. I found out that for g++ and clang++, 'nullptr' is supported with the options -std=c++11, -std=c++14, -std=c++17 and not supported with the option -std=c++03. To detect this situation, the value of __cplusplus can be used. The various __cpp_* macros don't help here. Also, MSVC 14 supports it, although its __cplusplus value is only 199711L. In my tests, AIX xlc and Solaris cc (up to Developer Studio 12.6) don't support it. Taken together, this gives this fix. 2023-02-05 Bruno Haible <br...@clisp.org> c-nullptr: Fix conflict with libstdc++ in GCC >= 11. Reported by Bjarni Ingi Gislason <bjarn...@simnet.is> in <https://lists.gnu.org/archive/html/bug-gnulib/2023-02/msg00030.html>. * m4/c-nullptr.m4 (gl_C_NULLPTR): Don't define nullptr if it is already defined. In C++ mode, ignore the result of the configure test and don't define it when we know that the C++ compiler already supports it. diff --git a/m4/c-nullptr.m4 b/m4/c-nullptr.m4 index af79854696..960eeff18d 100644 --- a/m4/c-nullptr.m4 +++ b/m4/c-nullptr.m4 @@ -18,13 +18,25 @@ AC_DEFUN([gl_C_NULLPTR], ]) AH_VERBATIM([nullptr], -[#ifndef HAVE_C_NULLPTR -# ifndef __cplusplus -# define nullptr ((void *) 0) -# elif 3 <= __GNUG__ -# define nullptr __null +[#ifndef nullptr /* keep config.h idempotent */ +# ifdef __cplusplus +/* For the C++ compiler the result of the configure test is irrelevant. + We know that at least g++ and clang with option -std=c++11 or higher, as well + as MSVC 14 or newer, already have nullptr. */ +# if !(((defined __GNUC__ || defined __clang__) && __cplusplus >= 201103L) \ + || (defined _MSC_VER && 1900 <= _MSC_VER)) +/* Define nullptr as a macro, the best we can. */ +# if 3 <= __GNUG__ +# define nullptr __null +# else +# define nullptr 0L +# endif +# endif # else -# define nullptr 0L +/* For the C compiler, use the result of the configure test. */ +# ifndef HAVE_C_NULLPTR +# define nullptr ((void *) 0) +# endif # endif #endif]) ])