[Bug c/31166] Integer hex constant does not follow promoting rules

2007-03-17 Thread roberto dot gordo at gmail dot com


--- Comment #9 from roberto dot gordo at gmail dot com  2007-03-17 17:58 
---
I would like to apologize for my faults in gcc bug report 31166, specially to
the people who responded, and fully acknowledge my error. I've misunderstood
your responses. Now, while reading them again, they appear completely logical
to me.

I was working during hours with a piece of code on which I've been bitten by
lots of c language weirdness. I've discovered and fixed most of them (except
the reported one), but after so many consecutive hours of debugging such ugly
code my mind was not in a very clear state... and my comments were fairly
stupid, I must admit. I'm sorry for that.

There is still something remaining that I don't fully understand (the
integer/unsigned promotion thing). I'm still wondering about that, but I accept
your responses, so I think I'm somewhat not giving the right interpretation at
the standard wordings. I will try to find the cause on mailing lists or other
places, since the gcc bugzilla may not be the correct place.

Thanks for your patience and please accept my apologies for wasting your time.
Sorry.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31166



[Bug c/31166] Integer hex constant does not follow promoting rules

2007-03-14 Thread roberto dot gordo at gmail dot com


--- Comment #8 from roberto dot gordo at gmail dot com  2007-03-14 12:29 
---
I'm still unable to match the behavior of gcc with the ISO C standard. I will
try to explain myself.

The reason for which gcc produces different results with hex constants is now
clear. Also, in the following quotation:

"The result of the unary - operator is the negative of its (promoted) operand.
The integer promotions are performed on the operand, and the result has the
promoted type."

I acknowledge that I've failed to note that given this code

  long long ll;
  ll = -0x8000;

the operand for the unary - operator is promoted first, and the operation is
done next. The result may fit on an int, but according to the standard, the
result has the promoted type (which has been already calculated as unsigned).

BUT.. you said

> Integer promotion is only performed on types smaller than int.

and I would want to comment on this. I do not claim to have good understanding
of English, so I may be interpreting the ISO C standard on a wrong way. Before
reopening the bug, I would appreciate comments on this. This are the relevant
parts:

Section: Conversions -> Arithmetic operands -> Boolean, characters, and
integers
"The following may be used in an expression wherever an int or unsigned int may
be used:
- An object or expression with an integer type whose integer conversion rank is
less than or equal to the rank of int and unsigned int."
[...]
If an int can represent all values of the original type, the value is converted
to an int; otherwise, it is converted to an unsigned int."

Please, note the wording: "less than *or equal*". As I read it, I understand
that promotion rules are applied to int, unsigned int, or other types with less
rank. And any unsigned int small enough to fit on a signed int is converted.
These rules appears to be valid also for the unary - , and even when operator
is unsigned. I would be happy to change my mind if you point to any section of
the standard stating that unsigned operands should never be touched, but
currently the text I see appears to say the opposite.

So, in the way I view it, the expression:

  -10U

should return an int instead of unsigned, and it should be safe to assign it to
a bigger integer.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31166



[Bug c/31166] Integer hex constant does not follow promoting rules

2007-03-14 Thread roberto dot gordo at gmail dot com


--- Comment #7 from roberto dot gordo at gmail dot com  2007-03-14 09:40 
---
That's OK, it is not a bug, sorry.


-- 

roberto dot gordo at gmail dot com changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution||INVALID


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31166



[Bug c/31166] Integer hex constant does not follow promoting rules

2007-03-14 Thread roberto dot gordo at gmail dot com


--- Comment #6 from roberto dot gordo at gmail dot com  2007-03-14 09:27 
---
I think I've found something. According to the ISO C standard, a decimal
constant without suffixes should ALWAYS be signed int (or signed long long if
it does not fit), but never be unsigned! An octal or hexadecimal constant
without suffixes may be unsigned when it does not fit on a signed. I was not
aware of this, sorry (and according to your comments, I think neither you were,
because the explanations that you gave to my bug report were not true).


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31166



[Bug c/31166] Integer hex constant does not follow promoting rules

2007-03-14 Thread roberto dot gordo at gmail dot com


--- Comment #5 from roberto dot gordo at gmail dot com  2007-03-14 08:52 
---
> unsigned is never promoted, it always stays unsigned.

Sorry to insist, but I'm still not convinced. Please, see these examples,
compiled with -std=c99.

{
  unsigned u;
  int i;
  u = 1; /* this is an unsigned */
  i = -u; /* this is an unsigned turned into a negative int */
  printf("%d\n", i); /* It will print -1 */
}

Another example.

{
  long long ll;
  ll = -2147483648;
  printf("%lld\n", ll); /* It will print -2147483648 */
}

2147483648 is the same constant as 0x8000. Acording to your comments, this
is an unsigned, because it does not fit on an int, and it should remain as
unsigned. But it is not. There is not overflow in printf, because I print as
long long.

This is just the same example, because 2147483648 == 0x8000

{
  long long ll;
  ll = -0x8000;
  printf("%lld\n", ll); /* It will print 2147483648 */
}

It is the same constant, represented on hex. Just the same number. I'm reading
the ISO C standard right now, and I can't find any explanation for an hex
constant to have such different semantics. If there it is and I've missed it, I
would appreciate to be pointed to the section of the standard which explains
this behavior, please.


