diff mbox series

Define HAVE_ for math long double functions declared in vxworks headers

Message ID or7e2k3o1z.fsf@livre.home
State New
Headers show
Series Define HAVE_ for math long double functions declared in vxworks headers | expand

Commit Message

Alexandre Oliva Dec. 25, 2019, 6:40 a.m. UTC
When cross-building for vxworks, test for declarations of long double
functions in math.h.  We don't normally test for these functions when
cross compiling, because link tests don't work, or ever really, but
not defining them as available causes replacements to be defined in
ways that may cause duplicate definition linker errors if the units
defining both the replacement and the actual implementation are
brought in because of other symbols.

Tested on trunk by checking configure results of libstdc++-v3 for an
affected target, and also building natively on x86_64-linux-gnu.  Also
tested for various cross configurations far more thoroughly on trees not
matching trunk so closely.  I'm checking this in.


libstdc++-v3/
	* crossconfig.m4 (GLIBCXX_CROSSCONFIG) [*-vxworks*]: Define
	long double functions as available if declared by math.h.
	(GLIBCXX_CHECK_MATH_DECL, GLIBCXX_CHECK_MATH_DECLS): New.
	* configure: Rebuild.
---
 libstdc++-v3/configure      | 1104 +++++++++++++++++++++++++++++++++++++++++++
 libstdc++-v3/crossconfig.m4 |   62 ++
 2 files changed, 1166 insertions(+)

Comments

