This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH] support: Add TEST_COMPARE macro
- From: Paul Eggert <eggert at cs dot ucla dot edu>
- To: Florian Weimer <fweimer at redhat dot com>, Siddhesh Poyarekar <siddhesh at gotplt dot org>, GNU C Library <libc-alpha at sourceware dot org>
- Cc: Adhemerval Zanella <adhemerval dot zanella at linaro dot org>
- Date: Fri, 1 Dec 2017 11:05:58 -0800
- Subject: Re: [PATCH] support: Add TEST_COMPARE macro
- Authentication-results: sourceware.org; auth=none
- References: <8d63a2dc-f9e9-acaa-5ac5-ac5c4fbd6c9f@redhat.com> <8c399cde-3093-0195-a89a-ca230540cffb@gotplt.org> <8339a519-935a-019c-4a8f-798e37f6f346@redhat.com> <5c5fbfc4-0077-22ad-1fd4-53388acaf1e7@cs.ucla.edu> <c51c9a5a-29f2-6461-3a53-f91868b222ca@redhat.com> <96692ad0-180c-6e7c-79c8-e5c96d79e34c@cs.ucla.edu> <7e965c74-8113-72b9-276c-baa031df007e@redhat.com> <24bc9987-5af7-6e8a-9b3d-aeae4a45f60a@cs.ucla.edu> <aa669215-dd46-18c8-07bb-94a67092fc73@redhat.com> <72d1c0c0-44b3-69f7-7630-0d47be285a30@cs.ucla.edu> <f0593826-1721-d424-905c-6755b813bbf7@redhat.com> <2b76ec51-8dac-2fc9-ba32-512fdfbec2ff@cs.ucla.edu> <17e4d3db-8a69-e50c-07b1-71e1e8739d9d@redhat.com> <742d0fab-b17e-a7f5-62df-d87510454aa4@cs.ucla.edu> <c71a4c4e-764a-9756-bcc5-fe3e6369af6f@redhat.com>
On 12/01/2017 07:53 AM, Florian Weimer wrote:
+/* Compare the two integers LEFT and RIGHT and report failure if they
+ are different. */
+#define TEST_COMPARE(left, right) \
+ ({ \
+ typedef __typeof__ (left) __left_type; \
+ typedef __typeof__ (right) __right_type; \
+ __left_type __left_value = (left); \
+ __right_type __right_value = (right); \
+ /* Prevent use with floating-point and boolean types. */ \
Why prevent booleans? They don't have problems when compared as integers.
+ _Static_assert ((__left_type) 0.1 == (__left_type) 0, \
+ "left value has floating-point type"); \
I suggest changing this to something like "(__left_type) 1.5 ==
(__left_type) 1", so that boolean types are allowed, and so that the
expression matches the string.
+ /* Make sure that type promotion does not alter the sign. */ \
+ enum \
+ { \
+ __left_is_unsigned = (__left_type) -1 > 0, \
+ __right_is_unsigned = (__right_type) -1 > 0, \
+ __left_promotes_to_right = __left_is_unsigned \
+ && sizeof (__left_value) < sizeof (__right_value), \
+ __right_promotes_to_left = __right_is_unsigned \
+ && sizeof (__right_value) < sizeof (__left_value) \
+ }; \
+ _Static_assert (__left_is_unsigned == __right_is_unsigned \
+ || __left_promotes_to_right \
+ || __right_promotes_to_left, \
+ "integer promotion may alter sign of operands"); \
This confuses integer promotion (which always converts to int or to
unsigned) with the usual integer conversions (which can convert to a
type wider than int or unsigned int). Integer promotion does not cause
any problems that TEST_COMPARE is trying to detect; on the contrary,
promotion helps to prevent such problems.
For example, if __left_value is signed char and __right_value is
unsigned short and unsigned short is narrower than int, the static
assertion will fail even though the comparison is safe because both
operands are promoted to int before comparison.
Please see the proposal in
<https://sourceware.org/ml/libc-alpha/2017-11/msg00903.html>, which
should do the right thing for such cases.