[PATCH v3] Provide a C++ version of iseqsig
Florian Weimer
fweimer@redhat.com
Tue Nov 14 13:35:00 GMT 2017
On 11/14/2017 02:21 PM, Gabriel F. T. Gomes wrote:
> diff --git a/math/math.h b/math/math.h
> index 326fd8ebe1..acc909d37f 100644
> --- a/math/math.h
> +++ b/math/math.h
> @@ -1152,8 +1152,76 @@ iszero (__T __val)
>
> /* Return X == Y but raising "invalid" and setting errno if X or Y is
> a NaN. */
> -# define iseqsig(x, y) \
> - __MATH_TG (__MATH_EVAL_FMT2 (x, y), __iseqsig, ((x), (y)))
> +# if !defined __cplusplus || (__cplusplus < 201103L && !defined __GNUC__)
> +# 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 as a template parameter for __iseqsig_type,
> + which calls the appropriate underlying function. */
> +template<typename _T1, typename _T2>
> +inline int
> +iseqsig(_T1 __x, _T2 __y) throw()
> +{
> +# if __cplusplus >= 201103L
> + typedef __decltype (__MATH_EVAL_FMT2 (__x, __y)) _T3;
> +# else
> + typedef __typeof (__MATH_EVAL_FMT2 (__x, __y)) _T3;
> +# endif
> + return __iseqsig_type<_T3>::__call(__x, __y);
> +}
> +
> +} /* extern "C++" */
> +# endif /* __cplusplus */
Would these two expressions have the same types, assuming _T1 and _T2
are the template parameters from the iseqsig definition?
__MATH_EVAL_FMT2 (__x, __y)
__MATH_EVAL_FMT2 (_T1 (), _T2 ())
I believe the second expression would be safe to evaluate, so it could
be used to select a suitable inline function. This would then work with
any C++ version.
But the current approach is okay as well.
> diff --git a/math/test-math-iseqsig.cc b/math/test-math-iseqsig.cc
> new file mode 100644
> index 0000000000..0316340638
> --- /dev/null
> +++ b/math/test-math-iseqsig.cc
> +static bool errors;
Maybe use support_record_failure from <support/check.h> instead?
> +static void
> +check (int actual, int expected, const char *actual_expr, int line)
> +{
> + if (actual != expected)
> + {
> + errors = true;
> + printf ("%s:%d: error: %s\n", __FILE__, line, actual_expr);
> + printf ("%s:%d: expected: %d\n", __FILE__, line, expected);
> + printf ("%s:%d: actual: %d\n", __FILE__, line, actual);
> + }
> +}
> +
> +#define CHECK(actual, expected) \
> + check ((actual), (expected), #actual, __LINE__)
I think my memory protection key patches contain a more general
implementation of this called TEST_COMPARE. Adhemerval requested just a
minor documentation change, so I could commit that separately if you
want to use it.
Thanks,
Florian
More information about the Libc-alpha
mailing list