From 0c845aa291230cace495d06ac5465bd3ccb99319 Mon Sep 17 00:00:00 2001 From: Alex Ozdemir Date: Thu, 2 Aug 2018 00:25:07 -0700 Subject: [PATCH] Bugfix: Math function checking We had config machinery that determined which math functions are available in libc. If a c math function was missing on the host system, then the corresponding jq function would be removed from the source, enabling the build to proceed anyway. The detection machinery was broken in a subtle way, as was shown after glibc updated to 2.27, dropping the `pow10` function. This caused compilation to fail. The essential problem was that we detected whether a math function was available by compiling and linking a small program evaluating that function on constants. However, since gcc's optimization machinery has special knowledge of some math functions (e.g. `pow10`), it can optimize them away, even if they don't exist in the library and are not linkable. That is, the following example compiles and links against glibc 2.27, even though `pow10` has been removed: ``` int main () { printf("%f", pow10(0.5)); return 0; } ``` What?! On the other hand, this program does not link: ``` int main () { double f; printf("%f", &f); printf("%f", pow10(f)); return 0; } ``` In the first program the call to `pow10` can be optimized away as a constant expression. This requires GCC to know about `pow10` (which it does!), but it does not require `pow10` to be in the library (and actually linkable). The solution is to use autoconf's machinery for detecting function presence, instead of our own (buggy) machinery. This has the added benefit of simplifying the code. The bug was reported in issue #1659 --- config/m4/check-math-func.m4 | 9 ++- configure.ac | 124 +++++++++++++++++------------------ 2 files changed, 69 insertions(+), 64 deletions(-) diff --git a/config/m4/check-math-func.m4 b/config/m4/check-math-func.m4 index ce632726ce..5677cedef5 100644 --- a/config/m4/check-math-func.m4 +++ b/config/m4/check-math-func.m4 @@ -1,4 +1,9 @@ -dnl AC_FIND_FUNC(func, arguments) +dnl AC_CHECK_MATH_FUNC(func) AC_DEFUN([AC_CHECK_MATH_FUNC], [ - AC_FIND_FUNC_NO_LIBS([$1], [m], [#include ], [$2]) + AC_LANG(C) + AC_CHECK_LIB([m],[$1],[ + eval "ac_tr_func=HAVE_[]upcase($1)" + AC_DEFINE_UNQUOTED($ac_tr_func) + ],[ + ]) ]) diff --git a/configure.ac b/configure.ac index 9186d00dc5..280694ce6f 100644 --- a/configure.ac +++ b/configure.ac @@ -148,68 +148,68 @@ if test $enable_pthread_tls = yes; then fi dnl libm math.h functions -AC_CHECK_MATH_FUNC(acos, [.5]) -AC_CHECK_MATH_FUNC(acosh, [.5]) -AC_CHECK_MATH_FUNC(asin, [.5]) -AC_CHECK_MATH_FUNC(asinh, [.5]) -AC_CHECK_MATH_FUNC(atan2, [.5,.5]) -AC_CHECK_MATH_FUNC(atan, [.5]) -AC_CHECK_MATH_FUNC(atanh, [.5]) -AC_CHECK_MATH_FUNC(cbrt, [.5]) -AC_CHECK_MATH_FUNC(ceil,[.5]) -AC_CHECK_MATH_FUNC(copysign,[.5,1.0]) -AC_CHECK_MATH_FUNC(cos, [.5]) -AC_CHECK_MATH_FUNC(cosh, [.5]) -AC_CHECK_MATH_FUNC(drem,[.5,1.0]) -AC_CHECK_MATH_FUNC(erf,[.5]) -AC_CHECK_MATH_FUNC(erfc,[.5]) -AC_CHECK_MATH_FUNC(exp10,[.5]) -AC_CHECK_MATH_FUNC(exp2, [.5]) -AC_CHECK_MATH_FUNC(exp, [.5]) -AC_CHECK_MATH_FUNC(expm1,[.5]) -AC_CHECK_MATH_FUNC(fabs,[.5]) -AC_CHECK_MATH_FUNC(fdim,[.5,1.0]) -AC_CHECK_MATH_FUNC(floor, [.5]) -AC_CHECK_MATH_FUNC(fma,[.5,1.0,1.5]) -AC_CHECK_MATH_FUNC(fmax,[.5,1.0]) -AC_CHECK_MATH_FUNC(fmin,[.5,1.0]) -AC_CHECK_MATH_FUNC(fmod,[.5,1.0]) -AC_FIND_FUNC([frexp], [m c], [#include ], [0, 0]) -AC_CHECK_MATH_FUNC(gamma,[.5]) -AC_CHECK_MATH_FUNC(hypot, [.5,.5]) -AC_CHECK_MATH_FUNC(j0, [.5]) -AC_CHECK_MATH_FUNC(j1, [.5]) -AC_CHECK_MATH_FUNC(jn, [1,.5]) -AC_CHECK_MATH_FUNC(ldexp,[.5,2]) -AC_CHECK_MATH_FUNC(lgamma,[.5]) -AC_CHECK_MATH_FUNC(log10, [.5]) -AC_CHECK_MATH_FUNC(log1p,[.5]) -AC_CHECK_MATH_FUNC(log2, [.5]) -AC_CHECK_MATH_FUNC(log, [.5]) -AC_CHECK_MATH_FUNC(logb,[.5]) -AC_CHECK_MATH_FUNC([modf], [m c], [#include ], [0, 0]) -AC_CHECK_MATH_FUNC([lgamma_r], [m c], [#include ], [0, 0]) -AC_CHECK_MATH_FUNC(nearbyint,[.5]) -AC_CHECK_MATH_FUNC(nextafter,[.5,1.0]) -AC_CHECK_MATH_FUNC(nexttoward,[.5,1.0]) -AC_CHECK_MATH_FUNC(pow10,[.5]) -AC_CHECK_MATH_FUNC(pow, [2,2]) -AC_CHECK_MATH_FUNC(remainder, [3,2]) -AC_CHECK_MATH_FUNC(rint,[.5]) -AC_CHECK_MATH_FUNC(round,[.5]) -AC_CHECK_MATH_FUNC(scalb,[.5,1.0]) -AC_CHECK_MATH_FUNC(scalbln,[.5,2]) -AC_CHECK_MATH_FUNC(significand,[.5]) -AC_CHECK_MATH_FUNC(sin, [.5]) -AC_CHECK_MATH_FUNC(sinh, [.5]) -AC_CHECK_MATH_FUNC(sqrt, [.5]) -AC_CHECK_MATH_FUNC(tan, [.5]) -AC_CHECK_MATH_FUNC(tanh, [.5]) -AC_CHECK_MATH_FUNC(tgamma, [.5]) -AC_CHECK_MATH_FUNC(trunc,[.5]) -AC_CHECK_MATH_FUNC(y0, [.5]) -AC_CHECK_MATH_FUNC(y1, [.5]) -AC_CHECK_MATH_FUNC(yn, [1,.5]) +AC_CHECK_MATH_FUNC(acos) +AC_CHECK_MATH_FUNC(acosh) +AC_CHECK_MATH_FUNC(asin) +AC_CHECK_MATH_FUNC(asinh) +AC_CHECK_MATH_FUNC(atan2) +AC_CHECK_MATH_FUNC(atan) +AC_CHECK_MATH_FUNC(atanh) +AC_CHECK_MATH_FUNC(cbrt) +AC_CHECK_MATH_FUNC(ceil) +AC_CHECK_MATH_FUNC(copysign) +AC_CHECK_MATH_FUNC(cos) +AC_CHECK_MATH_FUNC(cosh) +AC_CHECK_MATH_FUNC(drem) +AC_CHECK_MATH_FUNC(erf) +AC_CHECK_MATH_FUNC(erfc) +AC_CHECK_MATH_FUNC(exp10) +AC_CHECK_MATH_FUNC(exp2) +AC_CHECK_MATH_FUNC(exp) +AC_CHECK_MATH_FUNC(expm1) +AC_CHECK_MATH_FUNC(fabs) +AC_CHECK_MATH_FUNC(fdim) +AC_CHECK_MATH_FUNC(floor) +AC_CHECK_MATH_FUNC(fma) +AC_CHECK_MATH_FUNC(fmax) +AC_CHECK_MATH_FUNC(fmin) +AC_CHECK_MATH_FUNC(fmod) +AC_CHECK_MATH_FUNC(frexp) +AC_CHECK_MATH_FUNC(gamma) +AC_CHECK_MATH_FUNC(hypot) +AC_CHECK_MATH_FUNC(j0) +AC_CHECK_MATH_FUNC(j1) +AC_CHECK_MATH_FUNC(jn) +AC_CHECK_MATH_FUNC(ldexp) +AC_CHECK_MATH_FUNC(lgamma) +AC_CHECK_MATH_FUNC(log10) +AC_CHECK_MATH_FUNC(log1p) +AC_CHECK_MATH_FUNC(log2) +AC_CHECK_MATH_FUNC(log) +AC_CHECK_MATH_FUNC(logb) +AC_CHECK_MATH_FUNC(modf) +AC_CHECK_MATH_FUNC(lgamma_r) +AC_CHECK_MATH_FUNC(nearbyint) +AC_CHECK_MATH_FUNC(nextafter) +AC_CHECK_MATH_FUNC(nexttoward) +AC_CHECK_MATH_FUNC(pow10) # Not available with glibc version >= 2.27 +AC_CHECK_MATH_FUNC(pow) +AC_CHECK_MATH_FUNC(remainder) +AC_CHECK_MATH_FUNC(rint) +AC_CHECK_MATH_FUNC(round) +AC_CHECK_MATH_FUNC(scalb) +AC_CHECK_MATH_FUNC(scalbln) +AC_CHECK_MATH_FUNC(significand) +AC_CHECK_MATH_FUNC(sin) +AC_CHECK_MATH_FUNC(sinh) +AC_CHECK_MATH_FUNC(sqrt) +AC_CHECK_MATH_FUNC(tan) +AC_CHECK_MATH_FUNC(tanh) +AC_CHECK_MATH_FUNC(tgamma) +AC_CHECK_MATH_FUNC(trunc) +AC_CHECK_MATH_FUNC(y0) +AC_CHECK_MATH_FUNC(y1) +AC_CHECK_MATH_FUNC(yn) dnl Thread local storage have___thread=no