On Thursday 30 of January 2020, Stephan Bergmann wrote:
On 30/01/2020 12:56, Luboš Luňák wrote:
This contradicts your original mail, where you stated that what is used
is "if (sal_uInt32(e1) < e2) ... // (B)" (i.e. without the <0 check).
And
Maybe it is unclear, but my original mail was talking about a "correct"
comparison
e1 < e2
(i.e., where it is known that e1 >= 0, but where compilers might
nevertheless emit a signed-vs.-unsigned warning).
Then make_unsigned() covers a smaller problem area than make_signed(), which
covers all cases except for the exceptional totally huge value cases. I.e.
with make_signed() you practically do not need to care what the values in "e1
< e2" are. Why make API that requires caring about the value when there can
be API that makes it practically irrelevant?
It doesn't pretend any more than make_unsigned() does. It's just that
it's harder to accidentally break its requirements in practice.
...while it's probably easier to write code that is guaranteed to comply
with the make_unsigned preconditions.
No? I'd have to try really hard to write realistic code that uses highest bit
set in a large unsigned non-bitfield variable.
(Also, I have no idea what the usage patterns for actual types S1 and U2
are. For usages with small U2,
Small unsigned types are promoted at least to int. If needed, make_signed()
can promote them to long long if needed (probably not). And if they are to be
compared using <, then their usage pattern will be that U2 is a count of
something.
or e2 obtained from tainted sources,
casting to S2 may well be an issue wrt preconditions.)
Such as?
But people will not consistently use (*), because it's more
error-prone, longer to type and harder to read (yeah, we're all lazy).
Using just "e1 < S1
I'm not sure about that. As I wrote, I saw lots of occurrences of (*)
across the LO code base.
And how many occurences that do not do (*) have you seen? (I have no idea how
to reasonably search for those).
(And, again, people writing broken code is
something that o3tl::make_unsigned cannot and will not address.)
And, yet, o3tl::make_signed would address that, for all cases that matter.
(e2)" can assert in S1 and then the only disadvantage there I can see is
if somebody actually somehow manages to trigger the assert =>
make_signed() is the better API.
I don't understand the above sentence; what do you mean with "can assert
in S1"?
e2 > std::numeric_limits<S1>::max() || e1 < S1(e2)
can be rewritten as
S1 make_signed(U2 v) { assert( v <= std::numeric_limits<S1>::max()); return
v; }
and then
e1 < make_signed(e2)
pretty much always does the job. And we'll probably hit the 25th LO
anniversary sooner than this assert.
--
Luboš Luňák
l.lunak@collabora.com
Context
Privacy Policy |
Impressum (Legal Info) |
Copyright information: Unless otherwise specified, all text and images
on this website are licensed under the
Creative Commons Attribution-Share Alike 3.0 License.
This does not include the source code of LibreOffice, which is
licensed under the Mozilla Public License (
MPLv2).
"LibreOffice" and "The Document Foundation" are
registered trademarks of their corresponding registered owners or are
in actual use as trademarks in one or more countries. Their respective
logos and icons are also subject to international copyright laws. Use
thereof is explained in our
trademark policy.