We are reaching the end of the process to implement the BYOR (Bring Your Own Runtime) support and we are working on some of the more obscure things inside the compiler: implicit and explicit conversions and the related compiler options, such as /vo4 and /vo7.
If you would ask any normal person which number is bigger: -1 or any arbitrary positive number, then most people will say that -1 is smaller. Now ask the same thing to a computer and you may receive diferent and unexpected answers. Consider the following example program:
FUNCTION Start AS VOID
LOCAL dwValue AS DWORD
LOCAL liValue AS LONG
liValue := -1
dwValue := 1
? liValue < dwValue
Compile this code in Vulcan and it will compile without warnings, but the result will be that liValue (-1) is NOT smaller than dwValue (1).
Compile the same code in X# and you will get a compiler warning that you are comparing signed and unsigned integers. But the result is correct liValue is < dwValue.
Compile the same code (you wil have to remove the AS VOID from the start function) in VO and you will get a compiler warning 51422 (overflow or loss of data), which many people have disabled.If you ignore the error then the result will be that liValue(1) is NOT smaller than dwValue(1).
If you enable overflow errors in Vulcan (/ovf+) you will see what happened: the comparison will throw an overflow exception. The LONG Value gets converted from -1 to a DWORD with the value 0xFFFFFFFF and this produces an overflow. But without overflow checking this will then lead to a comparison where 0xFFFFFFFF is compared with 1. VO does the same.
After our implementation of the /vo4 compiler option in X# the compier warning will disappear, but the result of the comparison will be different from VO and Vulcan, because Roslyn will detect the possible overflow problem and will convert the comparison to a 64 bit comparison.
Now the 1 million dollar question of course is what we should do:
- create a compatible but incorrect result or
- create a correct but incompatible result.
Please let us know what you think of this...
A similar problem is
- Assigning a LONG to a PTR compiles in VO and Vulcan without an error
- Assigning a PTR to a LONG compiles in VO and Vulcan with an error
We would expect the complete opposite: assigning to an integer should be considered safe, but assigning a value to a PTR and thus potentially creating an invalid PTR seems pretty unsafe to us. So what do we do ?
- Compatible and unsafe?
- Incompatible and safe?
PS. For the next build we have already implemented:
- Vulcan compatible codeblocks
- Vulcan compatible string comparisons (/vo13)
- Vulcan compatible implicit casts and conversions (/vo7)
- Vulcan compatible signed/unsigned operations (/vo4)