diff mbox

[Ada] Resolution of parameterless calls that return arrays

Message ID 20130910150946.GA28771@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Sept. 10, 2013, 3:09 p.m. UTC
This patch handles properly additional constructs of the form F.all (I), where
F is an access_to_function that can be called without parameters, and  that
returns an array type.

Compiling err.adb must yield:

err.adb:23:09: too many arguments in call to "A"
err.adb:24:09: too many arguments in call

---
procedure Err is
   function F return String is
   begin      
      return "ABCD";
   end F;
   
   type Acc_F is access function return String;
   
   function A return Acc_F Is
   begin
      return F'Access;
   end A;

   function AA (I : Integer) return Acc_F Is
   begin
      return F'Access;
   end AA;

   B : Integer := 1;
   C : Character;

begin
   C := A (B);           -- (1) too many arguments in call
   C := AA(1) (B);       -- (3) too many arguments in call
end Err;
---

Executing essai.adb must yield:

'A'
'B'
'C'

---
with Text_IO; use Text_IO;
procedure Essai is
   function F return String is
   begin      
      return "ABCD";
   end F;
   
   type Acc_F is access function return String;
   
   function A return Acc_F Is
   begin
      return F'Access;
   end A;

   function AA (I : Integer) return Acc_F Is
   begin
      return F'Access;
   end AA;

   B : Integer := 1;
   C : Character;

begin
   C := A.all (B);
   Put_Line (Character'image (C)); B := B+1;
   C := AA(1).all (B);
   Put_Line (Character'image (C)); B := B+1;
   C := F(B);
   Put_Line (Character'image (C)); B := B+1;
end Essai;

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

2013-09-10  Ed Schonberg  <schonberg@adacore.com>

	* sem_ch3.adb (Access_Subprogram_Declaration): Check whether the
	designated type can appear in a parameterless call.
	* sem_ch4.adb (Analyze_Call): Do not insert an explicit dereference
	in the case of an indirect call through an access function that
	returns an array type.
	(Analyze_One_Call): Handle properly legal parameterless calls
	whose result is indexed, in constructs of the for F.all (I)
	* sem_ch6.ads (May_Need_Actuals): Make public, for use on access
	to subprogram types.
	* sem_res.adb (Resolve_Call): If the call is indirect, there is
	no entity to set on the name in the call.
diff mbox

Patch

Index: sem_ch3.adb
===================================================================
--- sem_ch3.adb	(revision 202456)
+++ sem_ch3.adb	(working copy)
@@ -1256,6 +1256,11 @@ 
          end loop;
       end if;
 
+      --  Check whether an indirect call without actuals may be possible. This
+      --  is used when resolving calls whose result is then indexed.
+
+      May_Need_Actuals (Desig_Type);
+
       --  If the return type is incomplete, this is legal as long as the type
       --  is declared in the current scope and will be completed in it (rather
       --  than being part of limited view).
Index: sem_res.adb
===================================================================
--- sem_res.adb	(revision 202459)
+++ sem_res.adb	(working copy)
@@ -5460,8 +5460,14 @@ 
                  ("cannot disambiguate function call and indexing", N);
             else
                New_Subp := Relocate_Node (Subp);
-               Set_Entity (Subp, Nam);
 
+               --  The called entity may be an explicit dereference, in which
+               --  case there is no entity to set.
+
+               if Nkind (New_Subp) /= N_Explicit_Dereference then
+                  Set_Entity (Subp, Nam);
+               end if;
+
                if (Is_Array_Type (Ret_Type)
                     and then Component_Type (Ret_Type) /= Any_Type)
                  or else
Index: sem_ch4.adb
===================================================================
--- sem_ch4.adb	(revision 202451)
+++ sem_ch4.adb	(working copy)
@@ -1037,6 +1037,9 @@ 
          --  function that returns a pointer_to_procedure which is the entity
          --  being called. Finally, F (X) may be a call to a parameterless
          --  function that returns a pointer to a function with parameters.
+         --  Note that if F return an access to subprogram whose designated
+         --  type is an array, F (X) cannot be interpreted as an indirect call
+         --  through the result of the call to F.
 
          elsif Is_Access_Type (Etype (Nam))
            and then Ekind (Designated_Type (Etype (Nam))) = E_Subprogram_Type
@@ -1047,6 +1050,8 @@ 
                   (Nkind (Parent (N)) /= N_Explicit_Dereference
                      and then Is_Entity_Name (Nam)
                      and then No (First_Formal (Entity (Nam)))
+                     and then not
+                       Is_Array_Type (Etype (Designated_Type (Etype (Nam))))
                      and then Present (Actuals)))
          then
             Nam_Ent := Designated_Type (Etype (Nam));
@@ -2998,7 +3003,9 @@ 
          return;
       end if;
 
-      --  An indexing requires at least one actual
+      --  An indexing requires at least one actual.The name of the call cannot
+      --  be an implicit indirect call, so it cannot be a generated explicit
+      --  dereference.
 
       if not Is_Empty_List (Actuals)
         and then
@@ -3007,7 +3014,11 @@ 
               (Needs_One_Actual (Nam)
                  and then Present (Next_Actual (First (Actuals)))))
       then
-         if Is_Array_Type (Subp_Type) then
+         if Is_Array_Type (Subp_Type)
+           and then
+            (Nkind (Name (N)) /= N_Explicit_Dereference
+              or else Comes_From_Source (Name (N)))
+         then
             Is_Indexed := Try_Indexed_Call (N, Nam, Subp_Type, Must_Skip);
 
          elsif Is_Access_Type (Subp_Type)
@@ -3046,9 +3057,14 @@ 
       if not Norm_OK then
 
          --  If an indirect call is a possible interpretation, indicate
-         --  success to the caller.
+         --  success to the caller. This may be an indecing of an explicit
+         --  dereference of a call that returns an access type (see above).
 
-         if Is_Indirect then
+         if Is_Indirect
+           or else (Is_Indexed
+                     and then Nkind (Name (N)) = N_Explicit_Dereference
+                     and then Comes_From_Source (Name (N)))
+         then
             Success := True;
             return;
 
Index: sem_ch6.adb
===================================================================
--- sem_ch6.adb	(revision 202460)
+++ sem_ch6.adb	(working copy)
@@ -211,10 +211,6 @@ 
    --  Create the declaration for an inequality operator that is implicitly
    --  created by a user-defined equality operator that yields a boolean.
 
-   procedure May_Need_Actuals (Fun : Entity_Id);
-   --  Flag functions that can be called without parameters, i.e. those that
-   --  have no parameters, or those for which defaults exist for all parameters
-
    procedure Process_PPCs
      (N       : Node_Id;
       Spec_Id : Entity_Id;
Index: sem_ch6.ads
===================================================================
--- sem_ch6.ads	(revision 202451)
+++ sem_ch6.ads	(working copy)
@@ -234,6 +234,13 @@ 
    --  E is the entity for a subprogram or generic subprogram spec. This call
    --  lists all inherited Pre/Post aspects if List_Inherited_Pre_Post is True.
 
+   procedure May_Need_Actuals (Fun : Entity_Id);
+   --  Flag functions that can be called without parameters, i.e. those that
+   --  have no parameters, or those for which defaults exist for all parameters
+   --  Used for subprogram declarations and for access subprogram declarations,
+   --  where they apply to the anonymous designated type. On return the flag
+   --  Set_Needs_No_Actuals is set appropriately in Fun.
+
    function Mode_Conformant (New_Id, Old_Id : Entity_Id) return Boolean;
    --  Determine whether two callable entities (subprograms, entries,
    --  literals) are mode conformant (RM 6.3.1(15))