aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/a-cbdlli.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/a-cbdlli.adb')
-rw-r--r--gcc/ada/a-cbdlli.adb51
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;