-- 

roberto dot gordo at gmail dot com changed:

   What|Removed |Added

 Status|RESOLVED|UNCONFIRMED
 Resolution|INVALID |


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31166



[Bug c/31166] Integer hex constant does not follow promoting rules

2007-03-13 Thread roberto dot gordo at gmail dot com


--- Comment #2 from roberto dot gordo at gmail dot com  2007-03-13 22:27 
---
I do not agree at all. Please, read.

So 0x8000 is unsigned because does not fit on an int type. That's OK. If
negating it gives an unsigned int of the same value, then, how do you explain
that the following code prints "n1 = -2147483648"

int n1;
n1 = -0x8000;
printf("n1 = %d\n", n1);

It works because the expression should not be unsigned. This is a quotation
from ISO/IEC 9899:1999 standard:

"The result of the unary - operator is the negative of its (promoted) operand.
The integer promotions are performed on the operand, and the result has the
promoted type."

and...

"Several operators convert operand values from one type to another
automatically [...] If an int can represent all values of the original type,
the value is converted to an int; otherwise, it is converted to an unsigned
int. These are called the integer promotions."

The unary - operator can (and should) apply again the promotion rules, and
should choose int.

So the expression -0x8000 shall promote to a signed integer type in which
it fits, which happens to be an int (on c99 and c90). And as you can see, gcc
works correcly here, just as the standard says. But if fails when the lvalue is
long long instead of int, as here:

long long n1;
n1 = -0x8000;

In case we have an int expression at the right, it should be converted as long
long without problems. In case we have a long long at the right, it should also
work without problems (at least for c99). And if we have an unsigned int at the
right, as you said, it should have not worked with an int and it is a bug by
itself in the way I understand the standard.


-- 

roberto dot gordo at gmail dot com changed:

   What|Removed |Added

         CC|        |roberto dot gordo at gmail
       ||dot com
 Status|RESOLVED|UNCONFIRMED
 Resolution|INVALID |


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31166



[Bug c/31166] New: Integer hex constant does not follow promoting rules

2007-03-13 Thread roberto dot gordo at gmail dot com
Forgive me if this is reported/fixed already; after many consecutive hours of
debugging I currently do not have the courage to search through the list of
bugs.

Please, try this code (tested on 32bit GNU/Linux), compiled with:
gcc -std=c99 -Wall -Wextra -o wtf wtf.c

#include 

int main(void)
{
int n1, n2;
long long n3, n4;

n1 = -0x8000;
n2 = -2147483648;

n3 = -0x8000;
n4 = -2147483648;

printf("n1 = %d\n", n1);
printf("n2 = %d\n", n2);

printf("n3 = %lld\n", n3);
printf("n4 = %lld\n", n4);

return 0;
}

It consists of two int variables and two long long variables, all of them set
to the same value (-2147483648 == 0x8000). This is what I get:

n1 = -2147483648
n2 = -2147483648
n3 = 2147483648
n4 = -2147483648

What happened to n3? It appears that hex constants are not promoted to long
long the same way as decimal ones. AFAIK, this behavoir does not match C99
(neither C90).

When compiling without -std=c99, gcc gives this warning:
warning: this decimal constant is unsigned only in ISO C90

I think that gcc is trying to say that the constant does not fit on an int (nor
a long) and it is promoted to unsigned, as it is stated by ISO C90. But yes, it
should fit on an int, because -2147483648 >= INT_MIN in this architecture.
Anyway, it is even more funny, because the warning is only for n2 and n4
(decimal constants) but not for n1 nor n4 (hex constants). This is the output
without -std=c99:

n1 = -2147483648
n2 = -2147483648
n3 = 2147483648
n4 = 2147483648

Tested with these versions of gcc:

Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v
--enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr
--enable-shared --with-system-zlib --libexecdir=/usr/lib
--without-included-gettext --enable-threads=posix --enable-nls
--program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu
--enable-libstdcxx-debug --enable-mpfr --with-tune=i686
--enable-checking=release i486-linux-gnu
Thread model: posix
gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)

Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v
--enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr
--enable-shared --with-system-zlib --libexecdir=/usr/lib
--without-included-gettext --enable-threads=posix --enable-nls
--program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu
--enable-libstdcxx-debug --enable-mpfr --enable-checking=release i486-linux-gnu
Thread model: posix
gcc version 4.1.2 20060928 (prerelease) (Ubuntu 4.1.1-13ubuntu5)

Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v
--enable-languages=c,c++,java,f95,objc,ada,treelang --prefix=/usr
--enable-shared --with-system-zlib --libexecdir=/usr/lib
--without-included-gettext --enable-threads=posix --enable-nls
--program-suffix=-4.0 --enable-__cxa_atexit --enable-clocale=gnu
--enable-libstdcxx-debug --enable-java-awt=gtk-default --enable-gtk-cairo
--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-4.0-1.4.2.0/jre --enable-mpfr
--disable-werror --with-tune=pentium4 --enable-checking=release i486-linux-gnu
Thread model: posix
gcc version 4.0.3 (Ubuntu 4.0.3-1ubuntu5)


-- 
   Summary: Integer hex constant does not follow promoting rules
   Product: gcc
   Version: 4.1.2
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: roberto dot gordo at gmail dot com


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31166