[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
snippet/warn-on-use: Don't cause wrong AC_CHECK_DECL results with clang
From: |
Bruno Haible |
Subject: |
snippet/warn-on-use: Don't cause wrong AC_CHECK_DECL results with clang |
Date: |
Tue, 20 Sep 2022 23:47:41 +0200 |
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 <bruno@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
])
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- snippet/warn-on-use: Don't cause wrong AC_CHECK_DECL results with clang,
Bruno Haible <=