Christian Böhme wrote: > Andrew Haley wrote: > >> ISO/IEC 14882:1998(E) >> 5 Expressions >> >> 9 > > That's _chapter_ 5 [expr], para 9 over here. > >>> vs. 4.7 "Integral conversions" as in the subject of the OP. >> >> Right, and you have now had the exact language quoted to you. > > Which, surprise, makes no mention of integral conversions nor > references to section 4.7 [conv.integral]. There, para 7 deserves > special attention: > > "The conversions allowed as integral promotions are excluded from > the set of integral conversions." > > That was the whole point of the OP (Did you read the subject ?). Unfortunately I did. yes. > But back to the original example: > >> Your first example was >> >> int64_t a; >> uint32_t b = 8; >> >> a = -(b * 2u); >> >> So, the last section of Para 9 applies: b is promoted to unsigned >> int, > > According to the OP b is of type uint32_t which coincidentally in > this particular example on a 32 bit machine, is a typedef from > unsigned int. OK. > Contrary to what the specifier may suggest, we all > know that ``typedef'' actually only introduces another name or > _alias_ for the name of the type that is given in a typedef > declaration. The literal constant 2u is, again, of type unsigned > int. According to 5.6 [expr.mul], (b * 2u) then yields a result > that is of type unsigned int. Where was there integral promotion > applied again ? The operands, and the result, are all of type unsigned int, which presumably is 32 bits in this case. >> int64_t a; >> uint32_t b = 8; >> >> a = -((int64_t )(b * 2u)); >> >> the unsigned int result of (b * 2u) is converted to int64_t and >> that is negated. > > As already stated elsewhere, this only _happens_ to be the correct > result. If b = 0xffffffff, then the above version yields the > negated value of (b * 2u), the latter being not closed over > the set that uint32_t represents producing a modulo 2^32 result. So what? The compiler does what the standard says it must. > If, as already assumed elsewhere, the 32 bit machine in question > provided a 32 unsigned integer multiplication that produces a 64 > bit unsigned integer result, the compiler will _never_ emit code > using this instruction based on information withheld by a standard > conforming frontend that the type of the result _must_ be that > of the operands and precluding the conversion to a type large > enough such that the multiplication is closed. Right: the compiler can use such an instruction, but it must discard the upper part of the result. > A 64 bit unsigned > int can then be negated yielding a _negative_ number as the correct > result. "The correct result"? The correct result is whatever the standard says it is. > The latter can be enforced by a statement like > > a = -(((uint64_t )b) * 2u); > > which, however, requests a 64 bit unsigned integer multiplication > which may be non existent or abysmally slow on the target. This > is the problem that _can_ precisely be avoided by integral conversion > applied during the multiplication operation. Right, so it sounds as though you do understand the standard. What, then, is your point? Andrew.