FreeBASIC 1.10.1 Release Discussion

General discussion for topics related to the FreeBASIC project or its community.
Post Reply
coderJeff
Site Admin
Posts: 4326
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: FreeBASIC 1.10.0 Development

Post by coderJeff »

fxm wrote: Dec 21, 2022 20:29 Note: This variant of the above bug 'Dim As Parent p = Type<Child>(1)' should also compile.
Maybe we need some new rules, because this did not seem correct to me to allow:

Code: Select all

type parent
    dim as integer i
end type
type child extends parent
	dim as integer j
end type
dim as parent p = type<child>(1,2)
I guess a warning maybe?
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC 1.10.0 Development

Post by fxm »

If we consider 'type<child>(1,2)' to be a temporary child instance, can this be discussed ?
coderJeff
Site Admin
Posts: 4326
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: FreeBASIC 1.10.0 Development

Post by coderJeff »

fxm wrote: Dec 23, 2022 17:09 If we consider 'type<child>(1,2)' to be a temporary child instance, can this be discussed ?
For sure we can discuss.

How should parent be constructed from child? What should be the implicit construction for the trivial type?

Also, not changed from previous versions:

Code: Select all

type parent extends object
  dim as integer i
end type
type child extends parent
  dim as integer j
end type
dim as parent p = type<child>(1,2)
'' No matching overloaded function, CHILD.constructor() in 'dim as parent p = type<child>(1,2)'
My opinion is that there are other issues, and this is only the start of the problems.

Like this doesn't really make much sense either:

Code: Select all

type parent extends object
    dim as integer i
end type
type child extends parent
	dim as integer j
	declare constructor()	
	declare constructor( arg1 as integer, arg2 as integer )
end type
dim as parent p = type<child>(1,2)
The extra field in CHILD is discarded and 'p' is only exactly the size of 'parent' so there is no polymorphism or casting that works here.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC 1.10.0 Development

Post by fxm »

1)
But you have added 'extends object' to my previous example, so implicit constructors (default constructor + copy constructor) exist.
Therefore, a matching conversion-constructor must be defined.

2)
My initial example (without an implicit constructor) worked before the change:

Code: Select all

type parent
  dim as integer i
end type
type child extends parent
  dim as integer j
end type
dim as parent p = type<child>(1,2)

3)
Otherwise I agree with you that using such a literal initializer:
dim as parent p = type<child>(1,2)
does not make much sense, but should it be banned ?

4)
So, at first, I am OK with correcting only this:

Code: Select all

Type Parent
    Dim As Integer I
End Type
Type Child Extends Parent
    Dim As Integer J
End Type

Dim As Child c
Dim As Parent p = c             '' error 24: Invalid data types in 'Dim As Parent p = c'
coderJeff
Site Admin
Posts: 4326
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: FreeBASIC 1.10.0 Development

Post by coderJeff »

3)
fxm wrote: Dec 23, 2022 18:49 Otherwise I agree with you that using such a literal initializer:
dim as parent p = type<child>(1,2)
does not make much sense, but should it be banned ?
Where this comes from is the recursive nature of initializer lists. I disallowed derived types to initialize base types, because we get really confusing results when initializing fields if it is allowed:

Code: Select all

type udt1
	dim as integer i1, i2
end type

type udt2 extends udt1
	dim as integer i3, i4, i5, i6
end type

type udt3 extends udt2
	dim as integer i7, i8, i9
end type

dim as udt2 u2 = (1,2,3,4,5,6)

dim as udt3 u3 = type<udt3>(u2, 7, 8, 9)

'' (1) allow derived types to initialize base types
'' (2) disallow derived types to initialize base types
''
''             '' allow(1)  disallow(2)
print u3.i1    ''   1           1
print u3.i2    ''   2           2
print u3.i3    ''   7           3
print u3.i4    ''   8           4
print u3.i5    ''   9           5
print u3.i6    ''   0           6
print u3.i7    ''   0           7
print u3.i8    ''   0           8
print u3.i9    ''   0           9
4)
fxm wrote: Dec 23, 2022 18:49 So, at first, I am OK with correcting only this:
I will try to correct for top-level variable assignment.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC 1.10.0 Development

