Building a gnulib testdir on native Windows, with clang and the MSVC header files, I get these errors:
source='../../gltests/test-string-c++.cc' object='test-string-c++.obj' libtool=no \ DEPDIR=.deps depmode=msvc7 /bin/sh ../../build-aux/depcomp \ /home/bruno/msvc/compile clang-cl -ferror-limit=0 -DHAVE_CONFIG_H -DEXEEXT=\".exe\" -I. -I../../gltests -I.. -DGNULIB_STRICT_CHECKING=1 -DIN_GNULIB_TESTS=1 -I. -I../../gltests -I.. -I../../gltests/.. -I../gllib -I../../gltests/../gllib -D_WIN32_WINNT=_WIN32_WINNT_WIN7 -I/usr/local/msvcclang64/include -Wall -Wno-extra-semi-stmt -Wno-unused-function -Wno-inconsistent-dllimport -Wno-reserved-id-macro -Wno-undef -Wno-missing-field-initializers -Wno-unused-parameter -Wno-gnu-include-next -Wno-implicit-int-conversion -Wno-sign-compare -Wno-sign-conversion -Wno-comma -Wno-unused-macros -Wno-nonportable-system-include-path -Wno-format-nonliteral -Wno-deprecated-declarations -Wno-tautological-unsigned-zero-compare -Wno-used-but-marked-unused -Wno-parentheses-equality -Wno-error -MD -O2 -c -o test-string-c++.obj `cygpath -w '../../gltests/test-string-c++.cc'` In file included from C:\cygwin64\home\bruno\testdir-all-windows\gltests\test-string-c++.cc:22: ../gllib\string.h(1107,19): error: no member named 'strndup' in the global namespace; did you mean 'strdup'? _GL_CXXALIAS_SYS (strndup, char *, (char const *__s, size_t __n)); ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ strdup ../gllib\string.h(322,20): note: expanded from macro '_GL_CXXALIAS_SYS' return ::func; \ ~~^ ../gllib\string.h(1026,19): note: 'strdup' declared here _GL_CXXALIASWARN (strdup); ^ ../gllib\string.h(1107,1): error: cannot initialize return object of type 'gnulib::_gl_strndup_wrapper::type' (aka 'char *(*)(const char *, unsigned long long)') with an lvalue of type 'typeof (strdup)' (aka 'char *(const char *)'): different number of parameters (2 vs 1) _GL_CXXALIAS_SYS (strndup, char *, (char const *__s, size_t __n)); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../gllib\string.h(322,18): note: expanded from macro '_GL_CXXALIAS_SYS' return ::func; \ ^~~~~~ ../gllib\string.h(1109,19): error: use of undeclared identifier 'strndup'; did you mean 'strdup'? _GL_CXXALIASWARN (strndup); ^~~~~~~ strdup ../gllib\string.h(394,24): note: expanded from macro '_GL_CXXALIASWARN' _GL_CXXALIASWARN_1 (func, GNULIB_NAMESPACE) ^ ../gllib\string.h(396,24): note: expanded from macro '_GL_CXXALIASWARN_1' _GL_CXXALIASWARN_2 (func, namespace) ^ ../gllib\string.h(401,22): note: expanded from macro '_GL_CXXALIASWARN_2' _GL_WARN_ON_USE (func, \ ^ ../gllib\string.h(564,31): note: expanded from macro '_GL_WARN_ON_USE' _GL_WARN_EXTERN_C __typeof__ (function) function \ ^ ../gllib\string.h(1026,19): note: 'strdup' declared here _GL_CXXALIASWARN (strdup); ^ ../gllib\string.h(1109,19): warning: The symbol ::strdup refers to the system function. Use gnulib::strdup instead. [-Wuser-defined-warnings] _GL_CXXALIASWARN (strndup); ^ ../gllib\string.h(1026,1): note: from 'diagnose_if' attribute on 'strdup': _GL_CXXALIASWARN (strdup); ^~~~~~~~~~~~~~~~~~~~~~~~~ ../gllib\string.h(394,4): note: expanded from macro '_GL_CXXALIASWARN' _GL_CXXALIASWARN_1 (func, GNULIB_NAMESPACE) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../gllib\string.h(396,4): note: expanded from macro '_GL_CXXALIASWARN_1' _GL_CXXALIASWARN_2 (func, namespace) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../gllib\string.h(401,5): note: expanded from macro '_GL_CXXALIASWARN_2' _GL_WARN_ON_USE (func, \ ^~~~~~~~~~~~~~~~~~~~~~~~ ../gllib\string.h(565,19): note: expanded from macro '_GL_WARN_ON_USE' __attribute__ ((__diagnose_if__ (1, message, "warning"))) ^ ~ 65 warnings and 3 errors generated. make[4]: *** [Makefile:23359: test-string-c++.obj] Error 1 The cause is that the MSVC header files don't declare strndup(), and with MSVC accordingly HAVE_DECL_STRNDUP is 0, but with clang, HAVE_DECL_STRNDUP is 1. The cause is that the clang compiler provides implicit function declarations of many ISO C functions (see the -fno-builtin-* command line options [1]). See: =============== foo.c =================== #include <string.h> int main () { #undef strndup (void) strndup; } ========================================= clang: foo.c(4,10): warning: implicitly declaring library function 'strndup' with type 'char *(const char *, unsigned long long)' [-Wimplicit-function-declaration] (void) strndup; ^ foo.c(4,10): note: include the header <string.h> or explicitly provide a declaration for 'strndup' 1 warning generated. Thus, clang "invents" a declaration when there is none. $ clang -Wall -fno-builtin-strndup foo.c foo.c:4:10: error: use of undeclared identifier 'strndup' (void) strndup; ^ 1 error generated. The problem is that these implicit function declarations are present in C mode but not in C++ mode. Thus, the effects of HAVE_DECL_STRNDUP being 1 are neutralized in C mode (by precisely these implicit function declarations), but not in C++ mode. Put differently: Gnulib assumes that the value of HAVE_DECL_STRNDUP is valid equally in C mode and in C++ mode; which it isn't here. The main macro which defines HAVE_DECL_STRNDUP is AC_CHECK_DECL, and we have a workaround for these implicit function declarations since 2020 [2]. A similar workaround also went into Autoconf 2.71. (It uses clang's -fno-builtin option; earlier it used -Werror. See [3].) What's the problem, then? It is that the gl_WARN_ON_USE_PREPARE macro, which also checks for declarations and sets ac_cv_decl_strndup as a "shortcut", does not have a clang workaround. This patch fixes it. [1] https://clang.llvm.org/docs/ClangCommandLineReference.html [2] https://lists.gnu.org/archive/html/bug-gnulib/2020-01/msg00030.html [3] https://lists.gnu.org/archive/html/autoconf-patches/2015-04/msg00022.html 2022-09-20 Bruno Haible <br...@clisp.org> snippet/warn-on-use: Don't cause wrong AC_CHECK_DECL results with clang. * m4/warn-on-use.m4 (gl_WARN_ON_USE_PREPARE): Use the clang command-line option that disables implicit built-in function declarations in clang. diff --git a/m4/warn-on-use.m4 b/m4/warn-on-use.m4 index d43355ab17..a81731f31c 100644 --- a/m4/warn-on-use.m4 +++ b/m4/warn-on-use.m4 @@ -1,4 +1,4 @@ -# warn-on-use.m4 serial 9 +# warn-on-use.m4 serial 10 dnl Copyright (C) 2010-2022 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -32,17 +32,30 @@ AC_DEFUN([gl_WARN_ON_USE_PREPARE], undefining macros.])])dnl for gl_func in m4_flatten([$2]); do AS_VAR_PUSHDEF([gl_Symbol], [gl_cv_have_raw_decl_$gl_func])dnl + dnl As a workaround to implicit built-in function declarations in + dnl clang (e.g. strndup), reference ac_compile_for_check_decl instead + dnl of ac_compile. If, for whatever reason, the override of AC_PROG_CC + dnl in zzgnulib.m4 is inactive, use the original ac_compile. + ac_save_ac_compile="$ac_compile" + if test -n "$ac_compile_for_check_decl"; then + ac_compile="$ac_compile_for_check_decl" + fi AC_CACHE_CHECK([whether $gl_func is declared without a macro], [gl_Symbol], [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$1], [[#undef $gl_func (void) $gl_func;]])], [AS_VAR_SET([gl_Symbol], [yes])], [AS_VAR_SET([gl_Symbol], [no])])]) + ac_compile="$ac_save_ac_compile" AS_VAR_IF([gl_Symbol], [yes], [AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_RAW_DECL_$gl_func]), [1]) - dnl shortcut - if the raw declaration exists, then set a cache - dnl variable to allow skipping any later AC_CHECK_DECL efforts - eval ac_cv_have_decl_$gl_func=yes]) + dnl Shortcut for an AC_CHECK_DECL invocation that may come later: + dnl If the raw declaration exists with the given includes, then + dnl AC_CHECK_DECL with its many includes would see it as well. + dnl So, set a cache variable to allow skipping any later + dnl AC_CHECK_DECL invocation for $gl_func. + eval "ac_cv_have_decl_$gl_func=yes" + ]) AS_VAR_POPDEF([gl_Symbol])dnl done ])