Menu

#992 False result of comparison

open
nobody
None
compiler
2023-11-19
2023-11-04
Sarg
No

Due to INTEGER datatype of the constant and the variable changed to UINTEGER the conditionnal jump (asm instruction) after the comparison is using the unsigned one instead the signed one.

Problem with gcc64 and also gas64.

dim as longint v1=-2147483649

if v1<=4294967295 then 
    print "v1<="
End If

if v1<4294967296 then 
    print "v1<"
End If
V1$0 = -2147483649ll;
    // if v1<=4294967295 then
    if( (uint64)V1$0 > 4294967295ull) goto label$3;
// if v12<4294967296 then
if( V12$0 >= 4294967296ll) goto label$5;

Discussion

  • Sarg

    Sarg - 2023-11-04

    In the third part of code the variable name is well V1 not V12.

     
  • Jeff Marshall

    Jeff Marshall - 2023-11-19

    Some additional information and notes:

    • Compiling with command line option-w signedness will warn of this situation.
    • explicitly using the longint suffix ll should ensure the constant is seen as signed
    • differences between 32-bit and 64-bit handling of constant literals

    For comparison:

    #macro show( compare )
        print "is " & #compare & " ?: ";
        if compare then
            print "yes"
        else
            print "no"
        end if 
    #endmacro
    
    scope
        dim as longint v1=-2147483649
        print "v1 = " & v1
        show( v1 <= 4294967295 ) '' this  
        show( v1 < 4294967296 ) 
        print
    end scope
    
    scope
        dim as longint v1=-2147483649ll
        print "v1 = " & v1
        show( v1 <= 4294967295ll ) 
        show( v1 < 4294967296ll )
        print
    end scope
    
    scope
        dim as longint v1=-2147483649
        dim as longint v2=4294967295
        dim as longint v3=4294967296
        print "v1 = " & v1
        print "v2 = " & v2
        print "v3 = " & v3
        show( v1 <= v2 ) 
        show( v1 < v3 ) 
        print
    end scope
    
    scope
        dim as longint v1=-2147483649ll
        dim as longint v2=4294967295ll
        dim as longint v3=4294967296ll
        print "v1 = " & v1
        print "v2 = " & v2
        print "v3 = " & v3
        show( v1 <= v2 ) 
        show( v1 < v3 ) 
        print
    end scope
    

    On 32-bit we get other warnings because constant is seen as unsigned 32-bit and the negative is not parsed as part of the constant - so is negating an unsigned literal

    v1 = 2147483647
    is v1 <= 4294967295 ?: yes
    is v1 < 4294967296 ?: yes
    
    v1 = -2147483649
    is v1 <= 4294967295ll ?: yes
    is v1 < 4294967296ll ?: yes
    
    v1 = 2147483647
    v2 = 4294967295
    v3 = 4294967296
    is v1 <= v2 ?: yes
    is v1 < v3 ?: yes
    
    v1 = -2147483649
    v2 = 4294967295
    v3 = 4294967296
    is v1 <= v2 ?: yes
    is v1 < v3 ?: yes
    

    On 64-bit we get the bad comparison due to mixing signed and unsigned operands:

    v1 = -2147483649
    is v1 <= 4294967295 ?: no
    is v1 < 4294967296 ?: yes
    
    v1 = -2147483649
    is v1 <= 4294967295ll ?: yes
    is v1 < 4294967296ll ?: yes
    
    v1 = -2147483649
    v2 = 4294967295
    v3 = 4294967296
    is v1 <= v2 ?: yes
    is v1 < v3 ?: yes
    
    v1 = -2147483649
    v2 = 4294967295
    v3 = 4294967296
    is v1 <= v2 ?: yes
    is v1 < v3 ?: yes
    
     

Log in to post a comment.