Post by fxm »

Thank you to try to allow the implicit up-casting of a derived variable (not 'Type(...)') used as initializer for construction of a base-type of any sub-level.

UDTn being the derived type of UDT0 at the nth level, and for all j >= i :
  • Dim As UDTj uj0
    Dim As UDTi ui = uj0 '' should work like: Dim As UDTi ui = Cast(UDTi, uj0)
Example :

Code: Select all

type udt1
    dim as integer i1, i2
end type

type udt2 extends udt1
    dim as integer i3, i4, i5, i6
end type

type udt3 extends udt2
    dim as integer i7, i8, i9
end type

dim as udt2 u20 = (1, 2, 3, 4, 5, 6)
dim as udt3 u30 = (1, 2, 3, 4, 5, 6, 7, 8, 9)

dim as udt1 u11 = u20  '' should work like: dim as udt1 u11 = cast(udt1, u20)

dim as udt1 u12 = u30  '' should work like: dim as udt1 u12 = cast(udt1, u30)

dim as udt2 u21 = u30  '' should work like: dim as udt2 u21 = cast(udt2, u30)

print u11.i1  '' should be: 1
print u11.i2  '' should be: 2
print
print u12.i1  '' should be: 1
print u12.i2  '' should be: 2
print
print u21.i1  '' should be: 1
print u21.i2  '' should be: 2
print u21.i3  '' should be: 3
print u21.i4  '' should be: 4
print u21.i5  '' should be: 5
print u21.i6  '' should be: 6

sleep
should work like with fbc 1.09.0
coderJeff
Site Admin
Posts: 4326
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: FreeBASIC 1.10.0 Development

Post by coderJeff »

This is just for reference as I investigate deeper:
fbc compiler uses some common parsing code for several forms of initialization. We have been using dim variable as datatype = <INIT> for examples, but should expect some similar behaviour for all of the following (There are slight variations depending on context):

Code: Select all

Variable Initialization
	dim as T x = <INIT>

Temporary Type
	type(<INIT>)

Operator New Initialization
	new T(<INIT>)

For/To/Step Operator Initialization 
	for i as T = <INIT> to <INIT> step <INIT>

Fields Initialization
	type Q
		as field T = <INIT>
	end type

Base Constructor
	constructor T()
		base( <INIT> )
	end constructor

Optional Expression
	[declare] sub x( arg as T = <INIT> )
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC 1.10.0 Development

Post by fxm »

From the example in my first post reporting this regression, implicit up-casting from a derived variable works otherwise for:
- assignment: 'parent_instance = child_instance'
- passing by value to a procedure: 'byval v as parent' from a passed child instance
- returning by value from a function: 'function = child_instance' to a parent instance
- returning by value from a function: 'return child_instance' to a parent instance

'Operator New Initialization' (see definition above) has the same regression behavior than 'Variable Initialization' (see definition above).

'Base construction' (see definition above) from a child instance works.

'Optional Expression' (see definition above) has the same regression behavior than 'Variable Initialization' (see definition above).
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC 1.10.0 Development

Post by fxm »

A weird warning exists since several official revisions, but with gcc (32 or 64 bits) only (seems to work with gas64 or gas (32-bit)).
When assigning from a Shared derived variable:

Code: Select all

Type Parent
    Dim As Integer I
End Type

Type Child Extends Parent
    Dim As Integer J
End Type

Dim Shared As Child c0 = (1, 2)
Dim As Parent p

p = c0
Print p.I

Sleep

Code: Select all

