aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHristian Kirtchev <kirtchev@adacore.com>2018-09-26 09:18:23 +0000
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>2018-09-26 09:18:23 +0000
commit4f95defaa9c9e60f3e07f629bde8189fb6af19cf (patch)
tree5240b291614aa754bc7f6ef295f95a3c8258f4ab
parent3e4ade66c6749652de644017de696f9c1e60f3ae (diff)
downloadgcc-4f95defaa9c9e60f3e07f629bde8189fb6af19cf.zip
gcc-4f95defaa9c9e60f3e07f629bde8189fb6af19cf.tar.gz
gcc-4f95defaa9c9e60f3e07f629bde8189fb6af19cf.tar.bz2
[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. 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. From-SVN: r264623
-rw-r--r--gcc/ada/ChangeLog6
-rw-r--r--gcc/ada/libgnat/g-dynhta.adb10
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gnat.dg/dynhash1.adb53
4 files changed, 71 insertions, 2 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index a93f5df..b9187b6 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,9 @@
+2018-09-26 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * 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.
+
2018-09-26 Sergey Rybin <rybin@adacore.com>
* doc/gnat_ugn/gnat_utility_programs.rst: Add note about
diff --git a/gcc/ada/libgnat/g-dynhta.adb b/gcc/ada/libgnat/g-dynhta.adb
index 004c276..e442514 100644
--- a/gcc/ada/libgnat/g-dynhta.adb
+++ b/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.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 459563f..6cb08cd 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2018-09-26 Hristian Kirtchev <kirtchev@adacore.com>
+ * gnat.dg/dynhash1.adb: New testcase.
+
+2018-09-26 Hristian Kirtchev <kirtchev@adacore.com>
+
* gnat.dg/sets1.adb: New testcase.
* gnat.dg/dynhash.adb, gnat.dg/linkedlist.adb: Update testcases
to new API.
diff --git a/gcc/testsuite/gnat.dg/dynhash1.adb b/gcc/testsuite/gnat.dg/dynhash1.adb
new file mode 100644
index 0000000..cbe241a
--- /dev/null
+++ b/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;