Richard Biener <[email protected]> writes:
> On Tue, Oct 24, 2017 at 3:24 PM, Richard Sandiford
> <[email protected]> wrote:
>> Richard Biener <[email protected]> writes:
>>> On Tue, Oct 24, 2017 at 2:48 PM, Richard Sandiford
>>> <[email protected]> wrote:
>>>> Richard Biener <[email protected]> writes:
>>>>> On Tue, Oct 24, 2017 at 1:23 PM, Richard Sandiford
>>>>> <[email protected]> wrote:
>>>>>> Eric Botcazou <[email protected]> writes:
>>>>>>>> Yeah. E.g. for ==, the two options would be:
>>>>>>>>
>>>>>>>> a) must_eq (a, b) -> a == b
>>>>>>>> must_ne (a, b) -> a != b
>>>>>>>>
>>>>>>>> which has the weird property that (a == b) != (!(a != b))
>>>>>>>>
>>>>>>>> b) must_eq (a, b) -> a == b
>>>>>>>> may_ne (a, b) -> a != b
>>>>>>>>
>>>>>>>> which has the weird property that a can be equal to b when a != b
>>>>>>>
>>>>>>> Yes, a) was the one I had in mind, i.e. the traditional operators are
>>>>>>> the must
>>>>>>> variants and you use an outer ! in order to express the may. Of
>>>>>>> course this
>>>>>>> would require a bit of discipline but, on the other hand, if most of
>>>>>>> the cases
>>>>>>> fall in the must category, that could be less ugly.
>>>>>>
>>>>>> I just think that discipline is going to be hard to maintain in practice,
>>>>>> since it's so natural to assume (a == b || a != b) == true. With the
>>>>>> may/must approach, static type checking forces the issue.
>>>>>>
>>>>>>>> Sorry about that. It's the best I could come up with without losing
>>>>>>>> the may/must distinction.
>>>>>>>
>>>>>>> Which variant is known_zero though? Must or may?
>>>>>>
>>>>>> must. maybe_nonzero is the may version.
>>>>>
>>>>> Can you rename known_zero to must_be_zero then?
>>>>
>>>> That'd be OK with me.
>>>>
>>>> Another alternative I wondered about was must_eq_0 / may_ne_0.
>>>>
>>>>> What's wrong with must_eq (X, 0) / may_eq (X, 0) btw?
>>>>
>>>> must_eq (X, 0) generated a warning if X is unsigned, so sometimes you'd
>>>> need must_eq (X, 0) and sometimes must_eq (X, 0U).
>>>
>>> Is that because they are templates? Maybe providing a partial
>>> specialization
>>> would help?
>>
>> I don't think it's templates specifically. We end up with something like:
>>
>> int f (unsigned int x, const int y)
>> {
>> return x != y;
>> }
>>
>> int g (unsigned int x) { return f (x, 0); }
>>
>> which generates a warning too.
>>
>>> I'd be fine with must_eq_p and may_eq_0.
>>
>> OK, I'll switch to that if there are no objections.
>
> Hum. But then we still warn for must_eq_p (x, 1), no?
Yeah. The patch also had a known_one and known_all_ones for
those two (fairly) common cases. For other values the patches
just add "U" where necessary.
If you think it would be better to use U consistently and not
have the helpers, then I'm happy to do that instead.
> So why does
>
> int f (unsigned int x)
> {
> return x != 0;
> }
>
> not warn? Probably because of promotion of the arg.
[Jakub's already answered this part.]
> Shouldn't we then simply never have a may/must_*_p (T1, T2)
> with T1 and T2 being not compatible? That is, force promotion
> rules on them with template magic?
This was what I meant by:
Or we could suppress warnings by forcibly converting the input.
Sometimes the warnings are useful though.
We already do this kind of conversion for arithmetic, to ensure
that poly_uint16 + poly_uint16 -> poly_int64 promotes before the
addition rather than after it. But it defeats the point of the
comparison warning, which is that you're potentially redefining
the sign bit.
I think the warning's just as valuable for may/must comparison of
non-literals as it is for normal comparison operators. It's just
unfortunate that we no longer get the special handling of literals.
Thanks,
Richard