If the expression function is not a completion, the usage names in the 
expression must be determined at the point of declaration, even though the
generated body is inserted at the end of the current declaration list or
package to prevent early freezing.

The following must be rejected with:

    forward_reference.ads:2:35: "F2" is undefined

---
package Forward_Reference is
   function F1 return Boolean is (F2);    --  Error: forward reference
   function F2 return Boolean is (True);
end Forward_Reference;

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

2011-12-12  Ed Schonberg  <schonb...@adacore.com>

        * sem_ch6.adb (Analyze_Expression_Function): If the function
        is not a completion, pre-analyze the expression now to prevent
        spurious visibility on later entities. The body is inserted at
        the end of the current declaration list or package to prevent
        early freezing, but the visibility is established at the point
        of definition.

Index: sem_ch6.adb
===================================================================
--- sem_ch6.adb (revision 182230)
+++ sem_ch6.adb (working copy)
@@ -281,6 +281,7 @@
       New_Body : Node_Id;
       New_Decl : Node_Id;
       New_Spec : Node_Id;
+      Ret      : Node_Id;
 
    begin
       --  This is one of the occasions on which we transform the tree during
@@ -302,15 +303,15 @@
          Prev     := Find_Corresponding_Spec (N);
       end if;
 
+      Ret := Make_Simple_Return_Statement (LocX, Expression (N));
+
       New_Body :=
         Make_Subprogram_Body (Loc,
           Specification              => New_Spec,
           Declarations               => Empty_List,
           Handled_Statement_Sequence =>
             Make_Handled_Sequence_Of_Statements (LocX,
-              Statements => New_List (
-                Make_Simple_Return_Statement (LocX,
-                  Expression => Expression (N)))));
+              Statements => New_List (Ret)));
 
       if Present (Prev) and then Ekind (Prev) = E_Generic_Function then
 
@@ -362,10 +363,13 @@
 
          --  To prevent premature freeze action, insert the new body at the end
          --  of the current declarations, or at the end of the package spec.
+         --  However, resolve usage names now, to prevent spurious visibility
+         --  on later entities.
 
          declare
             Decls : List_Id          := List_Containing (N);
             Par   : constant Node_Id := Parent (Decls);
+            Id    : constant Entity_Id := Defining_Entity (New_Decl);
 
          begin
             if Nkind (Par) = N_Package_Specification
@@ -377,6 +381,11 @@
             end if;
 
             Insert_After (Last (Decls), New_Body);
+            Push_Scope (Id);
+            Install_Formals (Id);
+            Preanalyze_Spec_Expression (Expression  (Ret), Etype (Id));
+            End_Scope;
+
          end;
       end if;
 

Reply via email to