diff options
Diffstat (limited to 'gcc/ada/a-cbdlli.adb')
-rw-r--r-- | gcc/ada/a-cbdlli.adb | 51 |
1 files changed, 50 insertions, 1 deletions
diff --git a/gcc/ada/a-cbdlli.adb b/gcc/ada/a-cbdlli.adb index e1f7725d5cd..5a3169eee50 100644 --- a/gcc/ada/a-cbdlli.adb +++ b/gcc/ada/a-cbdlli.adb @@ -1164,18 +1164,66 @@ package body Ada.Containers.Bounded_Doubly_Linked_Lists is "attempt to tamper with cursors of Source (list is busy)"; end if; + -- Clear target, note that this checks busy bits of Target + Clear (Target); - while Source.Length > 0 loop + while Source.Length > 1 loop + pragma Assert (Source.First in 1 .. Source.Capacity); + pragma Assert (Source.Last /= Source.First); + pragma Assert (N (Source.First).Prev = 0); + pragma Assert (N (Source.Last).Next = 0); + + -- Copy first element from Source to Target + X := Source.First; Append (Target, N (X).Element); + -- Unlink first node of Source + Source.First := N (X).Next; N (Source.First).Prev := 0; Source.Length := Source.Length - 1; + + -- The representation invariants for Source have been restored. It is + -- now safe to free the unlinked node, without fear of corrupting the + -- active links of Source. + + -- Note that the algorithm we use here models similar algorithms used + -- in the unbounded form of the doubly-linked list container. In that + -- case, Free is an instantation of Unchecked_Deallocation, which can + -- fail (because PE will be raised if controlled Finalize fails), so + -- we must defer the call until the last step. Here in the bounded + -- form, Free merely links the node we have just "deallocated" onto a + -- list of inactive nodes, so technically Free cannot fail. However, + -- for consistency, we handle Free the same way here as we do for the + -- unbounded form, with the pessimistic assumption that it can fail. + Free (Source, X); end loop; + + if Source.Length = 1 then + pragma Assert (Source.First in 1 .. Source.Capacity); + pragma Assert (Source.Last = Source.First); + pragma Assert (N (Source.First).Prev = 0); + pragma Assert (N (Source.Last).Next = 0); + + -- Copy element from Source to Target + + X := Source.First; + Append (Target, N (X).Element); + + -- Unlink node of Source + + Source.First := 0; + Source.Last := 0; + Source.Length := 0; + + -- Return the unlinked node to the free store + + Free (Source, X); + end if; end Move; ---------- @@ -1198,6 +1246,7 @@ package body Ada.Containers.Bounded_Doubly_Linked_Lists is declare Nodes : Node_Array renames Position.Container.Nodes; Node : constant Count_Type := Nodes (Position.Node).Next; + begin if Node = 0 then return No_Element; |