changeset 15982:a63613865d90

isfinite, isinf, isnan, signbit: Don't define as a macro in C++. * lib/math.in.h (_GL_MATH_CXX_REAL_FLOATING_DECL_1, _GL_MATH_CXX_REAL_FLOATING_DECL_2): nEW MACROS. (isfinite, isinf, isnan, signbit): In C++, define as overloaded functions, not as a macro. * tests/test-math-c++.cc (REAL_FLOATING_CHECK, OVERLOADED_CHECK): New macros. (isfinite, isinf, isnan, signbit): Check overloaded functions and absence of macro. Suggested by Eric Blake. Reported by Michael Goffioul <michael.goffioul@gmail.com>.
author Bruno Haible <bruno@clisp.org>
date Sat, 22 Oct 2011 13:52:56 +0200
parents f47b68339daa
children 19adf9aa1ea0
files ChangeLog lib/math.in.h tests/test-math-c++.cc
diffstat 3 files changed, 120 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2011-10-22  Bruno Haible  <bruno@clisp.org>
+
+	isfinite, isinf, isnan, signbit: Don't define as a macro in C++.
+	* lib/math.in.h (_GL_MATH_CXX_REAL_FLOATING_DECL_1,
+	_GL_MATH_CXX_REAL_FLOATING_DECL_2): nEW MACROS.
+	(isfinite, isinf, isnan, signbit): In C++, define as overloaded
+	functions, not as a macro.
+	* tests/test-math-c++.cc (REAL_FLOATING_CHECK, OVERLOADED_CHECK): New
+	macros.
+	(isfinite, isinf, isnan, signbit): Check overloaded functions and
+	absence of macro.
+	Suggested by Eric Blake.
+	Reported by Michael Goffioul <michael.goffioul@gmail.com>.
+
 2011-10-21  Bruno Haible  <bruno@clisp.org>
 
 	relocatable-prog-wrapper: Don't leave object files behind.
--- a/lib/math.in.h
+++ b/lib/math.in.h
@@ -35,6 +35,44 @@
 
 /* The definition of _GL_WARN_ON_USE is copied here.  */
 
+#ifdef __cplusplus
+/* Helper macros to define type-generic function FUNC as overloaded functions,
+   rather than as macros like in C.  POSIX declares these with an argument of
+   real-floating (that is, one of float, double, or long double).  */
+# define _GL_MATH_CXX_REAL_FLOATING_DECL_1(func) \
+static inline int                                                   \
+_gl_cxx_ ## func ## f (float f)                                     \
+{                                                                   \
+  return func (f);                                                  \
+}                                                                   \
+static inline int                                                   \
+_gl_cxx_ ## func ## d (double d)                                    \
+{                                                                   \
+  return func (d);                                                  \
+}                                                                   \
+static inline int                                                   \
+_gl_cxx_ ## func ## l (long double l)                               \
+{                                                                   \
+  return func (l);                                                  \
+}
+# define _GL_MATH_CXX_REAL_FLOATING_DECL_2(func) \
+inline int                                                          \
+func (float f)                                                      \
+{                                                                   \
+  return _gl_cxx_ ## func ## f (f);                                 \
+}                                                                   \
+inline int                                                          \
+func (double d)                                                     \
+{                                                                   \
+  return _gl_cxx_ ## func ## d (d);                                 \
+}                                                                   \
+inline int                                                          \
+func (long double l)                                                \
+{                                                                   \
+  return _gl_cxx_ ## func ## l (l);                                 \
+}
+#endif
+
 /* Helper macros to define a portability warning for the
    classification macro FUNC called with VALUE.  POSIX declares the
    classification macros with an argument of real-floating (that is,
@@ -1030,6 +1068,13 @@
     sizeof (x) == sizeof (double) ? gl_isfinited (x) : \
     gl_isfinitef (x))
 # endif
+# ifdef __cplusplus
+#  ifdef isfinite
+_GL_MATH_CXX_REAL_FLOATING_DECL_1 (isfinite)
+#   undef isfinite
+_GL_MATH_CXX_REAL_FLOATING_DECL_2 (isfinite)
+#  endif
+# endif
 #elif defined GNULIB_POSIXCHECK
 # if defined isfinite
 _GL_WARN_REAL_FLOATING_DECL (isfinite);
@@ -1050,6 +1095,13 @@
     sizeof (x) == sizeof (double) ? gl_isinfd (x) : \
     gl_isinff (x))
 # endif
+# ifdef __cplusplus
+#  ifdef isinf
+_GL_MATH_CXX_REAL_FLOATING_DECL_1 (isinf)
+#   undef isinf
+_GL_MATH_CXX_REAL_FLOATING_DECL_2 (isinf)
+#  endif
+# endif
 #elif defined GNULIB_POSIXCHECK
 # if defined isinf
 _GL_WARN_REAL_FLOATING_DECL (isinf);
@@ -1161,9 +1213,17 @@
     sizeof (x) == sizeof (double) ? __builtin_isnan ((double)(x)) : \
     __builtin_isnanf ((float)(x)))
 # endif
+# ifdef __cplusplus
+#  ifdef isnan
+_GL_MATH_CXX_REAL_FLOATING_DECL_1 (isnan)
+#   undef isnan
+_GL_MATH_CXX_REAL_FLOATING_DECL_2 (isnan)
+#  endif
+# else
 /* Ensure isnan is a macro.  */
