On macOS, BOOL is a typedef for signed char, but it should never hold a value that isn't 1 or 0. Any code that expects a different value in their BOOL should be fixed.
rdar://problem/51954400 ObjC: Add diagnostics to catch incorrect usage of BOOL
Differential D63856
[ObjC] Add a -Wtautological-compare warning for BOOL erik.pilkington on Jun 26 2019, 5:28 PM. Authored by
Details On macOS, BOOL is a typedef for signed char, but it should never hold a value that isn't 1 or 0. Any code that expects a different value in their BOOL should be fixed. rdar://problem/51954400 ObjC: Add diagnostics to catch incorrect usage of BOOL
Diff Detail
Event TimelineComment Actions This only applies to relational operators, right? I'm a little uncomfortable with calling this "tautological" since it's not like it's *undefined behavior* to have (BOOL) 2, it's just *unwise*. But as long as we aren't warning about reasonable idioms that are intended to handle unfortunate situations — like other code that might have left a non-{0,1} value in the BOOL — I think this is fine. Comment Actions I think the party line is that it is undefined behaviour (in some sense), since UBSan will happily crash if you try to load a non-boolean value from a BOOL. It is a bit unfortunate that "defensive" code will start warning here though :/. Maybe we can try to detect and permit something like B < NO || B > YES, or emit a note with some canonical way of checking for non-boolean BOOLs. Even if we end up having to disable it default, I think its still a good diagnostic to have. A warning on stores to BOOL would probably be a lot higher value, though. Comment Actions What? Since when?
I'm not sure this is a problem because I'm not sure there's any reason to write defensive code besides B != NO or B == NO. It's potentially problematic if someone writes B == YES, though. Comment Actions https://reviews.llvm.org/D27607
I was thinking about something like the following, which probably isn't worth warning on. Another way of handling it would be only emitting the diagnostic if !InRange. Not exactly sure how common that pattern actually is though. void myAPI(BOOL DoAThing) { if (DoAThing > YES || DoAThing < NO) DoAThing = YES; // ... } Comment Actions Interesting; I'm not sure I find that convincing. Probably the least convincing part is where it links to its own behavioral documentation as justification for doing what it does. But okay, I guess we do this.
I don't think it's a problem to warn about this; this is just a silly way of writing if (DoAThing != NO) { DoAThing = YES; }. |