Richard Biener <richard.guent...@gmail.com> writes: > On Tue, Oct 24, 2017 at 3:24 PM, Richard Sandiford > <richard.sandif...@linaro.org> wrote: >> Richard Biener <richard.guent...@gmail.com> writes: >>> On Tue, Oct 24, 2017 at 2:48 PM, Richard Sandiford >>> <richard.sandif...@linaro.org> wrote: >>>> Richard Biener <richard.guent...@gmail.com> writes: >>>>> On Tue, Oct 24, 2017 at 1:23 PM, Richard Sandiford >>>>> <richard.sandif...@linaro.org> wrote: >>>>>> Eric Botcazou <ebotca...@adacore.com> 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