]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[Ada] Incorrect iteration over hashed containers after multiple Inserts
authorEd Schonberg <schonberg@adacore.com>
Fri, 21 May 2021 19:51:13 +0000 (15:51 -0400)
committerPierre-Marie de Rodat <derodat@adacore.com>
Thu, 8 Jul 2021 13:34:17 +0000 (13:34 +0000)
gcc/ada/

* libgnat/a-cohama.ads: Introduce an equality operator over
cursors.
* libgnat/a-cohase.ads: Ditto.
* libgnat/a-cohama.adb: Add body for "=" over cursors.
(Insert): Do not set the Position component of the cursor that
denotes the inserted element.
* libgnat/a-cohase.adb: Ditto.

gcc/ada/libgnat/a-cohama.adb
gcc/ada/libgnat/a-cohama.ads
gcc/ada/libgnat/a-cohase.adb
gcc/ada/libgnat/a-cohase.ads

index 26bdd5522657f56258b45c243f3b24b413749946..e6d6e4d40305a8c9396ba22e0821196ecfb005bc 100644 (file)
@@ -116,6 +116,13 @@ is
    -- "=" --
    ---------
 
+   function "=" (Left, Right : Cursor) return Boolean is
+   begin
+      return
+       Left.Container = Right.Container
+         and then Left.Node = Right.Node;
+   end "=";
+
    function "=" (Left, Right : Map) return Boolean is
    begin
       return Is_Equal (Left.HT, Right.HT);
@@ -636,7 +643,11 @@ is
       end if;
 
       Position.Container := Container'Unrestricted_Access;
-      Position.Position := HT_Ops.Index (HT, Position.Node);
+
+      --  Note that we do not set the Position component of the cursor,
+      --  because it may become incorrect on subsequent insertions/deletions
+      --  from the container. This will lose some optimizations but prevents
+      --  anomalies when the underlying hash-table is expanded or shrunk.
    end Insert;
 
    procedure Insert
@@ -679,7 +690,6 @@ is
       end if;
 
       Position.Container := Container'Unrestricted_Access;
-      Position.Position := HT_Ops.Index (HT, Position.Node);
    end Insert;
 
    procedure Insert
index a04cb3a34c6ad04c1104d601fc99627b0a5fb616..3f172bd399adf0dfde1cf7ac6735b9ea205e4ba1 100644 (file)
@@ -110,6 +110,14 @@ is
    type Cursor is private;
    pragma Preelaborable_Initialization (Cursor);
 
+   function "=" (Left, Right : Cursor) return Boolean;
+   --  The representation of cursors includes a component used to optimize
+   --  iteration over maps. This component may become unreliable after
+   --  multiple map insertions, and must be excluded from cursor equality,
+   --  so we need to provide an explicit definition for it, instead of
+   --  using predefined equality (as implied by a questionable comment
+   --  in the RM).
+
    Empty_Map : constant Map;
    --  Map objects declared without an initialization expression are
    --  initialized to the value Empty_Map.
index 31374f6b9d6eb4322ee21a2aa8d9f44b590ed2fb..2342116043e122e7d5345c9744d3395a2e9aa478 100644 (file)
@@ -145,6 +145,13 @@ is
    -- "=" --
    ---------
 
+   function "=" (Left, Right : Cursor) return Boolean is
+   begin
+      return
+       Left.Container = Right.Container
+         and then Left.Node = Right.Node;
+   end "=";
+
    function "=" (Left, Right : Set) return Boolean is
    begin
       return Is_Equal (Left.HT, Right.HT);
@@ -763,11 +770,14 @@ is
       Position  : out Cursor;
       Inserted  : out Boolean)
    is
-      HT : Hash_Table_Type renames Container'Unrestricted_Access.HT;
    begin
       Insert (Container.HT, New_Item, Position.Node, Inserted);
       Position.Container := Container'Unchecked_Access;
-      Position.Position := HT_Ops.Index (HT, Position.Node);
+
+      --  Note that we do not set the Position component of the cursor,
+      --  because it may become incorrect on subsequent insertions/deletions
+      --  from the container. This will lose some optimizations but prevents
+      --  anomalies when the underlying hash-table is expanded or shrunk.
    end Insert;
 
    procedure Insert
index f0763afbcfc72489379794eacc852a761f6e3e68..2356ba7f66abd5400a8c84a90985174d1147891f 100644 (file)
@@ -69,6 +69,15 @@ is
    type Cursor is private;
    pragma Preelaborable_Initialization (Cursor);
 
+   function "=" (Left, Right : Cursor) return Boolean;
+   --  The representation of cursors includes a component used to optimize
+   --  iteration over sets. This component may become unreliable after
+   --  multiple set insertions, and must be excluded from cursor equality,
+   --  so we need to provide an explicit definition for it, instead of
+   --  using predefined equality (as implied by a questionable comment
+   --  in the RM). This is also the case for hashed maps, and affects the
+   --  use of Insert primitives in hashed structures.
+
    Empty_Set : constant Set;
    --  Set objects declared without an initialization expression are
    --  initialized to the value Empty_Set.