[PATCH] Provide a C++ version of iseqsig
Gabriel F. T. Gomes
gabriel@inconstante.eti.br
Fri Nov 3 13:16:00 GMT 2017
I would like to receive some feedback on the correctness of this
implementation, more specifically on the correctness of any implicit
type conversions, which I might have missed. I'm working on a test case
in the meantime (I only did some standalone tests outside of glibc test
suite).
-- 8< --
In C++ mode, __MATH_TG cannot be used for defining iseqsig, because
__MATH_TG relies on __builtin_types_compatible_p, which is a C-only
builtin. This is true when float128 is provided as an ABI-distinct type
from long double.
Moreover, the comparison macros from ISO C take two floating-point
arguments, which need not have the same type. Choosing what underlying
function to call requires evaluating the formats of the arguments, then
selecting which is wider. The macro __MATH_EVAL_FMT2 provides this
information, however, only the type of the macro expansion is relevant
(actually evaluating the expression would be incorrect).
This patch provides a C++ version of iseqsig, in which only the type
resulted from a call to __MATH_EVAL_FMT2 is used as an additional
argument, fmt, to the helper function, __iseqsig_type. This function
is overloaded, in compilation-time, to the floating-point type specified
by the fmt argument, then calls the appropriate underlying function (the
type of the arguments is left unchanged with the help of templates).
Tested for powerpc64le and x86_64.
[BZ #22377]
* math/math.h [C++] (iseqsig): New implementation, which does
not rely on __MATH_TG/__builtin_types_compatible_p.
---
math/math.h | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 49 insertions(+), 1 deletion(-)
diff --git a/math/math.h b/math/math.h
index 326fd8ebe1..4744f9a4c9 100644
--- a/math/math.h
+++ b/math/math.h
@@ -1152,8 +1152,56 @@ iszero (__T __val)
/* Return X == Y but raising "invalid" and setting errno if X or Y is
a NaN. */
+# ifndef __cplusplus
+# define iseqsig(x, y) \
+ __MATH_TG (__MATH_EVAL_FMT2 (x, y), __iseqsig, ((x), (y)))
+# else
+/* In C++ mode, __MATH_TG cannot be used, because it relies on
+ __builtin_types_compatible_p, which is a C-only builtin. Moreover,
+ the comparison macros from ISO C take two floating-point arguments,
+ which need not have the same type. Choosing what underlying function
+ to call requires evaluating the formats of the arguments, then
+ selecting which is wider. The macro __MATH_EVAL_FMT2 provides this
+ information, however, only the type of the macro expansion is
+ relevant (actually evaluating the expression would be incorrect).
+ Thus, the type is used in an additional argument, fmt, to the helper
+ function, __iseqsig_type, which is overloaded in compilation-time for
+ the correct floating-point type, then calls the appropriate
+ underlying function (the type of the arguments is unchanged with the
+ help of templates). */
+extern "C++" {
+template <typename __T1, typename __T2> inline int
+__iseqsig_type (float fmt, __T1 x, __T2 y)
+{
+ return __iseqsigf (x, y);
+}
+template <typename __T1, typename __T2> inline int
+__iseqsig_type (double fmt, __T1 x, __T2 y)
+{
+ return __iseqsig (x, y);
+}
+template <typename __T1, typename __T2> inline int
+__iseqsig_type (long double fmt, __T1 x, __T2 y)
+{
+# ifdef __NO_LONG_DOUBLE_MATH
+ return __iseqsig (x, y);
+# else
+ return __iseqsigl (x, y);
+# endif
+}
+# if __HAVE_DISTINCT_FLOAT128
+template <typename __T1, typename __T2> inline int
+__iseqsig_type (_Float128 fmt, __T1 x, __T2 y)
+{
+ return __iseqsigf128 (x, y);
+}
+# endif
+}
+# endif
+
# define iseqsig(x, y) \
- __MATH_TG (__MATH_EVAL_FMT2 (x, y), __iseqsig, ((x), (y)))
+ __iseqsig_type (__MATH_EVAL_FMT2 (x, y), x, y)
+
#endif
__END_DECLS
--
2.13.6
More information about the Libc-alpha
mailing list