C:\.....\FBIde0.4.6r4-FreeBASIC1.09.0.win64\FBIDETEMP.c:28:29: warning: missing braces around initializer 
   28 | static struct $5CHILD C0$ = { 1ll, 2ll };
      |                             ^
      |                               {  }

Same weird warning when passing a Shared derived variable (with gcc (32 or 64 bits) only):

Code: Select all

Type Parent
    Dim As Integer I
End Type

Type Child Extends Parent
    Dim As Integer J
End Type

Dim Shared As Child c0 = (1, 2)

Sub s1(Byval p As Parent)
    Print p.I
End Sub
s1(c0)

Sleep
With gas64, no warning but a bad value is printed.
Seems to work with gas (32-bit).

In both cases, using 'Cast(Parent, c0)' instead of 'c0' does not solve the problem !
Using 'Dim Shared As Child c0 : c0.I = 1 : C0.J = 2' instead of 'Dim Shared As Child c0 = (1, 2)' seems to suppress the warning, but does not fix the false value with gas64.
Using 'Dim Shared As Child c0 = Child(1, 2)' and a matching Child constructor, instead of 'Dim Shared As Child c0 = (1, 2)' seems to suppress the warning, but does not fix the false value with gas64.

=> Problem of casting a shared variable when assigning ?
coderJeff
Site Admin
Posts: 4326
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: FreeBASIC 1.10.0 Development

Post by coderJeff »

fxm wrote: Dec 24, 2022 14:41 => Problem of casting a shared variable when assigning ?
For the first part of the problem with gcc, it is related to #936 initializing type containing anonymous union can cause gcc warning Some versions of gcc won't complain about this, but some versions enable this warning by default with gcc -Wall warnings.

Workaround for gcc would be to turn off the warning:
#cmdline "-Wc -Wno-missing-braces"

You can see the C code by compiling with "-R", but in pseudo code it is like:

Code: Select all

'' fbc                            gcc (pseudo code)         

   type parent                    type parent                                 
     i as long                      i as long
   end type                       end type

   type child extends parent      type child
                                    base$ as parent
     j as long                      j as long
   end type                       end type
coderJeff
Site Admin
Posts: 4326
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: FreeBASIC 1.10.0 Development

Post by coderJeff »

fxm wrote: Dec 24, 2022 9:50 UDTn being the derived type of UDT0 at the nth level, and for all j >= i :
  • Dim As UDTj uj0
    Dim As UDTi ui = uj0 '' should work like: Dim As UDTi ui = Cast(UDTi, uj0)
fxm wrote: Dec 24, 2022 9:50 should work like with fbc 1.09.0
We actually have a pretty big problem here going back many versions of fbc:

Code: Select all

type parent
    dim as integer i
end type
type child extends parent
	dim as integer j, k, l, m, n, o, p, q
end type

sub test
	dim y1 as parent = type<child>(1,2,3,4,5,6,7,8,9)
end sub

test
Should probably crash on any backend since bad code is generated (by the compiler itself, not the backends).

"child" is fully copied to "parent", but since parent has space only allocated for 1 integer and child is 9 integers, memory gets trashed.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC 1.10.0 Development

Post by fxm »

Well seen Jeff !

But maybe there is still a problem that seems specific to gas64:

Code: Select all

Type Parent
    Dim As Integer I
End Type

Type Child Extends Parent
    Dim As Integer J
End Type

Sub s1(Byval p As Parent)
    Print p.I
End Sub

Dim As Parent p0
p0.I = 1
Dim As Child c0
c0.I = 1 : c0.J = 2

s1(p0)                '' printed 1: OK
s1(c0)                '' printed value <> 1: NOK (with gas64)
s1(Cast(Parent, c0))  '' printed value <> 1: NOK (with gas64)

Sleep
SARG
Posts: 1764
Joined: May 27, 2005 7:15
Location: FRANCE

Re: FreeBASIC 1.10.0 Development

Post by SARG »

