From: Bernhard H. <ber...@be...> - 2004-07-20 11:36:25
|
> >> 3) Read section "6.3.1.8 Usual arithmetic conversions": chars > >> should be promoted to signed int. It's not optimal to cast to > >> the type of the result, if e.g. the result is of type float or > >> long. But: SDCC tries to avoid the promotion, if the result is a > >> char (or smaller). > So the only conclusion can be that in "~1" the 1 must be promoted to signed int? And > the result is a signed int as well. The standard leaves us little room for optimization. It's easy to promote everything to int, but SDCC would generate horrible large code and the mailing lists would be full of complaints. I know what I'm talking about ;-) But there's room in the standard, Eric explained it better than I can in bug #860006: "It is acceptable to skip integer promotion as long as the same result is obtained as if the promotion occurred (often referred to as the "as-if semantics"). A quote from ISO/IEC 9899-1999 (the C-99 standard), section 5.1.2.3 Example 2:" > This contradicts your other answer, allthough I must admit my errors in typing up the > example did make things complicated. I don't see any inconsistency between my answers. Could you please repeat the two relevant statements? > >> unsigned long int d; > >> d &= ~1; > >> > >> anl _d,#0xFE > >> mov (_d + 2),#0x00 > >> mov (_d + 3),#0x00 > >> So the next question is if this is according to the C-standard > > Yes. > I guess this should be NO then. Why? What do you expect? d &= ~1; is optimized to d = d & 0x0000fffeL; and results in the optimal code anl _d,#0xFE mov (_d + 2),#0x00 mov (_d + 3),#0x00 > In my earlier post result means the result of the ~ operation not of the & operation. I'm afraid this is the reason of some misunderstandings ... > > > "i = c & 0x80": I don't think I've changed this. The result > > > should be 128 or 0 according to the standard. I have not > > > checked yet, but I guess SDCC already performed the > > > promotion to int or that's another bug. > > This bug has definitely been introduced by your fix. Without your fix > > the result of the AND operation is zero-extended to int. With your fix > > it's sign-extended. > I agree the result should not be -128. Apparently SDCC did not promote either operand > to signed int. This is not the point. Again the source: char c; int i; i = c & 0x80; Without your fix the operation looks like this: i = (int) (unsigned char) ((char) c & (unsigned char) 0x80); Your fix changes it to: i = (int) (char) ((char) c & (char) 0x80); The problem is the type of the result of the AND operation. Without your fix it's (unsigned char), with your fix it's (char). The AND operation itself is correctly calculated. The bug exhibits in the cast from (char) to (int). This cast is performed with sign-extension, which is wrong. It must be a cast from (unsigned char) to (int) with zero-extension. It's not a bug, that there's no promotion to 'int' for the AND operation. The result is correct, therefore it's also conforming with the standard. > But to blame this on me/my fix is a bit rude in my opinion ??? Maarten, I've checked the resulting code with and without your fix. The emitted code is buggy with your fix. It's a fact, which everybody can reproduce. You can test it too, then you should accept it, but please don't complain if I find a bug in your code. Bernhard P.S.: what edition do you use? I've got ISO/IEC 9899 2nd edition. I can't verfy your reference: > this is promoted to unsigned long (0xFFFFFFFE) (acc. to 6.3.1.3 2) |