Cursors for Hashed maps and hashed sets include a component that speeds
up iteration over these containers. However, in the presence of multiple
insertions into the corresponding hash-tables, this component may become
unreliable when a cursor obtained before an iteration is compared with a
cursor denoting the same element but obtained during a loop over the
container. To prevent these anomalies, we introduce an explicit equality
operator for the corresponding Cursor types, which ignores the
additional component. This patch assumes that the mention of
"predefined" equality in the sections of the RM that discuss these
cursors is in fact an over specification.
Tested on x86_64-pc-linux-gnu, committed on trunk
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.
diff --git a/gcc/ada/libgnat/a-cohama.adb b/gcc/ada/libgnat/a-cohama.adb
--- a/gcc/ada/libgnat/a-cohama.adb
+++ b/gcc/ada/libgnat/a-cohama.adb
@@ -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
diff --git a/gcc/ada/libgnat/a-cohama.ads b/gcc/ada/libgnat/a-cohama.ads
--- a/gcc/ada/libgnat/a-cohama.ads
+++ b/gcc/ada/libgnat/a-cohama.ads
@@ -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.
diff --git a/gcc/ada/libgnat/a-cohase.adb b/gcc/ada/libgnat/a-cohase.adb
--- a/gcc/ada/libgnat/a-cohase.adb
+++ b/gcc/ada/libgnat/a-cohase.adb
@@ -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
diff --git a/gcc/ada/libgnat/a-cohase.ads b/gcc/ada/libgnat/a-cohase.ads
--- a/gcc/ada/libgnat/a-cohase.ads
+++ b/gcc/ada/libgnat/a-cohase.ads
@@ -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.