diff mbox series

[Ada] Iterators are view-specific

Message ID 20190723081350.GA95260@adacore.com
State New
Headers show
Series [Ada] Iterators are view-specific | expand

Commit Message

Pierre-Marie de Rodat July 23, 2019, 8:13 a.m. UTC
Operational aspects, such as Default_Iterator, are view-specific, and if
such an aspect appears on the full view of a private type, an object of
the type cannot be iterated upon if it is not in the scope of the full
view, This patch diagnoses properly an attempt to iterate over such an
object.

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

2019-07-23  Ed Schonberg  <schonberg@adacore.com>

gcc/ada/

	* aspects.ads: New table Operational_Aspect, used to distinguish
	between aspects that are view-specific, such as those related to
	iterators, and representation aspects that apply to all views of
	a type.
	* aspects.adb (Find_Aspect): If the aspect being sought is
	operational, do not ecamine the full view of a private type to
	retrieve it.
	* sem_ch5.adb (Analyze_Iterator_Specification): Improve error
	message when the intended domain of iteration does not implement
	the required iterator aspects.

gcc/testsuite/

	* gnat.dg/iter5.adb: Add an expected error.
	* gnat.dg/iter6.adb: New testcase.
diff mbox series

Patch

--- gcc/ada/aspects.adb
+++ gcc/ada/aspects.adb
@@ -225,7 +225,10 @@  package body Aspects is
             Owner := Root_Type (Owner);
          end if;
 
-         if Is_Private_Type (Owner) and then Present (Full_View (Owner)) then
+         if Is_Private_Type (Owner)
+            and then Present (Full_View (Owner))
+            and then not Operational_Aspect (A)
+         then
             Owner := Full_View (Owner);
          end if;
       end if;

--- gcc/ada/aspects.ads
+++ gcc/ada/aspects.ads
@@ -277,6 +277,20 @@  package Aspects is
       Aspect_Warnings                   => True,
       others                            => False);
 
+   --  The following array indicates aspects that specify operational
+   --  characteristics, and thus are view-specific. Representation
+   --  aspects break privacy, as they are needed during expansion and
+   --  code generation.
+   --  List is currently incomplete ???
+
+   Operational_Aspect : constant array (Aspect_Id) of Boolean :=
+     (Aspect_Constant_Indexing          => True,
+      Aspect_Default_Iterator           => True,
+      Aspect_Iterator_Element           => True,
+      Aspect_Iterable                   => True,
+      Aspect_Variable_Indexing          => True,
+      others                            => False);
+
    --  The following array indicates aspects for which multiple occurrences of
    --  the same aspect attached to the same declaration are allowed.
 

--- gcc/ada/sem_ch5.adb
+++ gcc/ada/sem_ch5.adb
@@ -2234,8 +2234,17 @@  package body Sem_Ch5 is
                It : Interp;
 
             begin
+               --  THe domain of iteralion must implement either the RM
+               --  iterator interface, or the SPARK Iterable aspect.
+
                if No (Iterator) then
-                  null;  --  error reported below
+                  if No
+                     (Find_Aspect (Etype (Iter_Name), Aspect_Iterable))
+                  then
+                     Error_Msg_NE ("cannot iterate over&",
+                       N, Base_Type (Etype (Iter_Name)));
+                     return;
+                  end if;
 
                elsif not Is_Overloaded (Iterator) then
                   Check_Reverse_Iteration (Etype (Iterator));

--- gcc/testsuite/gnat.dg/iter5.adb
+++ gcc/testsuite/gnat.dg/iter5.adb
@@ -4,7 +4,7 @@  with Iter5_Pkg;
 
 procedure Iter5 is
 begin
-   for The_Filename of Iter5_Pkg.Iterator_For ("C:\Program_Files") loop
+   for The_Filename of Iter5_Pkg.Iterator_For ("C:\Program_Files") loop  --  { dg-error "cannot iterate over \"Item\"" }
       null;
    end loop;
 end Iter5;

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/iter6.adb
@@ -0,0 +1,40 @@ 
+--  { dg-do compile }
+
+with Ada.Iterator_Interfaces;
+
+procedure Iter6 is
+  package Pkg is
+  type Item (<>) is limited private;
+   private
+
+   type Cursor is null record;
+
+  function Constant_Reference (The_Item     : aliased Item;
+                               Unused_Index : Cursor) return String
+     is ("");
+
+  function Has_More (Data : Cursor) return Boolean is (False);
+
+  package List_Iterator_Interfaces is new Ada.Iterator_Interfaces
+    (Cursor, Has_More);
+
+   function Iterate (The_Item : Item)
+		    return List_Iterator_Interfaces.Forward_Iterator'class
+     is (raise Program_Error);
+
+  type Item (Name_Length : Natural) is tagged limited record
+     null;
+  end record
+  with
+    Constant_Indexing => Constant_Reference,
+    Default_Iterator  => Iterate,
+    Iterator_Element  => String;
+  end Pkg; use Pkg;
+
+  type Item_Ref is access Item;
+  function F return Item_Ref is (null);
+begin
+   for I of F.all loop --  { dg-error "cannot iterate over \"Item\"" }
+     null;
+   end loop;
+end;