+ std-proposals because it got dropped.

On Tue, Jan 7, 2020 at 5:57 PM Владимир Прокофьев <vov-crao@mail.ru> wrote:
and then converted back to unsigned long to write the result.
No. Signed type, involved into multiplication and division operations wins and result will be always signed. It is a common algebra operations. The result for the your example above will be signed (long long). If the lvalue has long type then the result will be converted to long.

OK, just as long as we're clear we're actually changing the type of the multiplication and division expressions. In a way that's incompatible with C.

Effectively, for T and U, and an expression

auto x = (T)-1 / (U)1;

what is decltype(x)?

The rules say that for T=long and U = unsigned long, decltype(x) is unsigned long.
Rule says wrong. Even common sense tells that decltype(x) have to be long.

Well, but that's not what the rule says now. I agree the rule might be misguided, but it is the current rule. Changing it is a breaking change. In an epochs-world I could see this happening. Perhaps. With the current focus of the committee not to break code unless the evidence is overwhelmingly in favor of it and the amount of code broken is miniscule, this is a tall order.

Standard doesn't tell about different behavior for 8, 16, 32 and 64 bits types. The 8 and 16 bits types shows correct behavior, just as I have described. But 32 and 64 bits shows trash. Here you can see different behavior https://rextester.com/CKKDX46498
Please tell me where this behavior is explained in the Standard?

[conv.prom] paragraph 1: www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4842.pdf#subsection.7.3.6

This basically says that char and short are converted to int (unsigned versions -> unsigned int) before doing arithmetic, and the result is an int, not a signed short or whatever. They don't work by the same rules.

Standard doesn't tell about different behavior for multiplication and division operations. But multiplication operation works correct for any type (https://rextester.com/UAH19753), whereas division operation works incorrect for 32 and 64 bits (https://rextester.com/CKKDX46498). See here for proof: http://coliru.stacked-crooked.com/a/092080eabcc16667
Please tell me where this behavior is explained in the Standard?

It isn't. It's a result of your assignment back to a signed type, and the inherent meanings of multiplication and division. Observe: https://godbolt.org/z/EoT4d6

Also I have modified https://rextester.com/CKKDX46498 to show division table of unsigned/signed : https://rextester.com/CLJNO52206 
As you can see the result is pretty strange.

The result is stupid but correct by the current rules. As stated above, I don't think the committee will be amenable to changing that, but feel free to bring a paper.

Note: The correct behavior is implemented in the Assembler language, because different instruction is used if signed is involved (idiv).

We can't just change that. We can't.
Please explain the difference for 16 and 32 bits division and between multiplication and division operations for 32 and 64 bits?
Integer promotion. See above.
That ship has sailed in 1987.
Wow! Long story. I cannot believe that I meet it only now! For 30 years of C/C++ coding! Debugging and testing!!
If we change that, it will break code.
Why not to add an option to fix it?
The standard does not define options.


On Tue, Jan 7, 2020 at 12:09 PM Владимир Прокофьев <vov-crao@mail.ru> wrote:

Вторник, 7 января 2020, 17:39 +07:00 от Gašper Ažman <gasper.azman@gmail.com>:

Then the committee is most likely going to add this to the steaming pile of "things we wish we could fix but can't because it would break code",

Do you really think that this fix will break the existing code? I don't think so, because this bug produces a mess result and nobody will write the code wich produces such mess.

But fixing it will make code reliable and stable.

If it is a policy to avoid any fix which can potentiality affect the existing code, then it will be much reasonable to provide a compiler option (say --fix-int-div) and then this option is ON, the fix is applied.
At least I will use this option everywhere.

Do you remember a bug in Intel Pentium processor in fdiv instruction? It produces a slightly different result comparing to expected, but this bug was fixed both in CPU and in many compilers with an extra flag. Why not to do the same for this bug??

like most of the implicit int conversions.

If you don't believe me, feel free to write a paper.
I am really cannot believe.
It is first serious bug in the C++ I have found and it will not be fixed.

On Tue, Jan 7, 2020, 10:36 Владимир Прокофьев <vov-crao@mail.ru> wrote:

See below.

Вторник, 7 января 2020, 17:06 +07:00 от Gašper Ažman <gasper.azman@gmail.com>:

Did we inherit this from C?

I am not sure. I see no history of modification of this rule.

I tested it in gcc with -std=c99 option and the result is confirmed. See http://coliru.stacked-crooked.com/a/3f3ed6126e361678

On Tue, Jan 7, 2020 at 6:46 AM Владимир Прокофьев via Std-Proposals <std-proposals@lists.isocpp.org> wrote:

I have found a mistake in the C++ Standard, https://en.cppreference.com/w/cpp/language/operator_arithmetic#Conversion : in the rule:

Otherwise, if the unsigned operand's conversion rank is greater or equal to the conversion rank of the signed operand, the signed operand is converted to the unsigned operand's type.

The NEGATIVE signed value CANNOT be converted to unsigned for any types. But opposite conversion from unsigned to signed is valid with appropriate rank.

To prove, please see wrong results here https://rextester.com/CKKDX46498

Note, that the error is observed for VS, CLang and GCC C++ compilers.

As you can see the error is observer in division operation to unsigned32 and 64 bits.
The division operation to SIGNED types is VALID (see first table in the example).
Also multiplication of signed and unsigned values is VALID.

The example above shows that the C++ compiler shows unreliable behavior which leads to produce wrong values as a result of division.

The correct rule shall be:

Otherwise, unsigned operand is converted to signed type of same or higher conversion rank of unsigned operand's type and then the operand with lesser conversion rank is converted to the operand with the greater conversion rank

С уважением.


Std-Proposals mailing list

С уважением.

С уважением.

С уважением.