[Info-vax] VMS Cobol - GnuCOBOL

Johnny Billquist bqt at softjar.se
Mon Mar 6 08:24:19 EST 2023


On 2023-03-03 13:42, bill wrote:
> On 3/3/2023 6:59 AM, Johnny Billquist wrote:
>> Damn! I learned something new today...
>>
>> On 2023-03-01 15:54, Dan Cross wrote:
>>> In article <ttnk0m$lg5$2 at news.misty.com>,
>>> Johnny Billquist  <bqt at softjar.se> wrote:
>>>> On 2023-02-28 20:11, Dan Cross wrote:
>>
>> [...]
>>
>>>> You overcomplicated the whole explanation.
>>>
>>> Hmm.
>>
>> I was wrong. :-)
>>
>>>> Basically, if you multiply two numbers, and the result would be bigger
>>>> than the types involved, the result is undefined.
>>>
>>> Well...no.  _unsigned_ integer overflow in C is well-defined (it
>>> has modular wrapping semantics; C11 sec 6.2.5 para 9).
>>> Similarly, overflow of signed atomics is well-defined (C11 sec
>>> 7.17.7.5 para 3), so this is not always true.
>>
>> I had actually missed that unsigned integers do have a defined 
>> overflow behavior. Thanks.
>>
>>>> In this case, the type
>>>> is unsigned short. If the multiplication cause anything that don't fit
>>>> into an unsigned short, then the result is undefined.
>>>>
>>>> And it's fairly easy to find two unsigned short numbers that when
>>>> multiplied will give a result that don't fit into an unsigned short.
>>>
>>> The range of unsigned short has little to do with it, and
>>> truncation of the result is fine too (again, defined to use
>>> modular wrapping for unsigned types; C11 sec 6.3.1.3).  The
>>> problem is entirely due to the promotion to _signed_ int prior
>>> to the multiplication.  The fix, incidentally, is easy:
>>>
>>> unsigned short
>>> mul(unsigned short a, unsigned short b)
>>> {
>>>     unsigned int aa = a, bb = b;
>>>     return aa * bb;
>>> }
>>>
>>> This is well-defined, even if the range of `unsigned short` is
>>> the same as `unsigned int`, which is permitted by the standard.
>>
>> Right. My second error. It is allowed to promote a unsigned short to a 
>> signed int.
>> I do feel that I don't entirely agree with that rule, but it's 
>> definitely written as such.
>>
>> Changing from unsigned to signed feels just as a freedom too much.
>>
>>>> It's really not that different from any other language. Some languages
>>>> will throw an exception, others will just give some result that 
>>>> might or
>>>> might not be meaningful. But there is no guarantee in almost any
>>>> language of some kind of specific meaningful result. Try it in FORTRAN
>>>> and see what you get there, or Cobol (or BASIC). :-)
>>>
>>> The issue, and the reason for the complex initial explanation,
>>> is the subtle interaction between the implicit type promotion
>>> rules, arithmetic, undefined behavior, and the freedom that UB
>>> gives to compiler writers, which is pretty unique to C.  Hence
>>> why optimizing compilers often _appear_ to introduce bugs when
>>> in fact they're performing perfectly legal transformations, and
>>> turning off the optimizer can appear to "fix" the problem.
>>
>> Yup. You were right. Sorry that I had to go and read the spec again. 
>> Trusting my brain was obviously the wrong thing to do.
>>
> 
> And it really doesn't matter whether the result is truncation,
> conversion to signed int, wrap around, throwing an exception or
> undefined.  The answer is still going to be wrong and the calculation
> worthless.  So, what's the point?  Fix the damn code.
> 
> Go ahead, blame the language again.

No. I don't fully agree. The fact that unsigned types are defined to 
have the wrapping behavior means that you could definitely do this 
intentionally and for rather good reasons.

But the type propagation rule here breaks that promise, which is what I 
find *very* broken. I do consider it a error in the language 
specification when this can happen.

   Johnny




More information about the Info-vax mailing list