From 16fbac39ff68a737317f6fc7be78cc93a14856af Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 19 Nov 2018 12:01:47 -0500 Subject: [PATCH] Fix configure's AC_CHECK_DECLS tests to work correctly with clang. The test case that Autoconf uses to discover whether a function has been declared doesn't work reliably with clang, because clang reports a warning not an error if the name is a known built-in function. On some platforms, this results in a lot of compile-time warnings about strlcpy and related functions not having been declared. There is a fix for this (by Noah Misch) in the upstream Autoconf sources, but since they've not made a release in years and show no indication of doing so anytime soon, let's just absorb their fix directly. We can revert this when and if we update to a newer Autoconf release. Back-patch to all supported branches. Discussion: https://postgr.es/m/26819.1542515567@sss.pgh.pa.us --- aclocal.m4 | 1 + config/check_decls.m4 | 116 ++++++++++++++++++++++++++++++++++++++++++ configure | 104 +++++++++++++++++++++++++++++++++++-- configure.in | 9 ++-- 4 files changed, 223 insertions(+), 7 deletions(-) create mode 100644 config/check_decls.m4 diff --git a/aclocal.m4 b/aclocal.m4 index a517e949f1..bfd34ecec8 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -4,6 +4,7 @@ m4_include([config/ax_prog_perl_modules.m4]) 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 new file mode 100644 index 0000000000..f1b90c5430 --- /dev/null +++ b/config/check_decls.m4 @@ -0,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 . + +# 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 +#include +#include +#include +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 67b7700862..a87f0865f5 100755 --- a/configure +++ b/configure @@ -1756,13 +1756,16 @@ fi 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/ *(.*//'` + # 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 @@ -1787,6 +1790,7 @@ else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_werror_flag fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 @@ -4990,11 +4994,100 @@ fi 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 +#include +#include +#include +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 : + if test -z "$LLVM_CONFIG"; then for ac_prog in llvm-config llvm-config-7 llvm-config-6.0 llvm-config-5.0 llvm-config-4.0 llvm-config-3.9 do @@ -5250,7 +5343,8 @@ _ACEOF -fi + +fi # fi unset CFLAGS @@ -15197,7 +15291,8 @@ esac # posix_fadvise() is a no-op on Solaris, so don't incur function overhead # by calling it, 2009-04-02 # http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/gen/posix_fadvise.c -if test "$PORTNAME" != "solaris"; then +if test "$PORTNAME" != "solaris"; then : + for ac_func in posix_fadvise do : ac_fn_c_check_func "$LINENO" "posix_fadvise" "ac_cv_func_posix_fadvise" @@ -15221,7 +15316,8 @@ cat >>confdefs.h <<_ACEOF #define HAVE_DECL_POSIX_FADVISE $ac_have_decl _ACEOF -fi + +fi # fi ac_fn_c_check_decl "$LINENO" "fdatasync" "ac_cv_have_decl_fdatasync" "#include " diff --git a/configure.in b/configure.in index feaf2aa682..2b71019fd1 100644 --- a/configure.in +++ b/configure.in @@ -392,7 +392,9 @@ PGAC_ARG_BOOL(with, llvm, no, [build with LLVM based JIT support], [AC_DEFINE([USE_LLVM], 1, [Define to 1 to build with LLVM based JIT support. (--with-llvm)])]) AC_SUBST(with_llvm) dnl must use AS_IF here, else AC_REQUIRES inside PGAC_LLVM_SUPPORT malfunctions -AS_IF([test "$with_llvm" = yes], [PGAC_LLVM_SUPPORT()]) +AS_IF([test "$with_llvm" = yes], [ + PGAC_LLVM_SUPPORT() +]) # fi unset CFLAGS @@ -1640,10 +1642,11 @@ esac # posix_fadvise() is a no-op on Solaris, so don't incur function overhead # by calling it, 2009-04-02 # http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/gen/posix_fadvise.c -if test "$PORTNAME" != "solaris"; then +dnl must use AS_IF here, else AC_REQUIRES inside AC_CHECK_DECLS malfunctions +AS_IF([test "$PORTNAME" != "solaris"], [ AC_CHECK_FUNCS(posix_fadvise) AC_CHECK_DECLS(posix_fadvise, [], [], [#include ]) -fi +]) # fi AC_CHECK_DECLS(fdatasync, [], [], [#include ]) AC_CHECK_DECLS([strlcat, strlcpy, strnlen])