[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 #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-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 #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 #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-13 Thread schwab at suse dot de


--- Comment #1 from schwab at suse dot de  2007-03-13 20:22 ---
0x8000 is of type unsigned int, negating it gives an unsigned int of the
same value, converted to long long still gives the same positive value.  On the
other hand 2147483648 is of type long long (in C99) because it does not fit in
long, and gives -2147483648 as long long when negated.  C90 does not have long
long, so 2147483648 is undefined behaviour, and GCC chooses unsigned long since
it fits there.


-- 

schwab at suse dot de 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-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] Integer hex constant does not follow promoting rules

2007-03-13 Thread schwab at suse dot de


--- Comment #3 from schwab at suse dot de  2007-03-13 22:35 ---
(In reply to comment #2)
 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

You print it as a signed integer.

 It works because the expression should not be unsigned.

The value is converted to signed int by printf.

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

Integer promotion is only performed on types smaller than int.

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

The operand is unsigned int, so there is no promotion.


-- 

schwab at suse dot de 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-13 Thread pinskia at gcc dot gnu dot org


--- Comment #4 from pinskia at gcc dot gnu dot org  2007-03-13 22:35 ---
unsigned is never promoted, it always stays unsigned.
So -0x8000 == 0x8000 :).

Try adding ULL (or UL) if you want an unsigned long long (unsigned long)
constant.


-- 


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