Patchwork [Ada] Change semantics of Merge

login
register
mail settings
Submitter Arnaud Charlet
Date Nov. 4, 2011, 2:02 p.m.
Message ID <20111104140215.GA20911@adacore.com>
Download mbox | patch
Permalink /patch/123643/
State New
Headers show

Comments

Arnaud Charlet - Nov. 4, 2011, 2:02 p.m.
The semantics of Merge changed slightly per AI05-0021. It was originally the
case that if Target and Source denoted the same container object, then the GNAT
implementation of Merge did nothing. However, it was argued that RM05 did not
precisely specify the semantics for this corner case. The decision of the ARG
was that if Target and Source denote the same non-empty container object, then
Program_Error is raised.

The text of AI05-0021 can be found here:

http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai05s/ai05-0021-1.txt

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

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

	* a-convec.adb, a-coinve.adb, a-cobove.adb (Merge): Raise PE
	when Target and Source denote same non-empty object
	* a-cdlili.adb, a-cidlli.adb, a-cbdlli.adb (Merge): Ditto

Patch

Index: a-cdlili.adb
===================================================================
--- a-cdlili.adb	(revision 180934)
+++ a-cdlili.adb	(working copy)
@@ -515,10 +515,24 @@ 
          LI, RI : Cursor;
 
       begin
-         if Target'Address = Source'Address then
+
+         --  The semantics of Merge changed slightly per AI05-0021. It was
+         --  originally the case that if Target and Source denoted the same
+         --  container object, then the GNAT implementation of Merge did
+         --  nothing. However, it was argued that RM05 did not precisely
+         --  specify the semantics for this corner case. The decision of the
+         --  ARG was that if Target and Source denote the same non-empty
+         --  container object, then Program_Error is raised.
+
+         if Source.Is_Empty then
             return;
          end if;
 
+         if Target'Address = Source'Address then
+            raise Program_Error with
+              "Target and Source denote same non-empty container";
+         end if;
+
          if Target.Busy > 0 then
             raise Program_Error with
               "attempt to tamper with cursors of Target (list is busy)";
Index: a-coinve.adb
===================================================================
--- a-coinve.adb	(revision 180934)
+++ a-coinve.adb	(working copy)
@@ -1268,16 +1268,26 @@ 
          I, J : Index_Type'Base;
 
       begin
-         if Target.Last < Index_Type'First then
-            Move (Target => Target, Source => Source);
+
+         --  The semantics of Merge changed slightly per AI05-0021. It was
+         --  originally the case that if Target and Source denoted the same
+         --  container object, then the GNAT implementation of Merge did
+         --  nothing. However, it was argued that RM05 did not precisely
+         --  specify the semantics for this corner case. The decision of the
+         --  ARG was that if Target and Source denote the same non-empty
+         --  container object, then Program_Error is raised.
+
+         if Source.Last < Index_Type'First then  -- Source is empty
             return;
          end if;
 
          if Target'Address = Source'Address then
-            return;
+            raise Program_Error with
+              "Target and Source denote same non-empty container";
          end if;
 
-         if Source.Last < Index_Type'First then
+         if Target.Last < Index_Type'First then  -- Target is empty
+            Move (Target => Target, Source => Source);
             return;
          end if;
 
Index: a-cidlli.adb
===================================================================
--- a-cidlli.adb	(revision 180934)
+++ a-cidlli.adb	(working copy)
@@ -563,10 +563,24 @@ 
          LI, RI : Cursor;
 
       begin
-         if Target'Address = Source'Address then
+
+         --  The semantics of Merge changed slightly per AI05-0021. It was
+         --  originally the case that if Target and Source denoted the same
+         --  container object, then the GNAT implementation of Merge did
+         --  nothing. However, it was argued that RM05 did not precisely
+         --  specify the semantics for this corner case. The decision of the
+         --  ARG was that if Target and Source denote the same non-empty
+         --  container object, then Program_Error is raised.
+
+         if Source.Is_Empty then
             return;
          end if;
 
+         if Target'Address = Source'Address then
+            raise Program_Error with
+              "Target and Source denote same non-empty container";
+         end if;
+
          if Target.Busy > 0 then
             raise Program_Error with
               "attempt to tamper with cursors of Target (list is busy)";
Index: a-cobove.adb
===================================================================
--- a-cobove.adb	(revision 180934)
+++ a-cobove.adb	(working copy)
@@ -788,16 +788,26 @@ 
          I, J : Count_Type;
 
       begin
-         if Target.Is_Empty then
-            Move (Target => Target, Source => Source);
+
+         --  The semantics of Merge changed slightly per AI05-0021. It was
+         --  originally the case that if Target and Source denoted the same
+         --  container object, then the GNAT implementation of Merge did
+         --  nothing. However, it was argued that RM05 did not precisely
+         --  specify the semantics for this corner case. The decision of the
+         --  ARG was that if Target and Source denote the same non-empty
+         --  container object, then Program_Error is raised.
+
+         if Source.Is_Empty then
             return;
          end if;
 
          if Target'Address = Source'Address then
-            return;
+            raise Program_Error with
+              "Target and Source denote same non-empty container";
          end if;
 
-         if Source.Is_Empty then
+         if Target.Is_Empty then
+            Move (Target => Target, Source => Source);
             return;
          end if;
 
Index: a-convec.adb
===================================================================
--- a-convec.adb	(revision 180934)
+++ a-convec.adb	(working copy)
@@ -909,16 +909,26 @@ 
          J : Index_Type'Base;
 
       begin
-         if Target.Last < Index_Type'First then
-            Move (Target => Target, Source => Source);
+
+         --  The semantics of Merge changed slightly per AI05-0021. It was
+         --  originally the case that if Target and Source denoted the same
+         --  container object, then the GNAT implementation of Merge did
+         --  nothing. However, it was argued that RM05 did not precisely
+         --  specify the semantics for this corner case. The decision of the
+         --  ARG was that if Target and Source denote the same non-empty
+         --  container object, then Program_Error is raised.
+
+         if Source.Last < Index_Type'First then  -- Source is empty
             return;
          end if;
 
          if Target'Address = Source'Address then
-            return;
+            raise Program_Error with
+              "Target and Source denote same non-empty container";
          end if;
 
-         if Source.Last < Index_Type'First then
+         if Target.Last < Index_Type'First then  -- Target is empty
+            Move (Target => Target, Source => Source);
             return;
          end if;
 
Index: a-cbdlli.adb
===================================================================
--- a-cbdlli.adb	(revision 180934)
+++ a-cbdlli.adb	(working copy)
@@ -713,10 +713,24 @@ 
          LI, RI : Cursor;
 
       begin
-         if Target'Address = Source'Address then
+
+         --  The semantics of Merge changed slightly per AI05-0021. It was
+         --  originally the case that if Target and Source denoted the same
+         --  container object, then the GNAT implementation of Merge did
+         --  nothing. However, it was argued that RM05 did not precisely
+         --  specify the semantics for this corner case. The decision of the
+         --  ARG was that if Target and Source denote the same non-empty
+         --  container object, then Program_Error is raised.
+
+         if Source.Is_Empty then
             return;
          end if;
 
+         if Target'Address = Source'Address then
+            raise Program_Error with
+              "Target and Source denote same non-empty container";
+         end if;
+
          if Target.Busy > 0 then
             raise Program_Error with
               "attempt to tamper with cursors of Target (list is busy)";