Thanks fxm.
Bug fixed, when a converting involving 2 structures was done the subtype (UDT symbol) was not changed....
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC 1.10.0 Development

Post by fxm »

I apologize in advance for repeating for some, but the construction:
'Dim As Parent p = .....'
can be interpreted (from my point of view) in different ways depending on the expression '.....'.

For '.....' =
  • '(...)' : This is a simple initializer which must respect the max number elements of Parent type.
  • 'Type(...)' : This is a copy-construction with a temporary Parent (default type) variable, so the internal '...' expression must respect the max number elements of Parent type.
  • 'Type<Parent>(...)' : This is a copy-construction with a temporary Parent variable, so the internal '...' expression must respect the max number elements of Parent type.
  • 'Type<Child>(...)' : This is a copy-construction with a temporary Child variable, so the internal'...' expression must respect the max number elements of Child type, and this variable must be up-casted before assignment.
  • 'variable' : This is a copy-construction with a variable which must be compatible with the Parent type, so perform an up-casting if this variable is a derived type of Parent.
Example:

Code: Select all

Type Parent
    Dim As Integer I
End Type

Type Child Extends Parent
    Dim As Integer J
End Type

Dim As Parent p0
Dim As Child c0

Dim As Parent p1 = (1)                  '' allowed : OK
'Dim As Parent p2 = (1, 2)              '' not allowed : OK

Dim As Parent p3 = Type(1)              '' allowed : OK
'Dim As Parent p4 = Type(1, 2)          '' not allowed : OK
Dim As Parent p5 = Type<Parent>(1)      '' allowed : OK
'Dim As Parent p6 = Type(1, 2)          '' Not allowed ! OK
'Dim As Parent p7 = Type<Parent>(1, 2)  '' Not allowed : OK
Dim As Parent p8 = Type<Child>(1, 2)    '' alloved for fbc 1.09.0 : OK, not allowed for fbc 1.10.0 : NOK

Dim As Parent p9 = p0                   '' allowed : OK
Dim As Parent p10 = c0                  '' allowed : OK

Sleep
coderJeff
Site Admin
Posts: 4326
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: FreeBASIC 1.10.0 Development

Post by coderJeff »

I have some changes completed and a fix from SARG for the gas64 problem. A new major change is that all the assignments and constructor calls in an initializer that would write outside the size of the target variable or field are discarded. We also have changes for the initializer handling.

The changes touch some compiler logic not specifically related to what we are working on. For example, SWAP is maybe affected, but CONST initializers should not be. There are some common routines that handle UDT's and other data types that are slightly modified and shared by other parts of the compiler.

In the next changes, currently, TYPE(), BASE(), and NEW() initializers do not allow up-casting.
fxm wrote: Dec 25, 2022 17:24 'Dim As Parent p =.....'
can be interpreted in different ways depending on the expression '.....'.
Thanks, the latest changes follow your last post for variable initializers.

I think we probably want to allow up-casting for array elements, but it is kind of tricky without breaking all the progress we have made so far.
Here is a case that didn't work in fbc 1.09.0 and is currently not allowed in fbc 1.10.0:

Code: Select all

type parent
    dim as integer i
end type
type child extends parent
	dim as integer j
end type
type B
	p1(0 to 0) as parent
	p2 as parent	
end type

dim y1 as B = type<B> _
( _                         ''  fbc 1.09   1.10
	{ type<parent>(1) }, _  ''        ok     ok
	type<parent>(3) _       ''        ok     ok
)

print y1.p1(0).i
print y1.p2.i

dim y2 as B = type<B> _
( _                          '' fbc 1.09   1.10
	{ type<child>(1,2) }, _  ''     *bad   up-cast not allowed  
	type<child>(3,4) _       ''     *bad   up-cast not allowed
)

print y2.p1(0).i
print y2.p2.i
I should be able to push changes soon. I know we have more work to do, but seems better to share the changes as they become available.
Post Reply