Bugs

General discussion for topics related to the FreeBASIC project or its community.
Post Reply
erik
Posts: 39
Joined: Dec 28, 2020 17:27
Location: Krasnoyarsk
Contact:

Re: Bugs

Post by erik »

Very large numbers in the compiler source code produce strange intermediate code.

In the file "symb.bi" on line 333 we have the constant FB_ARRAYDIM_UNKNOWN:

Code: Select all

'' Special value to represent the case where '...' ellipsis was given as ubound
const FB_ARRAYDIM_UNKNOWN = &h8000000000000000ll
In the file "ast-helper.bas" a constant is used on line 1019:

Code: Select all

'' Ellipsis ubound? can happen if ubound() is used in
'' an array initializer, when the ubound isn't fully
'' known yet, e.g. in this case:
''    dim array(0 to ...) as integer = { 1, ubound( array ), 3 }
if( bound = FB_ARRAYDIM_UNKNOWN ) then
	exit function
end if
At the output we have an intermediate C-code:

Code: Select all

if( (bound != -9223372036854775808ull) ) goto label$270;
{
	goto label$250;
}
The constant -9223372036854775808ull is unsigned, to which the negation operation is applied. This is strange. GCC produces a warning:

Code: Select all

SRC\COMPILER\AST-HELPER.BAS: In function 'hConstBound':
SRC\COMPILER\AST-HELPER.BAS:1019:36: error: comparison of integer expressions of different signedness: 'int64' {aka 'long long 
int'} and 'long long unsigned int' [-Werror=sign-compare]
Temporary solution:

Code: Select all

const FB_ARRAYDIM_UNKNOWN = &h8000000000000000ll - 1ll
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: Bugs

Post by marcov »

Maybe define the loopvar as unsigned ?
SARG
Posts: 1768
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Bugs

Post by SARG »

I don't get the error on Windows with GNU C17 (MinGW-W64 x86_64-posix-sjlj, built by Brecht Sanders) version 9.3.0 (x86_64-w64-mingw32)

What OS ? (Win or Linux)
What version of Gcc ?
erik
Posts: 39
Joined: Dec 28, 2020 17:27
Location: Krasnoyarsk
Contact:

Re: Bugs

Post by erik »

For GCC the "-Wall -Wextra" or "-Wsign-compare" options must be enabled.

However, even without these options, the number &h8000000000000000ll turns into -9223372036854775808ull. Comparing signed and unsigned numbers can be undefined behavior or turn into a potential problem in the future.
TeeEmCee
Posts: 375
Joined: Jul 22, 2006 0:54
Location: Auckland

Re: Bugs

Post by TeeEmCee »

It turns out that emitting -9223372036854775808ull is intentional. From hEmitInt in the C emitter:

Code: Select all

	if( typeIsSigned( dtype ) ) then
		s = str( value )

		'' Prevent GCC warnings for INT_MIN/LLONG_MIN:
		'' The '-' minus sign doesn't count as part of the number
		'' literal, and 2147483648 is too big for a 32bit integer,
		'' so it must be marked as unsigned.
		if( typeGetSize( dtype ) = 8 ) then
			if( value = -9223372036854775808ull ) then
				s += "u"
			end if
			s += "ll"
		else
			if( value = -2147483648u ) then
				s += "u"
			end if
		end if
(Regarding the warning in the comment: interestingly, the literal 9223372036854775808ll is an unsigned value in C and GCC prints "warning: integer constant is so large that it is unsigned", and while 0x8000000000000000ll is exactly the same value GCC prints no warning for it, hex constants are treated differently (which would be an alternative to adding "u").)

Anyway, the fix for this warning is https://github.com/rversteegen/fbc/comm ... 7ff1c8e366

But when I compile fbc with -gen gcc -Wc -Wall,-Wextra with GCC 12.2.0 I get an enormous amount of other spammed warnings (mostly -Wmissing-field-initializers), so I'm taking a look at those too.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Bugs

Post by dodicat »

Can somebody explain this in fb 1.10

Code: Select all


sub test(byref s as integer ptr) 
    print __function__,s
    dim as integer k
    s=@k
end sub

dim as integer g=2024
dim as integer ptr p=@g
print " Original pointer value "; p
test(p)
print "Pointer value after sub "; p
p=@g
print "________________________"
print
print " Original pointer value "; p
test(byval p)
print "Pointer value after sub "; p
sleep 
SARG
Posts: 1768
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Bugs

Post by SARG »

First call address of P
Second call address of g

Code: Select all

sub test(byref s as integer ptr) 
    print __function__,s
    dim as integer k
    s=@k
end sub

dim as integer g=2024
dim as integer ptr p=@g
print " Original pointer value "; p,g
test(p)
print "Pointer value after sub "; p,g
p=@g
print "________________________"
print
print " Original pointer value "; p,g
test(byval p)
print "Pointer value after sub "; p,g
srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: Bugs

Post by srvaldez »

dodicat, the reason for your test puzzles me, surely you know that the variable k will be out of scope after calling test, but FB doesn't warn or complain however gcc-13.2 and up give this warning warning: storing the address of local variable 'K$1' in '*S$1' [-Wdangling-pointer=]
fxm
Moderator
Posts: 12133
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Bugs

Post by fxm »

By specifying the 'Byval' keyword in front of an argument to a 'ByRef' parameter (or in front of a function result returned 'Byref'), a value usually stored in a pointer, can be passed directly as-is as an address, forcing the 'Byref' parameter (or 'Byref' function result) to reference the memory location that this address points to.

One interest of this is when a variable is only declared/defined through a pointer (as for example for a dynamic memory allocation), this avoid an explicit dereferencing, with the right type, of this pointer to pass by reference the pointed variable:
'Byval p' equivalent to '*p' at best, or to '*Cptr(type Ptr, p)'.

But in that case, as the value passed as-is directly forces the expected address, there is not exhaustive compatibility check of the provided 'Byval' variable type with respect to the expected parameter type (or result type).
=> danger, or only for hacking !

Working but purely academic example:

Code: Select all

Function upperCaseZstringCopy(Byref passedZstring As Zstring, Byref toCopyString As String) Byref As Zstring
    passedZstring = Ucase(toCopyString)
    Return passedZstring
End Function

Function getNewZstring (Byval size As Integer) Byref As Zstring
    ' instead of:
        ' Return *Cptr(Zstring Ptr, Callocate(size + 1))
    ' one can do:
        Return Byval Callocate(size + 1)
End Function

Dim As String s


s = "FreeBASIC"
' instead of:
    ' Dim Byref As Zstring rz1 = upperCaseZstringCopy(*Cast(Zstring Ptr, Callocate(Len(s) + 1)), s)
' one can do:
    Dim Byref As Zstring rz1 = upperCaseZstringCopy(Byval Callocate(Len(s) + 1), s)
Print "'" & s & "'", "'" & rz1 & "'"
Deallocate(@rz1)


s = "Version"
Dim Byref As Zstring rz2 = getNewZstring(Len(s))
rz2 = Ucase(s)
Print "'" & s & "'", "'" & rz2 & "'"
Deallocate(@rz2)

Sleep
fxm
Moderator
Posts: 12133
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Bugs

Post by fxm »

I updated the bug report dedicated of that 'Byval' use, but for a 'Byval' parameter:
#830 Byval placed before a passed variable for a Byval parameter induces an incomplete copy construction
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Bugs

Post by dodicat »

Thank you all for looking into this byval.
Yes srvaldez, static in the sub would have been the proper way.
The last thing I would have thought of was passing a value byval to a procedure, I came across it by accident.
Post Reply