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
 

Reply via email to