This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]