[Ada] Function calls in prefixed form in preconditions in generics

Submitted by Arnaud Charlet on July 5, 2013, 9:23 a.m.

Details

Message ID 20130705092311.GA12937@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet July 5, 2013, 9:23 a.m.
A construct of the form Obj.F (X => Expr) is parsed as a function call because
of the parameter association, before the prefix is analyzed and the construct
possibly rewritten as a call to F with controlling argument Obj.  In a generic
context, if such a call appears in a precondition, and given the delay in its
elaboration, it may be copied before analysis. In that case, there is no entity
attached to the prefix.

The following must compile and execute quietly:
     gnatmake -q -gnat12a main
     main

---
with  Gen2;
procedure Main is
  type Things is (This, That);
  package IP is new Gen2 (A => Things);
begin
   null;
end main;
---
with Gen1;
generic
  type A is(<>);
package Gen2 is
  package P is new Gen1 (A => A);
end Gen2;
---
generic
  type A is(<>);
package Gen1 is
  type T is abstract tagged private;
  function F(X:in out T'class; Y: Integer)
    return boolean;
  procedure Proc(X:in out T'class; Y:Integer)
  with
    pre=>X.F(Y=>1);
private
  type T is abstract tagged record
    Z:A;
  end record;
end Gen1;
---
package body Gen1 is
  function F(X:in out T'class; Y: Integer)
    return boolean is begin return True; end;
  procedure Proc(X:in out T'class; Y:Integer) is begin null; end;
end Gen1;

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

2013-07-05  Ed Schonberg  <schonberg@adacore.com>

	* sem_ch12.adb (Copy_Generic_Node): Check that name in function
	call is a valid entity name before preserving entity in generic
	copy.

Patch hide | download patch | download mbox

Index: sem_ch12.adb
===================================================================
--- sem_ch12.adb	(revision 200688)
+++ sem_ch12.adb	(working copy)
@@ -6577,7 +6577,13 @@ 
                      Set_Entity (New_N, Entity (Assoc));
                      Check_Private_View (N);
 
-                  elsif Nkind (Assoc) = N_Function_Call then
+                  --  The name in the call may be a selected component if the
+                  --  call has not been analyzed yet, as may be the case for
+                  --  pre/post conditions in a generic unit.
+
+                  elsif Nkind (Assoc) = N_Function_Call
+                    and then Is_Entity_Name (Name (Assoc))
+                  then
                      Set_Entity (New_N, Entity (Name (Assoc)));
 
                   elsif Nkind_In (Assoc, N_Defining_Identifier,