This patch removes some duplicate entries for an expression function that is
the completion of a previous function declaration.

The following commonds:

      gcc -c -gnat12 p.adb
      grep greater p.ali

must yield:

   2V13*greater{boolean} 2>22 2>25 2|2b13


package P is
   function greater (X, Y : integer) return Boolean;
   function equal (x, Y: Boolean) return Boolean is (X or Y);
end P;
---
package body P is
   function greater (X, Y : integer) return Boolean is
     (X > Y);
   function incr (x : integer) return integer is (X+1);
end P;

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

2012-02-22  Ed Schonberg  <schonb...@adacore.com>

        * sem_ch6.adb (Analyze_Expression_Function): If the construct
        is a completion, indicate that its formals are the formals of
        a completion, and as such do not get a cross- reference entry.
        (Analyze_Subprogram_Specification): Do not generate a definition
        for the entity of an expression function, because it may be a
        completion. Definition will be generated if needed when analyzing
        the generated subprogram declaration.

Index: sem_ch6.adb
===================================================================
--- sem_ch6.adb (revision 184470)
+++ sem_ch6.adb (working copy)
@@ -273,7 +273,6 @@
       Spec     : constant Node_Id    := Specification (N);
 
       Def_Id :  Entity_Id;
-      pragma Unreferenced (Def_Id);
 
       Prev :  Entity_Id;
       --  If the expression is a completion, Prev is the entity whose
@@ -371,6 +370,26 @@
 
          if Has_Completion (Prev) then
             Set_Is_Inlined (Prev);
+
+            --  The formals of the expression function are body formals,
+            --  and do not appear in the ali file, which will only contain
+            --  references to the formals of the original subprogram spec.
+
+            declare
+               F1 : Entity_Id;
+               F2 : Entity_Id;
+
+            begin
+               F1 := First_Formal (Def_Id);
+               F2 := First_Formal (Prev);
+
+               while Present (F1) loop
+                  Set_Spec_Entity (F1, F2);
+                  Next_Formal (F1);
+                  Next_Formal (F2);
+               end loop;
+            end;
+
          else
             Set_Is_Inlined (Defining_Entity (New_Body));
          end if;
@@ -3198,8 +3217,12 @@
       end if;
 
       Designator := Analyze_Subprogram_Specification (Specification (N));
+
+      --  A reference may already have been generated for the unit name, in
+      --  which case the following call is redundant. However it is needed for
+      --  declarations that are the rewriting of an expression function.
+
       Generate_Definition (Designator);
-      --  ??? why this call, already in Analyze_Subprogram_Specification
 
       if Debug_Flag_C then
          Write_Str ("==> subprogram spec ");
@@ -3399,9 +3422,15 @@
          Check_SPARK_Restriction ("user-defined operator is not allowed", N);
       end if;
 
-      --  Proceed with analysis
+      --  Proceed with analysis. Do not emit a cross-reference entry if the
+      --  specification comes from an expression function, because it may be
+      --  the completion of a previous declaration. It is is not, the cross-
+      --  reference entry will be emitted for the new subprogram declaration.
 
-      Generate_Definition (Designator);
+      if Nkind (Parent (N)) /= N_Expression_Function then
+         Generate_Definition (Designator);
+      end if;
+
       Set_Contract (Designator, Make_Contract (Sloc (Designator)));
 
       if Nkind (N) = N_Function_Specification then

Reply via email to