bug-gnulib
[Top][All Lists]
Advanced

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

uchar: uchar: Inline functions with C linkage in C++ mode


From: Bruno Haible
Subject: uchar: uchar: Inline functions with C linkage in C++ mode
Date: Thu, 06 Apr 2023 17:07:19 +0200

Building a testdir on Slackware 14.0 (with gcc 4.7) I see also this link error:

g++  -Wno-error -g -O2  -L/home/bruno/lib -o test-uchar-c++ test-uchar-c++.o  
libtests.a ../gllib/libgnu.a libtests.a ../gllib/libgnu.a libtests.a    -lm -lm 
-lm -lm -lm -lm -lm -lm -lm -lm -lm
test-uchar-c++.o: In function `__static_initialization_and_destruction_0':
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:28: 
undefined reference to `btoc32(int)'
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:32: 
undefined reference to `c32isalnum(unsigned int)'
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:36: 
undefined reference to `c32isalpha(unsigned int)'
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:40: 
undefined reference to `c32isblank(unsigned int)'
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:44: 
undefined reference to `c32iscntrl(unsigned int)'
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:48: 
undefined reference to `c32isdigit(unsigned int)'
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:52: 
undefined reference to `c32isgraph(unsigned int)'
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:56: 
undefined reference to `c32islower(unsigned int)'
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:60: 
undefined reference to `c32isprint(unsigned int)'
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:64: 
undefined reference to `c32ispunct(unsigned int)'
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:68: 
undefined reference to `c32isspace(unsigned int)'
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:72: 
undefined reference to `c32isupper(unsigned int)'
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:76: 
undefined reference to `c32isxdigit(unsigned int)'
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:86: 
undefined reference to `c32snrtombs(char*, unsigned int const**, unsigned int, 
unsigned int, __mbstate_t*)'
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:91: 
undefined reference to `c32srtombs(char*, unsigned int const**, unsigned int, 
__mbstate_t*)'
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:96: 
undefined reference to `c32stombs(char*, unsigned int const*, unsigned int)'
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:100: 
undefined reference to `c32tob(unsigned int)'
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:110: 
undefined reference to `mbsnrtoc32s(unsigned int*, char const**, unsigned int, 
unsigned int, __mbstate_t*)'
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:116: 
undefined reference to `mbsrtoc32s(unsigned int*, char const**, unsigned int, 
__mbstate_t*)'
/home/bruno/testdir-all/build/gltests/../../gltests/test-uchar-c++.cc:121: 
undefined reference to `mbstoc32s(unsigned int*, char const*, unsigned int)'
collect2: error: ld returned 1 exit status
make[4]: *** [test-uchar-c++] Error 1

It's apparently caused by the _GL_INLINE expansion

  #define _GL_INLINE extern inline __attribute__ ((__gnu_inline__))

that is used in uchar.h. An explicit 'extern "C"' is needed. But I can't
stuff it into _GL_INLINE like this:

  #define _GL_INLINE extern "C" inline __attribute__ ((__gnu_inline__))

because that would cause syntax errors in gl_list.h, when _GL_INLINE
is preceded by _GL_ATTRIBUTE_NODISCARD. So, the fix is to use
extern "C" { ... }.


2023-04-06  Bruno Haible  <bruno@clisp.org>

        uchar: Inline functions with C linkage in C++ mode (regr. 2023-04-04).
        * m4/gnulib-common.m4 (gl_COMMON_BODY): Put definitions of
        _GL_BEGIN_C_LINKAGE, _GL_END_C_LINKAGE into config.h.
        * lib/uchar.in.h: Enclose all inline functions in _GL_BEGIN_C_LINKAGE /
        _GL_END_C_LINKAGE.

diff --git a/lib/uchar.in.h b/lib/uchar.in.h
index b5554c64b6..4461a35901 100644
--- a/lib/uchar.in.h
+++ b/lib/uchar.in.h
@@ -145,11 +145,13 @@ static_assert (sizeof (char32_t) == sizeof (wchar_t));
 /* Convert a single-byte character to a 32-bit wide character.  */
 #if @GNULIB_BTOC32@
 # if _GL_WCHAR_T_IS_UCS4 && !defined IN_BTOC32
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE _GL_ATTRIBUTE_PURE wint_t
 btoc32 (int c)
 {
   return btowc (c);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (btoc32, wint_t, (int c) _GL_ATTRIBUTE_PURE);
 # endif
@@ -161,11 +163,13 @@ _GL_CXXALIASWARN (btoc32);
 /* Test a specific property of a 32-bit wide character.  */
 #if @GNULIB_C32ISALNUM@
 # if (_GL_WCHAR_T_IS_UCS4 && !GNULIB_defined_mbstate_t) && !defined 
IN_C32ISALNUM
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE int
 c32isalnum (wint_t wc)
 {
   return iswalnum (wc);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (c32isalnum, int, (wint_t wc));
 # endif
@@ -174,11 +178,13 @@ _GL_CXXALIASWARN (c32isalnum);
 #endif
 #if @GNULIB_C32ISALPHA@
 # if (_GL_WCHAR_T_IS_UCS4 && !GNULIB_defined_mbstate_t) && !defined 
IN_C32ISALPHA
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE int
 c32isalpha (wint_t wc)
 {
   return iswalpha (wc);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (c32isalpha, int, (wint_t wc));
 # endif
@@ -187,11 +193,13 @@ _GL_CXXALIASWARN (c32isalpha);
 #endif
 #if @GNULIB_C32ISBLANK@
 # if (_GL_WCHAR_T_IS_UCS4 && !GNULIB_defined_mbstate_t) && !defined 
IN_C32ISBLANK
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE int
 c32isblank (wint_t wc)
 {
   return iswblank (wc);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (c32isblank, int, (wint_t wc));
 # endif
@@ -200,11 +208,13 @@ _GL_CXXALIASWARN (c32isblank);
 #endif
 #if @GNULIB_C32ISCNTRL@
 # if (_GL_WCHAR_T_IS_UCS4 && !GNULIB_defined_mbstate_t) && !defined 
IN_C32ISCNTRL
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE int
 c32iscntrl (wint_t wc)
 {
   return iswcntrl (wc);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (c32iscntrl, int, (wint_t wc));
 # endif
@@ -213,11 +223,13 @@ _GL_CXXALIASWARN (c32iscntrl);
 #endif
 #if @GNULIB_C32ISDIGIT@
 # if (_GL_WCHAR_T_IS_UCS4 && !GNULIB_defined_mbstate_t) && !defined 
IN_C32ISDIGIT
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE int
 c32isdigit (wint_t wc)
 {
   return iswdigit (wc);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (c32isdigit, int, (wint_t wc));
 # endif
@@ -226,11 +238,13 @@ _GL_CXXALIASWARN (c32isdigit);
 #endif
 #if @GNULIB_C32ISGRAPH@
 # if (_GL_WCHAR_T_IS_UCS4 && !GNULIB_defined_mbstate_t) && !defined 
IN_C32ISGRAPH
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE int
 c32isgraph (wint_t wc)
 {
   return iswgraph (wc);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (c32isgraph, int, (wint_t wc));
 # endif
@@ -239,11 +253,13 @@ _GL_CXXALIASWARN (c32isgraph);
 #endif
 #if @GNULIB_C32ISLOWER@
 # if (_GL_WCHAR_T_IS_UCS4 && !GNULIB_defined_mbstate_t) && !defined 
IN_C32ISLOWER
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE int
 c32islower (wint_t wc)
 {
   return iswlower (wc);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (c32islower, int, (wint_t wc));
 # endif
@@ -252,11 +268,13 @@ _GL_CXXALIASWARN (c32islower);
 #endif
 #if @GNULIB_C32ISPRINT@
 # if (_GL_WCHAR_T_IS_UCS4 && !GNULIB_defined_mbstate_t) && !defined 
IN_C32ISPRINT
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE int
 c32isprint (wint_t wc)
 {
   return iswprint (wc);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (c32isprint, int, (wint_t wc));
 # endif
@@ -265,11 +283,13 @@ _GL_CXXALIASWARN (c32isprint);
 #endif
 #if @GNULIB_C32ISPUNCT@
 # if (_GL_WCHAR_T_IS_UCS4 && !GNULIB_defined_mbstate_t) && !defined 
IN_C32ISPUNCT
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE int
 c32ispunct (wint_t wc)
 {
   return iswpunct (wc);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (c32ispunct, int, (wint_t wc));
 # endif
@@ -278,11 +298,13 @@ _GL_CXXALIASWARN (c32ispunct);
 #endif
 #if @GNULIB_C32ISSPACE@
 # if (_GL_WCHAR_T_IS_UCS4 && !GNULIB_defined_mbstate_t) && !defined 
IN_C32ISSPACE
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE int
 c32isspace (wint_t wc)
 {
   return iswspace (wc);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (c32isspace, int, (wint_t wc));
 # endif
@@ -291,11 +313,13 @@ _GL_CXXALIASWARN (c32isspace);
 #endif
 #if @GNULIB_C32ISUPPER@
 # if (_GL_WCHAR_T_IS_UCS4 && !GNULIB_defined_mbstate_t) && !defined 
IN_C32ISUPPER
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE int
 c32isupper (wint_t wc)
 {
   return iswupper (wc);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (c32isupper, int, (wint_t wc));
 # endif
@@ -304,11 +328,13 @@ _GL_CXXALIASWARN (c32isupper);
 #endif
 #if @GNULIB_C32ISXDIGIT@
 # if (_GL_WCHAR_T_IS_UCS4 && !GNULIB_defined_mbstate_t) && !defined 
IN_C32ISXDIGIT
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE int
 c32isxdigit (wint_t wc)
 {
   return iswxdigit (wc);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (c32isxdigit, int, (wint_t wc));
 # endif
@@ -347,12 +373,14 @@ _GL_WARN_ON_USE (c32rtomb, "c32rtomb is not portable - "
 /* Convert a 32-bit wide string to a string.  */
 #if @GNULIB_C32SNRTOMBS@
 # if _GL_WCHAR_T_IS_UCS4 && !defined IN_C32SNRTOMBS
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE _GL_ARG_NONNULL ((2)) size_t
 c32snrtombs (char *dest, const char32_t **srcp, size_t srclen, size_t len,
              mbstate_t *ps)
 {
   return wcsnrtombs (dest, (const wchar_t **) srcp, srclen, len, ps);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (c32snrtombs, size_t,
                   (char *dest, const char32_t **srcp, size_t srclen, size_t 
len,
@@ -369,11 +397,13 @@ _GL_CXXALIASWARN (c32snrtombs);
 /* Convert a 32-bit wide string to a string.  */
 #if @GNULIB_C32SRTOMBS@
 # if _GL_WCHAR_T_IS_UCS4 && !defined IN_C32SRTOMBS
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE _GL_ARG_NONNULL ((2)) size_t
 c32srtombs (char *dest, const char32_t **srcp, size_t len, mbstate_t *ps)
 {
   return wcsrtombs (dest, (const wchar_t **) srcp, len, ps);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (c32srtombs, size_t,
                   (char *dest, const char32_t **srcp, size_t len, mbstate_t 
*ps)
@@ -389,6 +419,7 @@ _GL_CXXALIASWARN (c32srtombs);
 /* Convert a 32-bit wide string to a string.  */
 #if @GNULIB_C32STOMBS@
 # if _GL_WCHAR_T_IS_UCS4 && !defined IN_C32STOMBS
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE _GL_ARG_NONNULL ((2)) size_t
 c32stombs (char *dest, const char32_t *src, size_t len)
 {
@@ -397,6 +428,7 @@ c32stombs (char *dest, const char32_t *src, size_t len)
   memset (&state, '\0', sizeof (mbstate_t));
   return c32srtombs (dest, &src, len, &state);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (c32stombs, size_t,
                   (char *dest, const char32_t *src, size_t len)
@@ -413,11 +445,13 @@ _GL_CXXALIASWARN (c32stombs);
    or EOF otherwise.  */
 #if @GNULIB_C32TOB@
 # if _GL_WCHAR_T_IS_UCS4 && !defined IN_C32TOB
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE int
 c32tob (wint_t wc)
 {
   return wctob (wc);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (c32tob, int, (wint_t wc));
 # endif
@@ -460,12 +494,14 @@ _GL_WARN_ON_USE (mbrtoc32, "mbrtoc32 is not portable - "
 /* Convert a string to a 32-bit wide string.  */
 #if @GNULIB_MBSNRTOC32S@
 # if _GL_WCHAR_T_IS_UCS4 && !defined IN_MBSNRTOC32S
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE _GL_ARG_NONNULL ((2)) size_t
 mbsnrtoc32s (char32_t *dest, const char **srcp, size_t srclen, size_t len,
              mbstate_t *ps)
 {
   return mbsnrtowcs ((wchar_t *) dest, srcp, srclen, len, ps);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (mbsnrtoc32s, size_t,
                   (char32_t *dest, const char **srcp, size_t srclen, size_t 
len,
@@ -482,11 +518,13 @@ _GL_CXXALIASWARN (mbsnrtoc32s);
 /* Convert a string to a 32-bit wide string.  */
 #if @GNULIB_MBSRTOC32S@
 # if _GL_WCHAR_T_IS_UCS4 && !defined IN_MBSRTOC32S
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE _GL_ARG_NONNULL ((2)) size_t
 mbsrtoc32s (char32_t *dest, const char **srcp, size_t len, mbstate_t *ps)
 {
   return mbsrtowcs ((wchar_t *) dest, srcp, len, ps);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (mbsrtoc32s, size_t,
                   (char32_t *dest, const char **srcp, size_t len, mbstate_t 
*ps)
@@ -502,6 +540,7 @@ _GL_CXXALIASWARN (mbsrtoc32s);
 /* Convert a string to a 32-bit wide string.  */
 #if @GNULIB_MBSTOC32S@
 # if _GL_WCHAR_T_IS_UCS4 && !defined IN_MBSTOC32S
+_GL_BEGIN_C_LINKAGE
 _GL_INLINE _GL_ARG_NONNULL ((2)) size_t
 mbstoc32s (char32_t *dest, const char *src, size_t len)
 {
@@ -510,6 +549,7 @@ mbstoc32s (char32_t *dest, const char *src, size_t len)
   memset (&state, '\0', sizeof (mbstate_t));
   return mbsrtoc32s (dest, &src, len, &state);
 }
+_GL_END_C_LINKAGE
 # else
 _GL_FUNCDECL_SYS (mbstoc32s, size_t,
                   (char32_t *dest, const char *src, size_t len)
diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4
index c84a2afd9c..0df2181871 100644
--- a/m4/gnulib-common.m4
+++ b/m4/gnulib-common.m4
@@ -1,4 +1,4 @@
-# gnulib-common.m4 serial 82
+# gnulib-common.m4 serial 83
 dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -527,6 +527,18 @@ AC_DEFUN([gl_COMMON_BODY], [
 #  define _GL_UNUSED_LABEL
 # endif
 #endif
+])
+  AH_VERBATIM([c_linkage],
+[/* In C++, there is the concept of "language linkage", that encompasses
+    name mangling and function calling conventions.
+    The following macros start and end a block of "C" linkage.  */
+#ifdef __cplusplus
+# define _GL_BEGIN_C_LINKAGE extern "C" {
+# define _GL_END_C_LINKAGE }
+#else
+# define _GL_BEGIN_C_LINKAGE
+# define _GL_END_C_LINKAGE
+#endif
 ])
   AH_VERBATIM([async_safe],
 [/* The _GL_ASYNC_SAFE marker should be attached to functions that are






reply via email to

[Prev in Thread] Current Thread [Next in Thread]