-# ifndef isnan
-#  define isnan isnan
+#  ifndef isnan
+#   define isnan isnan
+#  endif
 # endif
 #elif defined GNULIB_POSIXCHECK
 # if defined isnan
@@ -1227,6 +1287,13 @@
     sizeof (x) == sizeof (double) ? gl_signbitd (x) : \
     gl_signbitf (x))
 # endif
+# ifdef __cplusplus
+#  ifdef signbit
+_GL_MATH_CXX_REAL_FLOATING_DECL_1 (signbit)
+#   undef signbit
+_GL_MATH_CXX_REAL_FLOATING_DECL_2 (signbit)
+#  endif
+# endif
 #elif defined GNULIB_POSIXCHECK
 # if defined signbit
 _GL_WARN_REAL_FLOATING_DECL (signbit);
--- a/tests/test-math-c++.cc
+++ b/tests/test-math-c++.cc
@@ -23,6 +23,18 @@
 
 #include "signature.h"
 
+/* Signature check for a function that takes a real-floating argument.
+   Check that each overloaded function with the specified signature exists.  */
+#define REAL_FLOATING_CHECK(func,\
+                            rettype1, parameters1,\
+                            rettype2, parameters2,\
+                            rettype3, parameters3) \
+  OVERLOADED_CHECK (func, rettype1, parameters1, _1); \
+  OVERLOADED_CHECK (func, rettype2, parameters2, _2); \
+  OVERLOADED_CHECK (func, rettype3, parameters3, _3)
+#define OVERLOADED_CHECK(func, rettype, parameters, suffix) \
+  static rettype (* _GL_UNUSED signature_check_ ## func ## suffix) parameters \
+    = static_cast<rettype(*)parameters>(func)
 
 #if GNULIB_TEST_ACOSF
 SIGNATURE_CHECK (GNULIB_NAMESPACE::acosf, float, (float));
@@ -76,6 +88,24 @@
 SIGNATURE_CHECK (GNULIB_NAMESPACE::frexp, double, (double, int *));
 #endif
 //SIGNATURE_CHECK (GNULIB_NAMESPACE::hypot, double, (double, double));
+#if GNULIB_TEST_ISFINITE
+# ifdef isfinite
+#  error "isfinite should not be a macro in C++"
+# endif
+REAL_FLOATING_CHECK (isfinite, int, (float), int, (double), int, (long double));
+#endif
+#if GNULIB_TEST_ISINF
+# ifdef isinf
+#  error "isinf should not be a macro in C++"
+# endif
+REAL_FLOATING_CHECK (isinf, int, (float), int, (double), int, (long double));
+#endif
+#if GNULIB_TEST_ISNAN
+# ifdef isnan
+#  error "isnan should not be a macro in C++"
+# endif
+REAL_FLOATING_CHECK (isnan, int, (float), int, (double), int, (long double));
+#endif
 //SIGNATURE_CHECK (GNULIB_NAMESPACE::j0, double, (double));
 //SIGNATURE_CHECK (GNULIB_NAMESPACE::j1, double, (double));
 //SIGNATURE_CHECK (GNULIB_NAMESPACE::jn, double, (int, double));
@@ -211,6 +241,13 @@
 SIGNATURE_CHECK (GNULIB_NAMESPACE::roundl, long double, (long double));
 #endif
 
+#if GNULIB_TEST_SIGNBIT
+# ifdef signbit
+#  error "signbit should not be a macro in C++"
+# endif
+REAL_FLOATING_CHECK (signbit, int, (float), int, (double), int, (long double));
+#endif
+
 #if GNULIB_TEST_SINL
 SIGNATURE_CHECK (GNULIB_NAMESPACE::sinl, long double, (long double));
 #endif