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

login
register
mail settings
Submitter Arnaud Charlet
Date July 5, 2013, 9:23 a.m.
Message ID <20130705092311.GA12937@adacore.com>
Download mbox | patch
Permalink /patch/257061/
State New
Headers show

Comments

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

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,