Quellcode durchsuchen

* New is_cyclic function to detect if def references itself - fixes #40010

J. Gareth "Curious Kit" Moreton vor 2 Jahren
Ursprung
Commit
f00a932cc6
2 geänderte Dateien mit 41 neuen und 0 gelöschten Zeilen
  1. 1 0
      compiler/defcmp.pas
  2. 40 0
      compiler/defutil.pas

+ 1 - 0
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;

+ 40 - 0
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