This patch corrects the implementation of routine Insert_Child in the following
multiway tree packages:

   Ada.Containers.Indefinite_Multiway_Trees
   Ada.Containers.Multiway_Trees

As a result, Insert_Child no longer returns a faulty Position when inserting
elements.

------------
-- Source --
------------

--  multi_main.adb

with Ada.Containers.Multiway_Trees;
with Ada.Text_IO; use Ada.Text_IO;

procedure Multi_Main is
   Size : constant := 4;

   type Small_Int is new Integer range 1 .. 9
     with Default_Value => 1;

   package MWT is new Ada.Containers.Multiway_Trees (Small_Int);
   use MWT;

   procedure Print_Tree (T : Tree) is
      procedure Output (C : Cursor) is
      begin
         Put_Line (Element (C)'Img);
      end Output;

   begin
      T.Iterate (Output'Access);
   end Print_Tree;

   T : Tree;
   R : constant Cursor := T.Root;
   C : Cursor;

begin
   for Index in 1 .. Size loop
      T.Prepend_Child (R, 8);
   end loop;

   T.Clear;

   T.Insert_Child
     (Parent   => R,
      Before   => No_Element,
      Position => C,
      Count    => 1);

   T.Insert_Child
     (Parent   => R,
      Before   => C,
      Position => C,
      New_Item => 2,
      Count    => 2);

   Print_Tree (T);
end Multi_Main;

----------------------------
-- Compilation and output --
----------------------------

$ gnatmake -q multi_main.adb
$ ./multi_main
 2
 2
 1

Tested on x86_64-pc-linux-gnu, committed on trunk

2014-10-30  Hristian Kirtchev  <kirtc...@adacore.com>

        * a-comutr.adb, a-cimutr.adb (Insert_Child): Add new variable First.
        Update the position after all insertions have taken place.

Index: a-cimutr.adb
===================================================================
--- a-cimutr.adb        (revision 216770)
+++ a-cimutr.adb        (working copy)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 2004-2013, Free Software Foundation, Inc.         --
+--          Copyright (C) 2004-2014, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -1217,6 +1217,7 @@
       Position  : out Cursor;
       Count     : Count_Type := 1)
    is
+      First   : Tree_Node_Access;
       Last    : Tree_Node_Access;
       Element : Element_Access;
 
@@ -1249,8 +1250,6 @@
            with "attempt to tamper with cursors (tree is busy)";
       end if;
 
-      Position.Container := Parent.Container;
-
       declare
          --  The element allocator may need an accessibility check in the case
          --  the actual type is class-wide or has access discriminants (see
@@ -1264,16 +1263,16 @@
          Element := new Element_Type'(New_Item);
       end;
 
-      Position.Node := new Tree_Node_Type'(Parent  => Parent.Node,
-                                           Element => Element,
-                                           others  => <>);
+      First := new Tree_Node_Type'(Parent  => Parent.Node,
+                                   Element => Element,
+                                   others  => <>);
 
-      Last := Position.Node;
+      Last := First;
+      for J in Count_Type'(2) .. Count loop
 
-      for J in Count_Type'(2) .. Count loop
          --  Reclaim other nodes if Storage_Error.  ???
 
-         Element := new Element_Type'(New_Item);
+         Element   := new Element_Type'(New_Item);
          Last.Next := new Tree_Node_Type'(Parent  => Parent.Node,
                                           Prev    => Last,
                                           Element => Element,
@@ -1283,7 +1282,7 @@
       end loop;
 
       Insert_Subtree_List
-        (First  => Position.Node,
+        (First  => First,
          Last   => Last,
          Parent => Parent.Node,
          Before => Before.Node);
@@ -1293,6 +1292,8 @@
       --  nodes we just inserted.
 
       Container.Count := Container.Count + Count;
+
+      Position := Cursor'(Parent.Container, First);
    end Insert_Child;
 
    -------------------------
Index: a-comutr.adb
===================================================================
--- a-comutr.adb        (revision 216770)
+++ a-comutr.adb        (working copy)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 2004-2013, Free Software Foundation, Inc.         --
+--          Copyright (C) 2004-2014, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -272,7 +272,8 @@
       New_Item  : Element_Type;
       Count     : Count_Type := 1)
    is
-      First, Last : Tree_Node_Access;
+      First : Tree_Node_Access;
+      Last  : Tree_Node_Access;
 
    begin
       if Parent = No_Element then
@@ -297,7 +298,6 @@
                                    others  => <>);
 
       Last := First;
-
       for J in Count_Type'(2) .. Count loop
 
          --  Reclaim other nodes if Storage_Error.  ???
@@ -1171,7 +1171,8 @@
       Position  : out Cursor;
       Count     : Count_Type := 1)
    is
-      Last : Tree_Node_Access;
+      First : Tree_Node_Access;
+      Last  : Tree_Node_Access;
 
    begin
       if Parent = No_Element then
@@ -1202,13 +1203,11 @@
            with "attempt to tamper with cursors (tree is busy)";
       end if;
 
-      Position.Container := Parent.Container;
-      Position.Node := new Tree_Node_Type'(Parent  => Parent.Node,
-                                           Element => New_Item,
-                                           others  => <>);
+      First := new Tree_Node_Type'(Parent  => Parent.Node,
+                                   Element => New_Item,
+                                   others  => <>);
 
-      Last := Position.Node;
-
+      Last := First;
       for J in Count_Type'(2) .. Count loop
 
          --  Reclaim other nodes if Storage_Error.  ???
@@ -1222,7 +1221,7 @@
       end loop;
 
       Insert_Subtree_List
-        (First  => Position.Node,
+        (First  => First,
          Last   => Last,
          Parent => Parent.Node,
          Before => Before.Node);
@@ -1232,6 +1231,8 @@
       --  nodes we just inserted.
 
       Container.Count := Container.Count + Count;
+
+      Position := Cursor'(Parent.Container, First);
    end Insert_Child;
 
    procedure Insert_Child
@@ -1241,7 +1242,8 @@
       Position  : out Cursor;
       Count     : Count_Type := 1)
    is
-      Last : Tree_Node_Access;
+      First : Tree_Node_Access;
+      Last  : Tree_Node_Access;
 
    begin
       if Parent = No_Element then
@@ -1272,13 +1274,11 @@
            with "attempt to tamper with cursors (tree is busy)";
       end if;
 
-      Position.Container := Parent.Container;
-      Position.Node := new Tree_Node_Type'(Parent  => Parent.Node,
-                                           Element => <>,
-                                           others  => <>);
+      First := new Tree_Node_Type'(Parent  => Parent.Node,
+                                   Element => <>,
+                                   others  => <>);
 
-      Last := Position.Node;
-
+      Last := First;
       for J in Count_Type'(2) .. Count loop
 
          --  Reclaim other nodes if Storage_Error.  ???
@@ -1292,7 +1292,7 @@
       end loop;
 
       Insert_Subtree_List
-        (First  => Position.Node,
+        (First  => First,
          Last   => Last,
          Parent => Parent.Node,
          Before => Before.Node);
@@ -1302,6 +1302,8 @@
       --  nodes we just inserted.
 
       Container.Count := Container.Count + Count;
+
+      Position := Cursor'(Parent.Container, First);
    end Insert_Child;
 
    -------------------------

Reply via email to