diff --git a/compiler/defcmp.pas b/compiler/defcmp.pas index 7ec8c1ce39..eb204ea431 100644 --- a/compiler/defcmp.pas +++ b/compiler/defcmp.pas @@ -1315,6 +1315,7 @@ implementation end else if is_zero_based_array(def_to) and + not is_cyclic(def_from) and equal_defs(tpointerdef(def_from).pointeddef,tarraydef(def_to).elementdef) then begin doconv:=tc_pointer_2_array; diff --git a/compiler/defutil.pas b/compiler/defutil.pas index bb14cfe7c9..eb01659ac6 100644 --- a/compiler/defutil.pas +++ b/compiler/defutil.pas @@ -229,6 +229,9 @@ interface {# Returns true if p is a voidpointer def } function is_voidpointer(p : tdef) : boolean; + {# Returns true if p is a cyclic reference (refers to itself at some point via pointer or array) } + function is_cyclic(p : tdef): Boolean; + {# Returns true, if definition is a float } function is_fpu(def : tdef) : boolean; @@ -1030,6 +1033,43 @@ implementation end; + { true, if p is a cyclic reference (refers to itself at some point via pointer or array) } + function is_cyclic(p : tdef): Boolean; + var + DefList: array of TDef; + CurrentTop: Integer; + + function is_cyclic_internal(def: tdef): Boolean; + var + X: Integer; + begin + if not (def.typ in [arraydef, pointerdef]) then + Exit(False); + + CurrentTop := Length(DefList); + + { Check to see if the definition has appeared already } + for X := 0 to CurrentTop - 1 do + if def = DefList[X] then + Exit(True); + + SetLength(DefList, CurrentTop + 1); + DefList[CurrentTop] := def; + + case def.typ of + arraydef: + Result := is_cyclic_internal(tarraydef(def).elementdef); + pointerdef: + Result := is_cyclic_internal(tabstractpointerdef(def).pointeddef); + else + InternalError(2022120301); + end; + end; + + begin + Result := is_cyclic_internal(p); + end; + { true, if def is a 8 bit int type } function is_8bitint(def : tdef) : boolean; begin