This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Ada] Pair miscount in Dynamic_HTable.Put
- From: Pierre-Marie de Rodat <derodat at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Hristian Kirtchev <kirtchev at adacore dot com>
- Date: Wed, 26 Sep 2018 05:24:42 -0400
- Subject: [Ada] Pair miscount in Dynamic_HTable.Put
This patch corrects the logic of GNAT.Dynamic_HTables.Dynamic_HTable.Put to
update the number of key-value pairs in the hash table only when the put is
adding a new pair, rather than updating the value of an existing pair.
Tested on x86_64-pc-linux-gnu, committed on trunk
2018-09-26 Hristian Kirtchev <kirtchev@adacore.com>
gcc/ada/
* libgnat/g-dynhta.adb (Prepend_Or_Replace): Update the number
of key-value pairs in the hash table only when adding a brand
new pair.
gcc/testsuite/
* gnat.dg/dynhash1.adb: New testcase.
--- gcc/ada/libgnat/g-dynhta.adb
+++ gcc/ada/libgnat/g-dynhta.adb
@@ -544,6 +544,9 @@ package body GNAT.Dynamic_HTables is
Detach (Nod);
Free (Nod);
+ -- The number of key-value pairs is updated when the hash table
+ -- contains a valid node which represents the pair.
+
T.Pairs := T.Pairs - 1;
-- Compress the hash table if the load factor drops below
@@ -1121,6 +1124,11 @@ package body GNAT.Dynamic_HTables is
Nod := new Node'(Key, Value, null, null);
Prepend (Nod, Head);
+
+ -- The number of key-value pairs must be updated for a prepend,
+ -- never for a replace.
+
+ T.Pairs := T.Pairs + 1;
end Prepend_Or_Replace;
-- Local variables
@@ -1148,8 +1156,6 @@ package body GNAT.Dynamic_HTables is
Prepend_Or_Replace (Head);
- T.Pairs := T.Pairs + 1;
-
-- Expand the hash table if the ratio of pairs to buckets goes over
-- Expansion_Threshold.
--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/dynhash1.adb
@@ -0,0 +1,53 @@
+with Ada.Text_IO; use Ada.Text_IO;
+with GNAT; use GNAT;
+with GNAT.Dynamic_HTables; use GNAT.Dynamic_HTables;
+
+procedure Dynhash1 is
+ function Hash (Key : Integer) return Bucket_Range_Type is
+ begin
+ return Bucket_Range_Type (Key);
+ end Hash;
+
+ package Integer_Hash_Tables is new Dynamic_HTable
+ (Key_Type => Integer,
+ Value_Type => Integer,
+ No_Value => 0,
+ Expansion_Threshold => 1.3,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ "=" => "=",
+ Hash => Hash);
+ use Integer_Hash_Tables;
+
+ Siz : Natural;
+ T : Instance;
+
+begin
+ T := Create (8);
+
+ Put (T, 1, 1);
+ Put (T, 1, 2);
+ Put (T, 1, 3);
+
+ Siz := Size (T);
+
+ if Siz /= 1 then
+ Put_Line ("ERROR: Put: wrong size");
+ Put_Line ("expected: 1");
+ Put_Line ("got :" & Siz'Img);
+ end if;
+
+ Delete (T, 1);
+ Delete (T, 1);
+
+ Siz := Size (T);
+
+ if Siz /= 0 then
+ Put_Line ("ERROR: Delete: wrong size");
+ Put_Line ("expected: 0");
+ Put_Line ("got :" & Siz'Img);
+ end if;
+
+ Destroy (T);
+end Dynhash1;