Jonathan Wakely Jan. 3, 2020, 3:27 p.m. UTC | #1
On 25/12/19 03:40 -0300, Alexandre Oliva wrote:
>
>When cross-building for vxworks, test for declarations of long double
>functions in math.h.  We don't normally test for these functions when
>cross compiling, because link tests don't work, or ever really, but
>not defining them as available causes replacements to be defined in
>ways that may cause duplicate definition linker errors if the units
>defining both the replacement and the actual implementation are
>brought in because of other symbols.
>
>Tested on trunk by checking configure results of libstdc++-v3 for an
>affected target, and also building natively on x86_64-linux-gnu.  Also
>tested for various cross configurations far more thoroughly on trees not
>matching trunk so closely.  I'm checking this in.
>
>
>libstdc++-v3/
>	* crossconfig.m4 (GLIBCXX_CROSSCONFIG) [*-vxworks*]: Define
>	long double functions as available if declared by math.h.
>	(GLIBCXX_CHECK_MATH_DECL, GLIBCXX_CHECK_MATH_DECLS): New.
>	* configure: Rebuild.
>---
> libstdc++-v3/configure      | 1104 +++++++++++++++++++++++++++++++++++++++++++
> libstdc++-v3/crossconfig.m4 |   62 ++
> 2 files changed, 1166 insertions(+)
>
>diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
>[omitted]
>diff --git a/libstdc++-v3/crossconfig.m4 b/libstdc++-v3/crossconfig.m4
>index 5e24889..2a0cb04 100644
>--- a/libstdc++-v3/crossconfig.m4
>+++ b/libstdc++-v3/crossconfig.m4
>@@ -291,9 +291,71 @@ case "${host}" in
>     AC_DEFINE(HAVE_SQRTF)
>     AC_DEFINE(HAVE_TANF)
>     AC_DEFINE(HAVE_TANHF)
>+
>+dnl # Different versions and execution modes implement different
>+dnl # subsets of these functions.  Instead of hard-coding, test for C
>+dnl # declarations in headers.  The C primitives could be defined as
>+dnl # macros, in which case the tests might fail, and we might have to
>+dnl # switch to more elaborate tests.
>+    GLIBCXX_CHECK_MATH_DECLS([
>+      acosl asinl atan2l atanl ceill cosl coshl expl fabsl floorl fmodl
>+      frexpl ldexpl log10l logl modfl powl sinl sinhl sqrtl tanl tanhl])
>+dnl # sincosl is the only one missing here, compared with the *l
>+dnl # functions in the list guarded by
>+dnl # long_double_math_on_this_cpu in configure.ac, right after
>+dnl # the expansion of the present macro.
>     ;;
>   *)
>     AC_MSG_ERROR([No support for this host/target combination.])
>    ;;
> esac
> ])
>+
>+
>+dnl
>+dnl Check to see if the (math function) argument passed is
>+dnl declared when using the c compiler
>+dnl
>+dnl Define HAVE_CARGF etc if "cargf" is declared
>+dnl
>+dnl argument 1 is name of function to check
>+dnl
>+dnl ASSUMES argument is a math function
>+dnl
>+dnl GLIBCXX_CHECK_MATH_DECL
>+AC_DEFUN([GLIBCXX_CHECK_MATH_DECL], [
>+  AC_CACHE_CHECK([for $1 declaration],
>+    [glibcxx_cv_func_$1_use], [
>+      AC_LANG_SAVE
>+      AC_LANG_C
>+      AC_TRY_COMPILE([
>+#include <math.h>
>+#ifdef HAVE_IEEEFP_H
>+# include <ieeefp.h>
>+#endif
>+], [
>+  void (*f)(void) = (void (*)(void))$1;

I wondered whether using ($1) here instead of just $1 would give any
benefit. It would mean that function-like macros are ignored.

Maybe it would be better to just do #undef $1 before the test, so that
all macros are ignored. That would match the actual usage, as <cmath>
does a #undef for each function.
Alexandre Oliva Jan. 22, 2020, 12:50 a.m. UTC | #2
On Jan  3, 2020, Jonathan Wakely <jwakely@redhat.com> wrote:

>> +#include <math.h>
>> +#ifdef HAVE_IEEEFP_H
>> +# include <ieeefp.h>
>> +#endif
>> +], [
>> +  void (*f)(void) = (void (*)(void))$1;

> I wondered whether using ($1) here instead of just $1 would give any
> benefit. It would mean that function-like macros are ignored.

The lack of parentheses after a functional macro name is enough to avoid
its use as a macro.  However, the test I used wouldn't avoid aliasing
macros, such as #define foo bar, and it would pass even if the name was
defined as an object rather than as a function.

I've also come up with a way to test, during C compilation, that $1 is a
function rather than anything else.

If the test was in C++, we could presumably use template type resolution
and static asserts to recognize function-typed expressions, though a
possibility of overloading could make it fall apart.

In theory the closer we are to the environment in which the test result
will be used, the more likely we are to get the desired result, but I'm
a little concerned about switching to a C++ test, precisely because of
the math.h header that we might or might not override, and of unexpected
overloading that system math headers might offer if they are C++-ready,
which could then get us wrong test results.  Any thoughts on this
possibility?


Meanwhile, here's what I'm testing now...
It's supposed to be a strict incremental improvement, unless $1-&$1
unexpectedly compiles for some case I couldn't think of.

Ok to install?


reject macros in math decl check

From: Alexandre Oliva <oliva@adacore.com>

The C++ headers #undef the functions we are testing for, just in case
they're implemented as macros.  Do that as well, so as to reject
macros of the form #define foo bar, where bar is the actual
implementation, since those wouldn't work in C++ after the #undef.

While at that, tighten the test so that it doesn't take objects of
pointer types as if they were functions.


for  libstdc++-v3/ChangeLog

	* crossconfig.m4 (GLIBCXX_CHECK_MATH_DECL): Reject macros and
	data objects.
	* configure: Rebuild.
---
 configure      |   66 +++++++++++++++++++++++++++++++++++++-------------------
 crossconfig.m4 |   11 ++++++++-
 2 files changed, 54 insertions(+), 23 deletions(-)

diff --git libstdc++-v3/crossconfig.m4 libstdc++-v3/crossconfig.m4
index 2a0cb04..221b59d 100644
--- libstdc++-v3/crossconfig.m4
+++ libstdc++-v3/crossconfig.m4
@@ -322,6 +322,14 @@ dnl argument 1 is name of function to check
 dnl
 dnl ASSUMES argument is a math function
 dnl
+dnl Test for $1 - &$1: it's well-formed iff $1 names a function,
+dnl because $1's type decays to that of &$1.
+dnl For any object type, even arrays and void*, types won't match.
+dnl
+dnl Undefine $1, so that we don't accept an alias macro, e.g.
+dnl say define foo bar, when bar is the function.  Our C++ headers
+dnl undefine math function names, so such a macro wouldn't do.
+dnl
 dnl GLIBCXX_CHECK_MATH_DECL
 AC_DEFUN([GLIBCXX_CHECK_MATH_DECL], [
   AC_CACHE_CHECK([for $1 declaration],
@@ -333,8 +341,9 @@ AC_DEFUN([GLIBCXX_CHECK_MATH_DECL], [
 #ifdef HAVE_IEEEFP_H
 # include <ieeefp.h>
 #endif
+#undef $1
 ], [
-  void (*f)(void) = (void (*)(void))$1;
+  (void)($1 - &$1);
 ], [glibcxx_cv_func_$1_use=yes
 ], [glibcxx_cv_func_$1_use=no])])
   if test "x$glibcxx_cv_func_$1_use" = xyes; then
Jonathan Wakely Jan. 22, 2020, 10:18 a.m. UTC | #3
On 21/01/20 21:50 -0300, Alexandre Oliva wrote:
>On Jan  3, 2020, Jonathan Wakely <jwakely@redhat.com> wrote:
>
>>> +#include <math.h>
>>> +#ifdef HAVE_IEEEFP_H
>>> +# include <ieeefp.h>
>>> +#endif
>>> +], [
>>> +  void (*f)(void) = (void (*)(void))$1;
>
>> I wondered whether using ($1) here instead of just $1 would give any
>> benefit. It would mean that function-like macros are ignored.
>
>The lack of parentheses after a functional macro name is enough to avoid
>its use as a macro.  However, the test I used wouldn't avoid aliasing
>macros, such as #define foo bar, and it would pass even if the name was
>defined as an object rather than as a function.
>
>I've also come up with a way to test, during C compilation, that $1 is a
>function rather than anything else.
>
>If the test was in C++, we could presumably use template type resolution
>and static asserts to recognize function-typed expressions, though a
>possibility of overloading could make it fall apart.
>
>In theory the closer we are to the environment in which the test result
>will be used, the more likely we are to get the desired result, but I'm
>a little concerned about switching to a C++ test, precisely because of
>the math.h header that we might or might not override, and of unexpected
>overloading that system math headers might offer if they are C++-ready,
>which could then get us wrong test results.  Any thoughts on this
>possibility?
>
>
>Meanwhile, here's what I'm testing now...
>It's supposed to be a strict incremental improvement, unless $1-&$1
>unexpectedly compiles for some case I couldn't think of.

Isn't allowing arithmetic on function pointers a GNU extension? It
gets diagnosed with -pedantic.

I think just adding the #undef to what you had originally is the best
version.
Andreas Schwab Jan. 22, 2020, 10:23 a.m. UTC | #4
On Dez 25 2019, Alexandre Oliva wrote:

> +dnl # Different versions and execution modes implement different
> +dnl # subsets of these functions.  Instead of hard-coding, test for C
> +dnl # declarations in headers.  The C primitives could be defined as
> +dnl # macros, in which case the tests might fail, and we might have to
> +dnl # switch to more elaborate tests.
> +    GLIBCXX_CHECK_MATH_DECLS([
> +      acosl asinl atan2l atanl ceill cosl coshl expl fabsl floorl fmodl
> +      frexpl ldexpl log10l logl modfl powl sinl sinhl sqrtl tanl tanhl])

Why can't you use AC_CHECK_DECLS?

Andreas.
Alexandre Oliva Jan. 23, 2020, 3:20 a.m. UTC | #5
On Jan 22, 2020, Jonathan Wakely <jwakely@redhat.com> wrote:

> Isn't allowing arithmetic on function pointers a GNU extension?

Does that matter?  This test is only supposed to be compiled by GCC.


> I think just adding the #undef to what you had originally is the best
> version.

'k, thanks, will adjust, test, post and install.
Alexandre Oliva Jan. 23, 2020, 3:39 a.m. UTC | #6
On Jan 22, 2020, Andreas Schwab <schwab@suse.de> wrote:

> On Dez 25 2019, Alexandre Oliva wrote:
>> +dnl # Different versions and execution modes implement different
>> +dnl # subsets of these functions.  Instead of hard-coding, test for C
>> +dnl # declarations in headers.  The C primitives could be defined as
>> +dnl # macros, in which case the tests might fail, and we might have to
>> +dnl # switch to more elaborate tests.
>> +    GLIBCXX_CHECK_MATH_DECLS([
>> +      acosl asinl atan2l atanl ceill cosl coshl expl fabsl floorl fmodl
>> +      frexpl ldexpl log10l logl modfl powl sinl sinhl sqrtl tanl tanhl])

> Why can't you use AC_CHECK_DECLS?

IIRC it doesn't #undef, for one, but that's only relevant now.

I can't really recall whether using it even occurred to me, but a good
reason not to use it is that it defines HAVE_FUNCTION_DECL rather than
setting glibcxx_cv_func_$1_use={yes,no} and (through AC_CHECK_FUNCS)
HAVE_$1, like the preexisting macros in linkage.m4 we're substituting
for did before.

We could probably use AC_CHECK_DECL underneath, placing the #undef in
the INCLUDES argument.  Indeed, it looks like the GLIBCXX_CHECK_*_DECL_?
macros in linkage.m4 could use AC_CHECK_DECL as well.

Does anyone know of any reason for them not to use AC_CHECK_DECL
instead of open-coding the tests?


And then, shouldn't they also #undef the functions they're testing for?
Or should neither?  It doesn't feel right to add the #undef to the new
but otherwise identical compile test, just because it skips the link
test.
Jonathan Wakely Jan. 23, 2020, 12:25 p.m. UTC | #7
On 23/01/20 00:20 -0300, Alexandre Oliva wrote:
>On Jan 22, 2020, Jonathan Wakely <jwakely@redhat.com> wrote:
>
>> Isn't allowing arithmetic on function pointers a GNU extension?
>
>Does that matter?  This test is only supposed to be compiled by GCC.

Maybe if somebody was crazy enough to build GCC with -pedantic-errors?

>> I think just adding the #undef to what you had originally is the best
>> version.
>
>'k, thanks, will adjust, test, post and install.

Thanks.
Alexandre Oliva Jan. 23, 2020, 7:39 p.m. UTC | #8
On Jan 23, 2020, Jonathan Wakely <jwakely@redhat.com> wrote:

> On 23/01/20 00:20 -0300, Alexandre Oliva wrote:
>> On Jan 22, 2020, Jonathan Wakely <jwakely@redhat.com> wrote:
>> 
>>> Isn't allowing arithmetic on function pointers a GNU extension?
>> 
>> Does that matter?  This test is only supposed to be compiled by GCC.

> Maybe if somebody was crazy enough to build GCC with -pedantic-errors?

In TFLAGS while configuring libstdc++...  Yeah, that would fail.

>>> I think just adding the #undef to what you had originally is the best
>>> version.
>> 
>> 'k, thanks, will adjust, test, post and install.

> Thanks.

Here's the revised version I'm about to install...  Regstrapped on
x86_64-linux-gnu along with other patches, also retested on an affected
target.


reject macros in math decl check

From: Alexandre Oliva <oliva@adacore.com>

The C++ headers #undef the functions we are testing for, just in case
they're implemented as macros, so do that in the cross math decl tests
as well.


for  libstdc++-v3/ChangeLog

	* crossconfig.m4 (GLIBCXX_CHECK_MATH_DECL): Reject macros.
	* configure: Rebuild.
---
 libstdc++-v3/configure      |   22 ++++++++++++++++++++++
 libstdc++-v3/crossconfig.m4 |    1 +
 2 files changed, 23 insertions(+)

diff --git a/libstdc++-v3/crossconfig.m4 b/libstdc++-v3/crossconfig.m4
index 2a0cb04..fe18288 100644
--- a/libstdc++-v3/crossconfig.m4
+++ b/libstdc++-v3/crossconfig.m4
@@ -333,6 +333,7 @@ AC_DEFUN([GLIBCXX_CHECK_MATH_DECL], [
 #ifdef HAVE_IEEEFP_H
 # include <ieeefp.h>
 #endif
+#undef $1
 ], [
   void (*f)(void) = (void (*)(void))$1;
 ], [glibcxx_cv_func_$1_use=yes
diff mbox series

Patch

diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
[omitted]
diff --git a/libstdc++-v3/crossconfig.m4 b/libstdc++-v3/crossconfig.m4
index 5e24889..2a0cb04 100644
--- a/libstdc++-v3/crossconfig.m4
+++ b/libstdc++-v3/crossconfig.m4
@@ -291,9 +291,71 @@  case "${host}" in
     AC_DEFINE(HAVE_SQRTF)
     AC_DEFINE(HAVE_TANF)
     AC_DEFINE(HAVE_TANHF)
+
+dnl # Different versions and execution modes implement different
+dnl # subsets of these functions.  Instead of hard-coding, test for C
+dnl # declarations in headers.  The C primitives could be defined as
+dnl # macros, in which case the tests might fail, and we might have to
+dnl # switch to more elaborate tests.
+    GLIBCXX_CHECK_MATH_DECLS([
+      acosl asinl atan2l atanl ceill cosl coshl expl fabsl floorl fmodl
+      frexpl ldexpl log10l logl modfl powl sinl sinhl sqrtl tanl tanhl])
+dnl # sincosl is the only one missing here, compared with the *l
+dnl # functions in the list guarded by
+dnl # long_double_math_on_this_cpu in configure.ac, right after
+dnl # the expansion of the present macro.
     ;;
   *)
     AC_MSG_ERROR([No support for this host/target combination.])
    ;;
 esac
 ])
+
+
+dnl
+dnl Check to see if the (math function) argument passed is
+dnl declared when using the c compiler
+dnl
+dnl Define HAVE_CARGF etc if "cargf" is declared
+dnl
+dnl argument 1 is name of function to check
+dnl
+dnl ASSUMES argument is a math function
+dnl
+dnl GLIBCXX_CHECK_MATH_DECL
+AC_DEFUN([GLIBCXX_CHECK_MATH_DECL], [
+  AC_CACHE_CHECK([for $1 declaration],
+    [glibcxx_cv_func_$1_use], [
+      AC_LANG_SAVE
+      AC_LANG_C
+      AC_TRY_COMPILE([
+#include <math.h>
+#ifdef HAVE_IEEEFP_H
+# include <ieeefp.h>
+#endif
+], [
+  void (*f)(void) = (void (*)(void))$1;
+], [glibcxx_cv_func_$1_use=yes
+], [glibcxx_cv_func_$1_use=no])])
+  if test "x$glibcxx_cv_func_$1_use" = xyes; then
+    AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_$1]))
+  fi
+])
+
+dnl
+dnl Check to see whether multiple math functions are
+dnl declared when using the c compiler
+dnl
+dnl Define HAVE_CARGF HAVE_POWL etc if "cargf" and "powl"
+dnl are declared
+dnl
+dnl argument 1 is a word list naming function to check
+dnl
+dnl ASSUMES arguments are math functions
+dnl
+dnl GLIBCXX_CHECK_MATH_DECLS
+AC_DEFUN([GLIBCXX_CHECK_MATH_DECLS], [
+  m4_foreach_w([glibcxx_func], [$1], [
+    GLIBCXX_CHECK_MATH_DECL(glibcxx_func)
+  ])
+])