Paul Eggert wrote:
> I can
> reproduce it with current Gnulib by building testdir-all with the above
> recipe on Fedora 44, then copying testdir-all to Solaris 10 sparc and
> then running:
>
> # This uses Oracle Developer Studio 12.6 152881-04 2019/03/08.
> export PATH=/opt/developerstudio12.6/bin:$PATH
> ./configure CC=cc CXX=CC
> make
>
> This eventually fails with:
>
> CC -DHAVE_CONFIG_H -DEXEEXT=\"\" -DEXEEXT=\"\" -I. -I..
> -DGNULIB_STRICT_CHECKING=1 -DIN_GNULIB_TESTS=1 -I. -I. -I.. -I./.. \
> -I../gllib -I./../gllib -D_REENTRANT -Wno-error -Wno-error -g -c -o
> test-arpa_inet-h-c++.o test-arpa_inet-h-c++.cc
> "../gllib/string.h", line 1823: Error: Template declarations cannot have
> extern "C" linkage.
> "../gllib/string.h", line 1824: Error: Template declarations cannot have
> extern "C" linkage.
> "../gllib/string.h", line 1826: Error: Template declarations cannot have
> extern "C" linkage.
> 3 Error(s) detected.
Thanks for the report.
I can reproduce it in a non-VPATH build.
To analyze it:
1. Produce the preprocessed output:
$ CC ... -E test-arpa_inet-h-c++.cc > /tmp/i
2. Look from where gllib/string.h gets included: from gllib/sys/select.h
3. Look from where gllib/sys/select.h gets included: from
/usr/include/sys/types.h
4. Look from where /usr/include/sys/types.h gets included: from
gllib/sys/types.h
5. Look from where gllib/sys/types.h gets included: from gllib/sys/socket.h
6. Look from where gllib/sys/socket.h gets included: from gllib/arpa/inet.h
7. Look from where gllib/arpa/inet.h gets included: from test-arpa_inet-h-c++.cc
8. Find at any open extern "C" { ... } blocks in this include chain:
It is /usr/include/sys/types.h line 629 which includes <sys/select.h>,
block opened at line 43 and closed at line 646.
As mentioned in
https://lists.gnu.org/archive/html/bug-gnulib/2026-05/msg00070.html,
the common convention is that all .h files must be included *outside*
of extern "C" blocks.
So, I tried to fix this in the usual way, see first-attempt.diff (attached).
But it does not work.
> Here are lines 1821-1829 of gllib/string.h:
>
> # ifdef __cplusplus
> _GL_BEGIN_NAMESPACE
> template <typename T> T strnul (T);
> template <> inline const char *strnul<const char *> (const char *s)
> { return _gl_strnul (s); }
> template <> inline char *strnul< char *> ( char *s)
> { return const_cast<char *>(_gl_strnul (s)); }
> _GL_END_NAMESPACE
> # else
>
> You can see the full log in the build directory by logging into cfarm210
> and inspecting ~eggert/testdir-all/build-log.txt.
>
> Should there be be a 'extern "C++"' around this template, just as there
> is for mbsstr, mbspcasecmp, mbscasestr in lib/string.in.h? But those
> other instances are marked "needed for AIX", not "needed for Oracle
> Developer Studio".
Yes, this is the symptom-fix. Like I did for AIX in
https://lists.gnu.org/archive/html/bug-gnulib/2025-02/msg00054.html
It was marked as "needed for AIX", because a year ago, I still tested
with xlc on AIX 7.1. That machine (cfarm111.cfarm.net) is no longer
online; that's why now Oracle CC is the first compiler to stumble across it.
2026-05-10 Bruno Haible <[email protected]>
strnul: Fix compilation in C++ mode on Solaris 10 with Oracle Studio 12.
Reported by Paul Eggert in
<https://lists.gnu.org/archive/html/bug-gnulib/2026-05/msg00068.html>.
* lib/string.in.h (strnul): Wrap template declarations and definitions
in 'extern "C++" { ... }'.
diff --git a/lib/string.in.h b/lib/string.in.h
index 3fa3e943eb..8e4fd8f81e 100644
--- a/lib/string.in.h
+++ b/lib/string.in.h
@@ -1272,6 +1272,7 @@ _GL_STRNUL_INLINE const char *_gl_strnul (const char
*string)
}
# endif
# ifdef __cplusplus
+extern "C++" { /* needed for Solaris 10 */
_GL_BEGIN_NAMESPACE
template <typename T> T strnul (T);
template <> inline const char *strnul<const char *> (const char *s)
@@ -1279,6 +1280,7 @@ template <> inline const char *strnul<const char *>
(const char *s)
template <> inline char *strnul< char *> ( char *s)
{ return const_cast<char *>(_gl_strnul (s)); }
_GL_END_NAMESPACE
+}
# else
# if (defined __GNUC__ && __GNUC__ + (__GNUC_MINOR__ >= 9) > 4 && !defined
__cplusplus) \
|| (defined __clang__ && __clang_major__ >= 3) \
diff --git a/ChangeLog b/ChangeLog
index a162917acb..8e660e1e2c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2026-05-10 Bruno Haible <[email protected]>
+
+ sys_types-h: Fix compilation error on Solaris 10 in C++ mode.
+ * lib/sys_types.in.h: On Solaris in C++ mode, before including the
+ system's <sys/types.h> file, include <sys/select.h>.
+
2026-05-10 Bruno Haible <[email protected]>
calloc-gnu tests: Skip expensive part on Solaris.
diff --git a/lib/sys_types.in.h b/lib/sys_types.in.h
index 733b4ba4b0..ec3ce9be80 100644
--- a/lib/sys_types.in.h
+++ b/lib/sys_types.in.h
@@ -42,6 +42,11 @@
/* The include_next requires a split double-inclusion guard. */
# define _GL_INCLUDING_SYS_TYPES_H
+/* Solaris 10 has a bug: In C++ mode, <sys/select.h> must be included before
+ <sys/types.h>. */
+# if defined __cplusplus && defined _sun
+# include <sys/select.h>
+# endif
#@INCLUDE_NEXT@ @NEXT_SYS_TYPES_H@
# undef _GL_INCLUDING_SYS_TYPES_H