-
Notifications
You must be signed in to change notification settings - Fork 455
Reducing Warnings - Safe Integral Comparisons #960
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have made some suggested changes based on what appear to be missing unsigned specifiers. Though, I may be mistaken so I am going to go ahead and approve the PR and leave it up to you to decide whether my suggestions are appropriate.
src/libbson/tests/test-bson-cmp.c
Outdated
BSON_ASSERT (!bson_cmp_less_ss (1, -1)); | ||
BSON_ASSERT (!bson_cmp_less_ss (1, 1)); | ||
|
||
BSON_ASSERT (!bson_cmp_less_uu (0u, 0)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BSON_ASSERT (!bson_cmp_less_uu (0u, 0)); | |
BSON_ASSERT (!bson_cmp_less_uu (0u, 0u)); |
src/libbson/tests/test-bson-cmp.c
Outdated
BSON_ASSERT (bson_cmp_greater_ss (1, -1)); | ||
BSON_ASSERT (!bson_cmp_greater_ss (1, 1)); | ||
|
||
BSON_ASSERT (!bson_cmp_greater_uu (0u, 0)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BSON_ASSERT (!bson_cmp_greater_uu (0u, 0)); | |
BSON_ASSERT (!bson_cmp_greater_uu (0u, 0u)); |
src/libbson/tests/test-bson-cmp.c
Outdated
BSON_ASSERT (!bson_cmp_less_equal_ss (1, -1)); | ||
BSON_ASSERT (bson_cmp_less_equal_ss (1, 1)); | ||
|
||
BSON_ASSERT (bson_cmp_less_equal_uu (0u, 0)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BSON_ASSERT (bson_cmp_less_equal_uu (0u, 0)); | |
BSON_ASSERT (bson_cmp_less_equal_uu (0u, 0u)); |
src/libbson/tests/test-bson-cmp.c
Outdated
BSON_ASSERT (bson_cmp_greater_equal_ss (1, -1)); | ||
BSON_ASSERT (bson_cmp_greater_equal_ss (1, 1)); | ||
|
||
BSON_ASSERT (bson_cmp_greater_equal_uu (0u, 0)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BSON_ASSERT (bson_cmp_greater_equal_uu (0u, 0)); | |
BSON_ASSERT (bson_cmp_greater_equal_uu (0u, 0u)); |
|
||
BSON_ASSERT (bson_in_range_unsigned (int32_t, 0u)); | ||
BSON_ASSERT (bson_in_range_unsigned (int32_t, (uint64_t) int32_max)); | ||
BSON_ASSERT (!bson_in_range_unsigned (int32_t, (uint64_t) (int32_max + 1))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BSON_ASSERT (!bson_in_range_unsigned (int32_t, (uint64_t) (int32_max + 1))); | |
BSON_ASSERT (!bson_in_range_unsigned (int32_t, (uint64_t) (int32_max + 1u))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
int32_max
is an int64_t
(signed), so a signed integer literal is appropriate here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Passing 0
to unsigned parameter is benign since 0 is guaranteed to be representable regardless of signedness, but for consistency, I agree it would be good to update the literals with unsigned suffixes. (Hurray for copy-paste errors...)
|
||
BSON_ASSERT (bson_in_range_unsigned (int32_t, 0u)); | ||
BSON_ASSERT (bson_in_range_unsigned (int32_t, (uint64_t) int32_max)); | ||
BSON_ASSERT (!bson_in_range_unsigned (int32_t, (uint64_t) (int32_max + 1))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
int32_max
is an int64_t
(signed), so a signed integer literal is appropriate here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Nicely done. I think bson-cmp.h
is going to be useful. I have two comments, but nothing to block merge.
src/libbson/src/bson/bson-cmp.h
Outdated
return bson_cmp_greater_equal_uu (value, 0u) && \ | ||
bson_cmp_less_equal_uu (value, max); \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return bson_cmp_greater_equal_uu (value, 0u) && \ | |
bson_cmp_less_equal_uu (value, max); \ | |
return bson_cmp_less_equal_uu (value, max); \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SGTM.
BSON_ASSERT (!bson_in_range_signed (int8_t, int8_max + 1)); | ||
|
||
BSON_ASSERT (bson_in_range_unsigned (int8_t, 0u)); | ||
BSON_ASSERT (bson_in_range_unsigned (int8_t, (uint64_t) int8_max)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest removing unnecessary cast to uint64_t
for consistency with other calls. Here and below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These casts are necesary, as the intN_min
and intN_max
variables are signed integers. Without the casts, the arguments will produce implicit sign conversion warnings from int64_t
to uint64_t
.
This is part of a series of PRs intended to reduce the set of warnings currently being observed when building the C driver.
This PR introduces a set of utilities modeled after the Safe Integral Comparisons proposal for the C++ standard library, which was accepted and merged into the C++20 standard. These utilities are extremely useful in addressing warnings involving comparisons or conversions between integers with different signedness and sizes.
The interface proposed in the original paper relies on type deduction to select appropriate behavior according to the signedness and size of the given arguments:
As C does not have type deduction required to support this interface, two major compromises are made instead:
int64_t
oruint64_t
as specified by (1) before further analysis.Therefore, the equivalent code to the above example given
A = int16_t
andB = uint32_t
looks like the following:where the
_su
suffix indicatesa
is signed andb
is unsigned.The set of supported types is also limited to the following:
ssize_t
andsize_t
.More types may be added if needed, so long as for the given type
T
,sizeof (T) <= sizeof (uint64_t)
is true and its representable range is known and defined with corresponding*_MIN
and*_MAX
macros.To support the
std::in_range
set of functions even on C90 (where the necessary<limits.h>
and<stdint.h>
macros may not be defined), the corresponding set of numeric limit macros have been added to bson-compat.h, including those forssize_t
(note:SSIZE_MIN
is normally not defined even by the POSIX standard). The preprocessor block conditioned on!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
may be removed once the minimum C standard for the C driver is bumped to C99 or newer.