Thread: Fixing AC_CHECK_DECLS to do the right thing with clang

Fixing AC_CHECK_DECLS to do the right thing with clang

From
Tom Lane
Date:
We've seen repeated complaints about bogus build warnings when using
"clang": it complains that strlcpy and some related library functions
haven't been declared.  Several of the buildfarm animals exhibit such
warnings, for instance.  That's because Autoconf's AC_CHECK_DECLS macro
fails to cope with the fact that clang only generates a warning, not
an error, for the test case that that macro uses.  Noah fixed this
in upstream autoconf several years ago:

http://git.savannah.gnu.org/cgit/autoconf.git/commit/?id=82ef7805faffa151e724aa76c245ec590d174580

However, I'm beginning to despair of the Autoconf crowd ever putting
out an official new release.  Hence, I propose to apply and back-patch
the attached, which essentially just imports Noah's fix into our
configure script.  I've verified that this does the right thing with
Fedora 28's version of clang (clang version 6.0.1).

            regards, tom lane

diff --git a/aclocal.m4 b/aclocal.m4
index a517e94..bfd34ec 100644
*** a/aclocal.m4
--- b/aclocal.m4
*************** m4_include([config/ax_prog_perl_modules.
*** 4,9 ****
--- 4,10 ----
  m4_include([config/ax_pthread.m4])
  m4_include([config/c-compiler.m4])
  m4_include([config/c-library.m4])
+ m4_include([config/check_decls.m4])
  m4_include([config/docbook.m4])
  m4_include([config/general.m4])
  m4_include([config/libtool.m4])
diff --git a/config/check_decls.m4 b/config/check_decls.m4
index ...0dda18b .
*** a/config/check_decls.m4
--- b/config/check_decls.m4
***************
*** 0 ****
--- 1,116 ----
+ # config/check_decls.m4
+
+ # This file redefines the standard Autoconf macro _AC_CHECK_DECL_BODY,
+ # and adds a supporting function _AC_UNDECLARED_WARNING, to make
+ # AC_CHECK_DECLS behave correctly when checking for built-in library
+ # functions with clang.
+
+ # This is based on commit 82ef7805faffa151e724aa76c245ec590d174580
+ # in the Autoconf git repository.  We can drop it if they ever get
+ # around to releasing a new version of Autoconf.  In the meantime,
+ # it's distributed under Autoconf's license:
+
+ # This file is part of Autoconf.  This program is free
+ # software; you can redistribute it and/or modify it under the
+ # terms of the GNU General Public License as published by the
+ # Free Software Foundation, either version 3 of the License, or
+ # (at your option) any later version.
+ #
+ # This program is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ # GNU General Public License for more details.
+ #
+ # Under Section 7 of GPL version 3, you are granted additional
+ # permissions described in the Autoconf Configure Script Exception,
+ # version 3.0, as published by the Free Software Foundation.
+ #
+ # You should have received a copy of the GNU General Public License
+ # and a copy of the Autoconf Configure Script Exception along with
+ # this program; see the files COPYINGv3 and COPYING.EXCEPTION
+ # respectively.  If not, see <http://www.gnu.org/licenses/>.
+
+ # Written by David MacKenzie, with help from
+ # Franc,ois Pinard, Karl Berry, Richard Pixley, Ian Lance Taylor,
+ # Roland McGrath, Noah Friedman, david d zuhn, and many others.
+
+
+ # _AC_UNDECLARED_WARNING
+ # ----------------------
+ # Set ac_[]_AC_LANG_ABBREV[]_decl_warn_flag=yes if the compiler uses a warning,
+ # not a more-customary error, to report some undeclared identifiers.  Fail when
+ # an affected compiler warns also on valid input.  _AC_PROG_PREPROC_WORKS_IFELSE
+ # solves a related problem.
+ AC_DEFUN([_AC_UNDECLARED_WARNING],
+ [# The Clang compiler raises a warning for an undeclared identifier that matches
+ # a compiler builtin function.  All extant Clang versions are affected, as of
+ # Clang 3.6.0.  Test a builtin known to every version.  This problem affects the
+ # C and Objective C languages, but Clang does report an error under C++ and
+ # Objective C++.
+ #
+ # Passing -fno-builtin to the compiler would suppress this problem.  That
+ # strategy would have the advantage of being insensitive to stray warnings, but
+ # it would make tests less realistic.
+ AC_CACHE_CHECK([how $[]_AC_CC[] reports undeclared, standard C functions],
+ [ac_cv_[]_AC_LANG_ABBREV[]_decl_report],
+ [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [(void) strchr;])],
+   [AS_IF([test -s conftest.err], [dnl
+     # For AC_CHECK_DECL to react to warnings, the compiler must be silent on
+     # valid AC_CHECK_DECL input.  No library function is consistently available
+     # on freestanding implementations, so test against a dummy declaration.
+     # Include always-available headers on the off chance that they somehow
+     # elicit warnings.
+     AC_COMPILE_IFELSE([AC_LANG_PROGRAM([dnl
+ #include <float.h>
+ #include <limits.h>
+ #include <stdarg.h>
+ #include <stddef.h>
+ extern void ac_decl (int, char *);],
+ [@%:@ifdef __cplusplus
+   (void) ac_decl ((int) 0, (char *) 0);
+   (void) ac_decl;
+ @%:@else
+   (void) ac_decl;
+ @%:@endif
+ ])],
+       [AS_IF([test -s conftest.err],
+     [AC_MSG_FAILURE([cannot detect from compiler exit status or warnings])],
+     [ac_cv_[]_AC_LANG_ABBREV[]_decl_report=warning])],
+       [AC_MSG_FAILURE([cannot compile a simple declaration test])])],
+     [AC_MSG_FAILURE([compiler does not report undeclared identifiers])])],
+   [ac_cv_[]_AC_LANG_ABBREV[]_decl_report=error])])
+
+ case $ac_cv_[]_AC_LANG_ABBREV[]_decl_report in
+   warning) ac_[]_AC_LANG_ABBREV[]_decl_warn_flag=yes ;;
+   *) ac_[]_AC_LANG_ABBREV[]_decl_warn_flag= ;;
+ esac
+ ])# _AC_UNDECLARED_WARNING
+
+ # _AC_CHECK_DECL_BODY
+ # -------------------
+ # Shell function body for AC_CHECK_DECL.
+ m4_define([_AC_CHECK_DECL_BODY],
+ [  AS_LINENO_PUSH([$[]1])
+   # Initialize each $ac_[]_AC_LANG_ABBREV[]_decl_warn_flag once.
+   AC_DEFUN([_AC_UNDECLARED_WARNING_]_AC_LANG_ABBREV,
+        [_AC_UNDECLARED_WARNING])dnl
+   AC_REQUIRE([_AC_UNDECLARED_WARNING_]_AC_LANG_ABBREV)dnl
+   [as_decl_name=`echo $][2|sed 's/ *(.*//'`]
+   [as_decl_use=`echo $][2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`]
+   AC_CACHE_CHECK([whether $as_decl_name is declared], [$[]3],
+   [ac_save_werror_flag=$ac_[]_AC_LANG_ABBREV[]_werror_flag
+   ac_[]_AC_LANG_ABBREV[]_werror_flag="$ac_[]_AC_LANG_ABBREV[]_decl_warn_flag$ac_[]_AC_LANG_ABBREV[]_werror_flag"
+   AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$[]4],
+ [@%:@ifndef $[]as_decl_name
+ @%:@ifdef __cplusplus
+   (void) $[]as_decl_use;
+ @%:@else
+   (void) $[]as_decl_name;
+ @%:@endif
+ @%:@endif
+ ])],
+            [AS_VAR_SET([$[]3], [yes])],
+            [AS_VAR_SET([$[]3], [no])])])
+   ac_[]_AC_LANG_ABBREV[]_werror_flag=$ac_save_werror_flag
+   AS_LINENO_POP
+ ])# _AC_CHECK_DECL_BODY
diff --git a/configure b/configure
index 67b7700..cf4954f 100755
*** a/configure
--- b/configure
*************** fi
*** 1756,1768 ****
  ac_fn_c_check_decl ()
  {
    as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
!   as_decl_name=`echo $2|sed 's/ *(.*//'`
    as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
  $as_echo_n "checking whether $as_decl_name is declared... " >&6; }
  if eval \${$3+:} false; then :
    $as_echo_n "(cached) " >&6
  else
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
  /* end confdefs.h.  */
  $4
