diff mbox

[Ada] Proper handling of Has_Element in user-defined iterators

Message ID 20111221115340.GA12459@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Dec. 21, 2011, 11:53 a.m. UTC
To iterate over a user-defined container, it must have a primitive operation
that returns an iterator type, that is to say a type that implements one of the
iterfaces declared in an instance of Ada.Iterator_Interfaces. Has_Element is
a formal of this package. In the expansion of the iterator loop, Has_Element
renames some function of an unrelated name, declared in the package that
declares the container. Therefore the actual subprogram must be obtained from
the declaration in the instance, and not from the container package itself.

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

2011-12-21  Ed Schonberg  <schonberg@adacore.com>

	* exp_ch5.adb (Expand_Iterator_Loop): The cursor operation
	Has_Element is the formal of Iterator_Interfaces, and within
	the instantion of this package it is a renaming of some local
	function with an unrelated name. Retrieve the operation from
	the instance itself, not from the container package.
diff mbox

Patch

Index: exp_ch5.adb
===================================================================
--- exp_ch5.adb	(revision 182572)
+++ exp_ch5.adb	(working copy)
@@ -3049,10 +3049,6 @@ 
 
             Iter_Type := Etype (Name (I_Spec));
 
-            if Is_Iterator (Iter_Type) then
-               Pack := Scope (Pack);
-            end if;
-
             --  The "of" case uses an internally generated cursor whose type
             --  is found in the container package. The domain of iteration
             --  is expanded into a call to the default Iterator function, but
@@ -3074,42 +3070,42 @@ 
                begin
                   Cursor := Make_Temporary (Loc, 'I');
 
-                  if Is_Iterator (Iter_Type) then
-                     null;
+                  --  For an container element iterator, the iterator type
+                  --  is obtained from the corresponding aspect.
 
-                  else
-                     Iter_Type := Etype (Default_Iter);
+                  Iter_Type := Etype (Default_Iter);
+                  Pack := Scope (Iter_Type);
 
-                     --  Rewrite domain of iteration as a call to the default
-                     --  iterator for the container type. If the container is
-                     --  a derived type and the aspect is inherited, convert
-                     --  container to parent type. The Cursor type is also
-                     --  inherited from the scope of the parent.
+                  --  Rewrite domain of iteration as a call to the default
+                  --  iterator for the container type. If the container is
+                  --  a derived type and the aspect is inherited, convert
+                  --  container to parent type. The Cursor type is also
+                  --  inherited from the scope of the parent.
 
-                     if Base_Type (Etype (Container)) =
-                        Base_Type (Etype (First_Formal (Default_Iter)))
-                     then
-                        Container_Arg := New_Copy_Tree (Container);
+                  if Base_Type (Etype (Container)) =
+                     Base_Type (Etype (First_Formal (Default_Iter)))
+                  then
+                     Container_Arg := New_Copy_Tree (Container);
 
-                     else
-                        Container_Arg :=
-                          Make_Type_Conversion (Loc,
-                            Subtype_Mark =>
-                              New_Occurrence_Of
-                                (Etype (First_Formal (Default_Iter)), Loc),
-                            Expression => New_Copy_Tree (Container));
-                     end if;
-
-                     Rewrite (Name (I_Spec),
-                       Make_Function_Call (Loc,
-                         Name => New_Occurrence_Of (Default_Iter, Loc),
-                         Parameter_Associations =>
-                           New_List (Container_Arg)));
-                     Analyze_And_Resolve (Name (I_Spec));
+                  else
+                     Container_Arg :=
+                       Make_Type_Conversion (Loc,
+                         Subtype_Mark =>
+                           New_Occurrence_Of
+                             (Etype (First_Formal (Default_Iter)), Loc),
+                         Expression => New_Copy_Tree (Container));
                   end if;
 
-                  --  Find cursor type in proper container package.
+                  Rewrite (Name (I_Spec),
+                    Make_Function_Call (Loc,
+                      Name => New_Occurrence_Of (Default_Iter, Loc),
+                      Parameter_Associations =>
+                        New_List (Container_Arg)));
+                  Analyze_And_Resolve (Name (I_Spec));
 
+                  --  Find cursor type in proper iterator package, which
+                  --  is an instantiation of Iterator_Interfaces.
+
                   Ent := First_Entity (Pack);
                   while Present (Ent) loop
                      if Chars (Ent) = Name_Cursor then
@@ -3145,7 +3141,7 @@ 
 
                      --  Generate:
                      --    declare
-                     --       Id : Element_Type := Pack.Element (curosr);
+                     --       Id : Element_Type := Element (curosr);
                      --    begin
                      --       <original loop statements>
                      --    end;
@@ -3222,6 +3218,8 @@ 
             --    while Iterator.Has_Element loop
             --       <Stats>
             --    end loop;
+            --
+            --   Has_Element is the second actual in the iterator package
 
             New_Loop :=
               Make_Loop_Statement (Loc,
@@ -3230,16 +3228,18 @@ 
                     Condition =>
                       Make_Function_Call (Loc,
                         Name                   =>
-                          Make_Selected_Component (Loc,
-                           Prefix => New_Occurrence_Of (Pack, Loc),
-                           Selector_Name =>
-                             Make_Identifier (Loc, Name_Has_Element)),
-
+                          New_Occurrence_Of (
+                           Next_Entity (First_Entity (Pack)), Loc),
                         Parameter_Associations =>
                           New_List (
                             New_Reference_To (Cursor, Loc)))),
+
                 Statements => Stats,
                 End_Label  => Empty);
+            --                 Make_Selected_Component (Loc,
+            --       Prefix => New_Reference_To (Cursor, Loc),
+            --          Selector_Name =>
+            --         Make_Identifier (Loc, Name_Has_Element))),
 
             --  Create the declarations for Iterator and cursor and insert then
             --  before the source loop. Given that the domain of iteration is
@@ -3248,7 +3248,7 @@ 
             --  Generate:
 
             --    I : Iterator_Type renames Container;
-            --    C : Pack.Cursor_Type := Container.[First | Last];
+            --    C : Cursor_Type := Container.[First | Last];
 
             Insert_Action (N,
               Make_Object_Renaming_Declaration (Loc,