Re: [PATCH 2/2] fix clang -Wtautological-compare with unsigned enum
On Thu, Jan 17, 2013 at 11:44 AM, Linus Torvalds torva...@linux-foundation.org wrote: On Thu, Jan 17, 2013 at 3:00 AM, John Keeping j...@keeping.me.uk wrote: There's also a warning that triggers with clang 3.2 but not clang trunk, which I think is a legitimate warning - perhaps someone who understands integer type promotion better than me can explain why the code is OK (patch-score is declared as 'int'): builtin/apply.c:1044:47: warning: comparison of constant 18446744073709551615 with expression of type 'int' is always false [-Wtautological-constant-out-of-range-compare] if ((patch-score = strtoul(line, NULL, 10)) == ULONG_MAX) ^ ~ The warning seems to be very very wrong, and implies that clang has some nasty bug in it. Since patch-score is 'int', and UNLONG_MAX is 'unsigned long', the conversion rules for the comparison is that the int result from the assignment is cast to unsigned long. And if you cast (int)-1 to unsigned long, you *do* get ULONG_MAX. That's true regardless of whether long has the same number of bits as int or is bigger. The implicit cast will be done as a sign-extension (unsigned long is not signed, but the source type of 'int' *is* signed, and that is what determines the sign extension on casting). So the is always false is pure and utter crap. clang is wrong, and it is wrong in a way that implies that it actually generates incorrect code. It may well be worth making a clang bug report about this. That said, clang is certainly understandably confused. The code depends on subtle conversion rules and bit patterns, and is clearly very confusingly written. So it would probably be good to rewrite it as unsigned long val = strtoul(line, NULL, 10); if (val == ULONG_MAX) .. patch-score = val; instead. At which point you might as well make the comparison be = INT_MAX instead, since anything bigger than that is going to be bogus. So the git code is probably worth cleaning up, but for git it would be a cleanup. For clang, this implies a major bug and bad code generation. Yes, I can tell by the wording of the error message that you are right and clang has a problem. But the git code it complained about does have a real problem, because the result of signed int a = ULONG_MAX is implementation-defined. It cannot be guaranteed or expected that patch-score will ever be assigned -1 there, and so the comparison may always be false. I guess the warning is correct, but only accidentally. :-) Your rewrite is more sane and corrects the problem, I think. Phil -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/2] fix clang -Wtautological-compare with unsigned enum
On Fri, Jan 18, 2013 at 9:15 AM, Phil Hord phil.h...@gmail.com wrote: Yes, I can tell by the wording of the error message that you are right and clang has a problem. But the git code it complained about does have a real problem, because the result of signed int a = ULONG_MAX is implementation-defined. Only theoretically. Git won't work on machines that don't have 8-bit bytes anyway, so worrying about the theoretical crazy architectures that aren't two's complement etc isn't something I'd care about. There's a whole class of technically implementation-defined issues in C that simply aren't worth caring for. Yes, the standard is written so that it works on machines that aren't byte-addressable, or EBCDIC or have things like 18-bit words and 36-bit longwords. Or 16-bit int for microcontrollers etc. That doesn't make those implementation-defined issues worth worrying about these days. A compiler writer could in theory make up some idiotic rules that are still valid by the C standard even on modern machines, but such a compiler should simply not be used, and the compiler writer in question should be called out for being an ass-hat. Paper standards are only worth so much. And that so much really isn't very much. Linus -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/2] fix clang -Wtautological-compare with unsigned enum
On Thu, Jan 17, 2013 at 3:00 AM, John Keeping j...@keeping.me.uk wrote: There's also a warning that triggers with clang 3.2 but not clang trunk, which I think is a legitimate warning - perhaps someone who understands integer type promotion better than me can explain why the code is OK (patch-score is declared as 'int'): builtin/apply.c:1044:47: warning: comparison of constant 18446744073709551615 with expression of type 'int' is always false [-Wtautological-constant-out-of-range-compare] if ((patch-score = strtoul(line, NULL, 10)) == ULONG_MAX) ^ ~ The warning seems to be very very wrong, and implies that clang has some nasty bug in it. Since patch-score is 'int', and UNLONG_MAX is 'unsigned long', the conversion rules for the comparison is that the int result from the assignment is cast to unsigned long. And if you cast (int)-1 to unsigned long, you *do* get ULONG_MAX. That's true regardless of whether long has the same number of bits as int or is bigger. The implicit cast will be done as a sign-extension (unsigned long is not signed, but the source type of 'int' *is* signed, and that is what determines the sign extension on casting). So the is always false is pure and utter crap. clang is wrong, and it is wrong in a way that implies that it actually generates incorrect code. It may well be worth making a clang bug report about this. That said, clang is certainly understandably confused. The code depends on subtle conversion rules and bit patterns, and is clearly very confusingly written. So it would probably be good to rewrite it as unsigned long val = strtoul(line, NULL, 10); if (val == ULONG_MAX) .. patch-score = val; instead. At which point you might as well make the comparison be = INT_MAX instead, since anything bigger than that is going to be bogus. So the git code is probably worth cleaning up, but for git it would be a cleanup. For clang, this implies a major bug and bad code generation. Linus Linus -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/2] fix clang -Wtautological-compare with unsigned enum
BTW, I think it has been addressed [1] by clang already and that would explain why you don't have the warning when using clang trunk version. [1]: http://llvm-reviews.chandlerc.com/D113 Antoine, On Thu, Jan 17, 2013 at 5:44 PM, Linus Torvalds torva...@linux-foundation.org wrote: On Thu, Jan 17, 2013 at 3:00 AM, John Keeping j...@keeping.me.uk wrote: There's also a warning that triggers with clang 3.2 but not clang trunk, which I think is a legitimate warning - perhaps someone who understands integer type promotion better than me can explain why the code is OK (patch-score is declared as 'int'): builtin/apply.c:1044:47: warning: comparison of constant 18446744073709551615 with expression of type 'int' is always false [-Wtautological-constant-out-of-range-compare] if ((patch-score = strtoul(line, NULL, 10)) == ULONG_MAX) ^ ~ The warning seems to be very very wrong, and implies that clang has some nasty bug in it. Since patch-score is 'int', and UNLONG_MAX is 'unsigned long', the conversion rules for the comparison is that the int result from the assignment is cast to unsigned long. And if you cast (int)-1 to unsigned long, you *do* get ULONG_MAX. That's true regardless of whether long has the same number of bits as int or is bigger. The implicit cast will be done as a sign-extension (unsigned long is not signed, but the source type of 'int' *is* signed, and that is what determines the sign extension on casting). So the is always false is pure and utter crap. clang is wrong, and it is wrong in a way that implies that it actually generates incorrect code. It may well be worth making a clang bug report about this. That said, clang is certainly understandably confused. The code depends on subtle conversion rules and bit patterns, and is clearly very confusingly written. So it would probably be good to rewrite it as unsigned long val = strtoul(line, NULL, 10); if (val == ULONG_MAX) .. patch-score = val; instead. At which point you might as well make the comparison be = INT_MAX instead, since anything bigger than that is going to be bogus. So the git code is probably worth cleaning up, but for git it would be a cleanup. For clang, this implies a major bug and bad code generation. Linus Linus -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/2] fix clang -Wtautological-compare with unsigned enum
On Thu, Jan 17, 2013 at 08:44:20AM -0800, Linus Torvalds wrote: On Thu, Jan 17, 2013 at 3:00 AM, John Keeping j...@keeping.me.uk wrote: There's also a warning that triggers with clang 3.2 but not clang trunk, which I think is a legitimate warning - perhaps someone who understands integer type promotion better than me can explain why the code is OK (patch-score is declared as 'int'): builtin/apply.c:1044:47: warning: comparison of constant 18446744073709551615 with expression of type 'int' is always false [-Wtautological-constant-out-of-range-compare] if ((patch-score = strtoul(line, NULL, 10)) == ULONG_MAX) ^ ~ The warning seems to be very very wrong, and implies that clang has some nasty bug in it. Since patch-score is 'int', and UNLONG_MAX is 'unsigned long', the conversion rules for the comparison is that the int result from the assignment is cast to unsigned long. And if you cast (int)-1 to unsigned long, you *do* get ULONG_MAX. That's true regardless of whether long has the same number of bits as int or is bigger. The implicit cast will be done as a sign-extension (unsigned long is not signed, but the source type of 'int' *is* signed, and that is what determines the sign extension on casting). So the is always false is pure and utter crap. clang is wrong, and it is wrong in a way that implies that it actually generates incorrect code. It may well be worth making a clang bug report about this. The warning doesn't occur with a build from their trunk so it looks like it's already fixed - it just won't make into into a release for about 5 months going by their timeline. Thanks for the clear explanation. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] fix clang -Wtautological-compare with unsigned enum
Create a GREP_HEADER_FIELD_MIN so we can check that the field value is sane and silent the clang warning. Clang warning happens because the enum is unsigned (this is implementation-defined, and there is no negative fields) and the check is then tautological. Signed-off-by: Antoine Pelisse apeli...@gmail.com --- I tried to consider discussion [1] and this [2] discussion on clang's list With these two patches and the patch from Max Horne, I'm finally able to compile with CC=clang CFLAGS=-Werror. [1]: http://thread.gmane.org/gmane.comp.version-control.git/184908 [2]: http://clang-developers.42468.n3.nabble.com/Possibly-invalid-enum-tautology-warning-td3233140.html grep.c | 3 ++- grep.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/grep.c b/grep.c index 4bd1b8b..bb548ca 100644 --- a/grep.c +++ b/grep.c @@ -625,7 +625,8 @@ static struct grep_expr *prep_header_patterns(struct grep_opt *opt) for (p = opt-header_list; p; p = p-next) { if (p-token != GREP_PATTERN_HEAD) die(bug: a non-header pattern in grep header list.); - if (p-field 0 || GREP_HEADER_FIELD_MAX = p-field) + if (p-field GREP_HEADER_FIELD_MIN || + GREP_HEADER_FIELD_MAX = p-field) die(bug: unknown header field %d, p-field); compile_regexp(p, opt); } diff --git a/grep.h b/grep.h index 8fc854f..e4a1df5 100644 --- a/grep.h +++ b/grep.h @@ -28,7 +28,8 @@ enum grep_context { }; enum grep_header_field { - GREP_HEADER_AUTHOR = 0, + GREP_HEADER_FIELD_MIN = 0, + GREP_HEADER_AUTHOR = GREP_HEADER_FIELD_MIN, GREP_HEADER_COMMITTER, GREP_HEADER_REFLOG, -- 1.8.1.1.435.g20d29be.dirty -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/2] fix clang -Wtautological-compare with unsigned enum
With these two patches and the patch from Max Horne, I'm deeply sorry for this typo Max -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html