--- 1756,1771 ----
  ac_fn_c_check_decl ()
  {
    as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
!   # Initialize each $ac_[]_AC_LANG_ABBREV[]_decl_warn_flag once.
!       as_decl_name=`echo $2|sed 's/ *(.*//'`
    as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
  $as_echo_n "checking whether $as_decl_name is declared... " >&6; }
  if eval \${$3+:} false; then :
    $as_echo_n "(cached) " >&6
  else
+   ac_save_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag="$ac_c_decl_warn_flag$ac_c_werror_flag"
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
  /* end confdefs.h.  */
  $4
*************** fi
*** 1791,1796 ****
--- 1794,1800 ----
  eval ac_res=\$$3
             { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
  $as_echo "$ac_res" >&6; }
+   ac_c_werror_flag=$ac_save_werror_flag
    eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

  } # ac_fn_c_check_decl
*************** fi
*** 4990,4995 ****
--- 4994,5087 ----
    test -n "$AWK" && break
  done

+ # The Clang compiler raises a warning for an undeclared identifier that matches
+ # a compiler builtin function.  All extant Clang versions are affected, as of
+ # Clang 3.6.0.  Test a builtin known to every version.  This problem affects the
+ # C and Objective C languages, but Clang does report an error under C++ and
+ # Objective C++.
+ #
+ # Passing -fno-builtin to the compiler would suppress this problem.  That
+ # strategy would have the advantage of being insensitive to stray warnings, but
+ # it would make tests less realistic.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking how $CC reports undeclared, standard C functions" >&5
+ $as_echo_n "checking how $CC reports undeclared, standard C functions... " >&6; }
+ if ${ac_cv_c_decl_report+:} false; then :
+   $as_echo_n "(cached) " >&6
+ else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+
+ int
+ main ()
+ {
+ (void) strchr;
+   ;
+   return 0;
+ }
+ _ACEOF
+ if ac_fn_c_try_compile "$LINENO"; then :
+   if test -s conftest.err; then :
+       # For AC_CHECK_DECL to react to warnings, the compiler must be silent on
+     # valid AC_CHECK_DECL input.  No library function is consistently available
+     # on freestanding implementations, so test against a dummy declaration.
+     # Include always-available headers on the off chance that they somehow
+     # elicit warnings.
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ #include <float.h>
+ #include <limits.h>
+ #include <stdarg.h>
+ #include <stddef.h>
+ extern void ac_decl (int, char *);
+ int
+ main ()
+ {
+ #ifdef __cplusplus
+   (void) ac_decl ((int) 0, (char *) 0);
+   (void) ac_decl;
+ #else
+   (void) ac_decl;
+ #endif
+
+   ;
+   return 0;
+ }
+ _ACEOF
+ if ac_fn_c_try_compile "$LINENO"; then :
+   if test -s conftest.err; then :
+   { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+ $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ as_fn_error $? "cannot detect from compiler exit status or warnings
+ See \`config.log' for more details" "$LINENO" 5; }
+ else
+   ac_cv_c_decl_report=warning
+ fi
+ else
+   { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+ $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ as_fn_error $? "cannot compile a simple declaration test
+ See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ else
+   { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+ $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ as_fn_error $? "compiler does not report undeclared identifiers
+ See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ else
+   ac_cv_c_decl_report=error
+ fi
+ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_decl_report" >&5
+ $as_echo "$ac_cv_c_decl_report" >&6; }
+
+ case $ac_cv_c_decl_report in
+   warning) ac_c_decl_warn_flag=yes ;;
+   *) ac_c_decl_warn_flag= ;;
+ esac
+
  if test "$with_llvm" = yes; then :



Re: Fixing AC_CHECK_DECLS to do the right thing with clang

From
Andres Freund
Date:
Hi,

On 2018-11-17 23:32:47 -0500, Tom Lane wrote:
> We've seen repeated complaints about bogus build warnings when using
> "clang": it complains that strlcpy and some related library functions
> haven't been declared.  Several of the buildfarm animals exhibit such
> warnings, for instance.  That's because Autoconf's AC_CHECK_DECLS macro
> fails to cope with the fact that clang only generates a warning, not
> an error, for the test case that that macro uses.  Noah fixed this
> in upstream autoconf several years ago:
> 
> http://git.savannah.gnu.org/cgit/autoconf.git/commit/?id=82ef7805faffa151e724aa76c245ec590d174580
> 
> However, I'm beginning to despair of the Autoconf crowd ever putting
> out an official new release.  Hence, I propose to apply and back-patch
> the attached, which essentially just imports Noah's fix into our
> configure script.  I've verified that this does the right thing with
> Fedora 28's version of clang (clang version 6.0.1).

Seems like a good plan. The problem doesn't reproduce for me on debian
(using any version of clang), so all I can report is that at patched
build still works as it should.

- Andres


Re: Fixing AC_CHECK_DECLS to do the right thing with clang

From
Tom Lane
Date:
Andres Freund <andres@anarazel.de> writes:
> Seems like a good plan. The problem doesn't reproduce for me on debian
> (using any version of clang), so all I can report is that at patched
> build still works as it should.

Interesting.  It's hardly surprising that the problem would occur only
on some platforms, since if <string.h> declares the function then the
problem isn't visible.  But I'm surprised that some Debian boxes would
show it and some not.  Still, a closer look at the buildfarm shows both
clang-on-Debian members with the warning (eg gull) and clang-on-Debian
members without (eg yours).

            regards, tom lane