[multiple changes]
authorArnaud Charlet <charlet@gcc.gnu.org>
Sun, 20 Nov 2011 11:44:38 +0000 (12:44 +0100)
committerArnaud Charlet <charlet@gcc.gnu.org>
Sun, 20 Nov 2011 11:44:38 +0000 (12:44 +0100)
2011-11-20  Robert Dewar  <dewar@adacore.com>

* exp_ch6.adb, exp_util.adb: Minor reformatting

2011-11-20  Eric Botcazou  <ebotcazou@adacore.com>

* sinfo.ads (Reference): Document that it is OK to set
Is_Known_Non_Null on a temporary initialized to a N_Reference
node.

2011-11-20  Matthew Heaney  <heaney@adacore.com>

* a-cbdlli.adb, a-cfdlli.adb (Move): Set Last component to 0
for Source list.

From-SVN: r181530

gcc/ada/ChangeLog
gcc/ada/a-cbdlli.adb
gcc/ada/a-cfdlli.adb
gcc/ada/exp_ch6.adb
gcc/ada/exp_util.adb
gcc/ada/sinfo.ads

index 35a2096ca37e3a82374a9ac4c18d68a401ce8aa7..22f5712ceeea5fe53690e93d4329a1dd39fda2ba 100644 (file)
@@ -1,3 +1,18 @@
+2011-11-20  Robert Dewar  <dewar@adacore.com>
+
+       * exp_ch6.adb, exp_util.adb: Minor reformatting
+
+2011-11-20  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * sinfo.ads (Reference): Document that it is OK to set
+       Is_Known_Non_Null on a temporary initialized to a N_Reference
+       node.
+
+2011-11-20  Matthew Heaney  <heaney@adacore.com>
+
+       * a-cbdlli.adb, a-cfdlli.adb (Move): Set Last component to 0
+       for Source list.
+
 2011-11-20  Eric Botcazou  <ebotcazou@adacore.com>
 
        * exp_ch6.adb (Make_Build_In_Place_Call_In_Assignment):
index e1f7725d5cdf2dcf74ddd3bbddcfd4ab0b5f3dc1..9e4007159407a937ffd0b9377fcb0b0a2ef9d8e9 100644 (file)
@@ -1164,18 +1164,67 @@ package body Ada.Containers.Bounded_Doubly_Linked_Lists is
            "attempt to tamper with cursors of Source (list is busy)";
       end if;
 
-      Clear (Target);
+      Clear (Target);  -- checks busy bit of Target
+
+      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
 
-      while Source.Length > 0 loop
          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 very 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;
 
    ----------
index 93a88a725d635ddbfeb3584c96126261ce009b0d..d1bd218972d502d68883c0494de53355b7842f65 100644 (file)
@@ -1007,16 +1007,65 @@ package body Ada.Containers.Formal_Doubly_Linked_Lists is
 
       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);  -- optimize away???
 
+         --  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 very 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;
 
    ----------
index f3d915de74acdc7f7cce8686e87995310eabca76..227f72921befcf34d759a3e3d4a8816a40f3a129 100644 (file)
@@ -8034,7 +8034,8 @@ package body Exp_Ch6 is
       Insert_After_And_Analyze (Assign, Ptr_Typ_Decl);
 
       --  Finally, create an access object initialized to a reference to the
-      --  function call.
+      --  function call. We know this access value is non-null, so mark the
+      --  entity accordingly to suppress junk access checks.
 
       New_Expr := Make_Reference (Loc, Relocate_Node (Func_Call));
 
@@ -8299,7 +8300,8 @@ package body Exp_Ch6 is
       end if;
 
       --  Finally, create an access object initialized to a reference to the
-      --  function call.
+      --  function call. We know this access value cannot be null, so mark the
+      --  entity accordingly to suppress the access check.
 
       New_Expr := Make_Reference (Loc, Relocate_Node (Func_Call));
 
index 56a6f20ed1902bee90c72e6f3c69886fc9e6b16f..37a1be0e47876899987cc1360a08443ab838f4df 100644 (file)
@@ -6710,6 +6710,10 @@ package body Exp_Util is
 
             if Alfa_Mode then
                New_Exp := E;
+
+            --  Otherwise generate reference, marking the value as non-null
+            --  since we know it cannot be null and we don't want a check.
+
             else
                New_Exp := Make_Reference (Loc, E);
                Set_Is_Known_Non_Null (Def_Id);
index 35a73f9ad94d3b366583cb566efc4755481f00d6..3379faef0385096c46457f875d393917d28dd11f 100644 (file)
@@ -7310,6 +7310,11 @@ package Sinfo is
       --  more sense to call it an Expression field, but then we would have to
       --  special case the treatment of the N_Reference node.
 
+      --  Note: evaluating a N_Reference node is guaranteed to yield a non-null
+      --  value at run time. Therefore, it is valid to set Is_Known_Non_Null on
+      --  a temporary initialized to a N_Reference node in order to eliminate
+      --  superfluous access checks.
+
       --  Sprint syntax: prefix'reference
 
       --  N_Reference