Re: [PATCH 2/2] fix clang -Wtautological-compare with unsigned enum

2013-01-18 Thread Linus Torvalds
On Fri, Jan 18, 2013 at 9:15 AM, Phil Hord  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

2013-01-18 Thread Phil Hord
On Thu, Jan 17, 2013 at 11:44 AM, Linus Torvalds
 wrote:
> On Thu, Jan 17, 2013 at 3:00 AM, John Keeping  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

2013-01-17 Thread John Keeping
On Thu, Jan 17, 2013 at 08:44:20AM -0800, Linus Torvalds wrote:
> On Thu, Jan 17, 2013 at 3:00 AM, John Keeping  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


Re: [PATCH 2/2] fix clang -Wtautological-compare with unsigned enum

2013-01-17 Thread Antoine Pelisse
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
 wrote:
> On Thu, Jan 17, 2013 at 3:00 AM, John Keeping  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

2013-01-17 Thread Linus Torvalds
On Thu, Jan 17, 2013 at 3:00 AM, John Keeping  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

2013-01-17 Thread John Keeping
On Thu, Jan 17, 2013 at 11:32:39AM +0100, Antoine Pelisse wrote:
> John, could you confirm that you trigger the -Wtautological-compare
> warning with your version of clang ?

Yes, the warning is still there with both 3.2 and a recent trunk build
but this patch squelches it.

> And that this patch makes clang compilation warning-free (with the
> very latest clang) ?

There is one remaining warning on pu which hasn't been discussed in this
thread as far as I can see.  I'll send a patch shortly.

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)
 ^  ~


> On Wed, Jan 16, 2013 at 11:47 PM, Antoine Pelisse  wrote:
> > 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 
> > ---
> > 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

2013-01-17 Thread Antoine Pelisse
John, could you confirm that you trigger the -Wtautological-compare
warning with your version of clang ?
And that this patch makes clang compilation warning-free (with the
very latest clang) ?

Cheers,

On Wed, Jan 16, 2013 at 11:47 PM, Antoine Pelisse  wrote:
> 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 
> ---
> 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

2013-01-16 Thread Antoine Pelisse
> 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


[PATCH 2/2] fix clang -Wtautological-compare with unsigned enum

2013-01-16 Thread Antoine Pelisse
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 
---
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