public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [Ada] Implementation of AI05-0150 : Use_All_Type
@ 2011-08-02  8:03 Arnaud Charlet
  0 siblings, 0 replies; only message in thread
From: Arnaud Charlet @ 2011-08-02  8:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ed Schonberg

[-- Attachment #1: Type: text/plain, Size: 1316 bytes --]

Use_All_Type extends the functionality of use_type clauses: it makes potentially
use-visible all the primitive operations of a type, as well as the class-wide
operations declared in the immediate scopes of ancestor types, and the literals
of enumeration types.

The following must compile quietly:

    gcc -c -gnat12 r.adb

---
package P is
   type Enum is (Aa, Bb, Cc);
   type T is tagged null record;
   procedure Proc (X : T'Class; Y : Enum);
   procedure Moot (X : T'Class);
   function "+" (X, Y: T) return T;
end P;
---
with P;
package Q is
   subtype T_Sub is P.T;
   subtype E_Sub is P.Enum;
end Q;
---
with Q;
procedure R is
   use all type Q.T_Sub;
   Z : Q.T_Sub;
   It : Q.E_Sub;
begin
   declare
      use all type Q.E_Sub;
   begin   
      Z := Z + Z;
      Proc (X => Z, Y => Bb);
      Moot (Z);
      It := Aa;
   end;
end R;

2011-08-02  Ed Schonberg  <schonberg@adacore.com>

	* atree.ads, atree.adb: New subprograms to manipulate Elist5.
	* par_ch8.adb (P_Use_Type): initialize Used_Operations for node.
	* sinfo.ads, sinfo.adb (Used_Operations): new attribute of
	use_type_clauses, to handle more efficiently use_type and use_all_type
	constructs.
	* sem_ch8.adb: Rewrite Use_One_Type and End_Use_Type to handle the
	Ada2012 Use_All_Type clause.
	(Use_Class_Wide_Operations): new procedure.


[-- Attachment #2: difs --]
[-- Type: text/plain, Size: 14285 bytes --]

Index: sinfo.adb
===================================================================
--- sinfo.adb	(revision 177089)
+++ sinfo.adb	(working copy)
@@ -3078,6 +3078,14 @@ package body Sinfo is
       return List2 (N);
    end Visible_Declarations;
 
+   function Used_Operations
+     (N : Node_Id) return Elist_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Use_Type_Clause);
+      return Elist5 (N);
+   end Used_Operations;
+
    function Was_Originally_Stub
       (N : Node_Id) return Boolean is
    begin
@@ -6123,6 +6131,14 @@ package body Sinfo is
       Set_List2_With_Parent (N, Val);
    end Set_Visible_Declarations;
 
+   procedure Set_Used_Operations
+     (N : Node_Id; Val :  Elist_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Use_Type_Clause);
+      Set_Elist5 (N, Val);
+   end Set_Used_Operations;
+
    procedure Set_Was_Originally_Stub
       (N : Node_Id; Val : Boolean := True) is
    begin
Index: sinfo.ads
===================================================================
--- sinfo.ads	(revision 177089)
+++ sinfo.ads	(working copy)
@@ -1804,6 +1804,12 @@ package Sinfo is
    --    the body, so this flag is used to generate the proper message (see
    --    Sem_Util.Check_Unused_Withs for details)
 
+   --  Used_Operations (Elist5-Sem)
+   --    Present in N_Use_Type_Clause nodes. Holds the list of operations that
+   --    are made potentially use-visible by the clause. Simplifies processing
+   --    on exit from the scope of the use_type_clause, in particular in the
+   --    case of Use_All_Type, when those operations several scopes.
+
    --  Was_Originally_Stub (Flag13-Sem)
    --    This flag is set in the node for a proper body that replaces stub.
    --    During the analysis procedure, stubs in some situations get rewritten
@@ -4913,6 +4919,7 @@ package Sinfo is
       --  Subtype_Marks (List2)
       --  Next_Use_Clause (Node3-Sem)
       --  Hidden_By_Use_Clause (Elist4-Sem)
+      --  Used_Operations (Elist5-Sem)
       --  All_Present (Flag15)
 
       -------------------------------
@@ -8960,6 +8967,9 @@ package Sinfo is
    function Visible_Declarations
      (N : Node_Id) return List_Id;    -- List2
 
+   function Used_Operations
+     (N : Node_Id) return Elist_Id;   -- Elist5
+
    function Was_Originally_Stub
      (N : Node_Id) return Boolean;    -- Flag13
 
@@ -9932,6 +9942,9 @@ package Sinfo is
    procedure Set_Visible_Declarations
      (N : Node_Id; Val : List_Id);            -- List2
 
+   procedure Set_Used_Operations
+     (N : Node_Id; Val : Elist_Id);           -- Elist5
+
    procedure Set_Was_Originally_Stub
      (N : Node_Id; Val : Boolean := True);    -- Flag13
 
@@ -11993,6 +12006,7 @@ package Sinfo is
    pragma Inline (Variant_Part);
    pragma Inline (Variants);
    pragma Inline (Visible_Declarations);
+   pragma Inline (Used_Operations);
    pragma Inline (Was_Originally_Stub);
    pragma Inline (Withed_Body);
    pragma Inline (Zero_Cost_Handling);
@@ -12313,6 +12327,7 @@ package Sinfo is
    pragma Inline (Set_Variant_Part);
    pragma Inline (Set_Variants);
    pragma Inline (Set_Visible_Declarations);
+   pragma Inline (Set_Used_Operations);
    pragma Inline (Set_Was_Originally_Stub);
    pragma Inline (Set_Withed_Body);
    pragma Inline (Set_Zero_Cost_Handling);
Index: par-ch8.adb
===================================================================
--- par-ch8.adb	(revision 176998)
+++ par-ch8.adb	(working copy)
@@ -124,6 +124,7 @@ package body Ch8 is
       Use_Node := New_Node (N_Use_Type_Clause, Prev_Token_Ptr);
       Set_All_Present (Use_Node, All_Present);
       Set_Subtype_Marks (Use_Node, New_List);
+      Set_Used_Operations (Use_Node, No_Elist);
 
       if Ada_Version = Ada_83 then
          Error_Msg_SC ("(Ada 83) use type not allowed!");
Index: sem_ch8.adb
===================================================================
--- sem_ch8.adb	(revision 177057)
+++ sem_ch8.adb	(working copy)
@@ -2679,6 +2679,23 @@ package body Sem_Ch8 is
          Chain_Use_Clause (N);
       end if;
 
+      --  Commented needed???
+
+      if Used_Operations (N) /= No_Elist then
+         declare
+            Elmt : Elmt_Id;
+         begin
+            Elmt := First_Elmt (Used_Operations (N));
+            while Present (Elmt) loop
+               Set_Is_Potentially_Use_Visible (Node (Elmt));
+               Next_Elmt (Elmt);
+            end loop;
+         end;
+
+         return;
+      end if;
+
+      Set_Used_Operations (N, New_Elmt_List);
       Id := First (Subtype_Marks (N));
       while Present (Id) loop
          Find_Type (Id);
@@ -3535,25 +3552,8 @@ package body Sem_Ch8 is
    procedure End_Use_Type (N : Node_Id) is
       Elmt    : Elmt_Id;
       Id      : Entity_Id;
-      Op_List : Elist_Id;
-      Op      : Entity_Id;
       T       : Entity_Id;
 
-      function May_Be_Used_Primitive_Of (T : Entity_Id) return Boolean;
-      --  An operator may be primitive in several types, if they are declared
-      --  in the same scope as the operator. To determine the use-visibility of
-      --  the operator in such cases we must examine all types in the profile.
-
-      ------------------------------
-      -- May_Be_Used_Primitive_Of --
-      ------------------------------
-
-      function May_Be_Used_Primitive_Of (T : Entity_Id) return Boolean is
-      begin
-         return Scope (Op) = Scope (T)
-           and then (In_Use (T) or else Is_Potentially_Use_Visible (T));
-      end May_Be_Used_Primitive_Of;
-
    --  Start of processing for End_Use_Type
 
    begin
@@ -3585,43 +3585,22 @@ package body Sem_Ch8 is
             Set_In_Use (Base_Type (T), False);
             Set_Current_Use_Clause (T, Empty);
             Set_Current_Use_Clause (Base_Type (T), Empty);
-            Op_List := Collect_Primitive_Operations (T);
-
-            Elmt := First_Elmt (Op_List);
-            while Present (Elmt) loop
-               Op := Node (Elmt);
-
-               if Nkind (Op) = N_Defining_Operator_Symbol then
-                  declare
-                     T_First : constant Entity_Id :=
-                                 Base_Type (Etype (First_Formal (Op)));
-                     T_Res   : constant Entity_Id := Base_Type (Etype (Op));
-                     T_Next  : Entity_Id;
-
-                  begin
-                     if Present (Next_Formal (First_Formal (Op))) then
-                        T_Next :=
-                          Base_Type (Etype (Next_Formal (First_Formal (Op))));
-                     else
-                        T_Next := T_First;
-                     end if;
-
-                     if not May_Be_Used_Primitive_Of (T_First)
-                       and then not May_Be_Used_Primitive_Of (T_Next)
-                       and then not May_Be_Used_Primitive_Of (T_Res)
-                     then
-                        Set_Is_Potentially_Use_Visible (Op, False);
-                     end if;
-                  end;
-               end if;
-
-               Next_Elmt (Elmt);
-            end loop;
          end if;
 
          <<Continue>>
-         Next (Id);
+            Next (Id);
       end loop;
+
+      if Is_Empty_Elmt_List (Used_Operations (N)) then
+         return;
+
+      else
+         Elmt := First_Elmt (Used_Operations (N));
+         while Present (Elmt) loop
+            Set_Is_Potentially_Use_Visible (Node (Elmt), False);
+            Next_Elmt (Elmt);
+         end loop;
+      end if;
    end End_Use_Type;
 
    ----------------------
@@ -7578,6 +7557,11 @@ package body Sem_Ch8 is
       --  type clause is in the spec of the same package. Even though the spec
       --  was analyzed first, its context is reloaded when analysing the body.
 
+      procedure Use_Class_Wide_Operations (Typ : Entity_Id);
+      --  AI05-150: if the use_type_clause carries the "all" qualifier,
+      --  class-wide operations of ancestor types are use-visible if the
+      --  ancestor type is visible.
+
       ----------------------------
       -- Spec_Reloaded_For_Body --
       ----------------------------
@@ -7599,6 +7583,70 @@ package body Sem_Ch8 is
          return False;
       end Spec_Reloaded_For_Body;
 
+      -------------------------------
+      -- Use_Class_Wide_Operations --
+      -------------------------------
+
+      procedure Use_Class_Wide_Operations (Typ : Entity_Id) is
+         Scop : Entity_Id;
+         Ent  : Entity_Id;
+
+         function Is_Class_Wide_Operation_Of
+        (Op  : Entity_Id;
+         T   : Entity_Id) return Boolean;
+         --  Determine whether a subprogram has a class-wide parameter or
+         --  result that is T'Class.
+
+         ---------------------------------
+         --  Is_Class_Wide_Operation_Of --
+         ---------------------------------
+
+         function Is_Class_Wide_Operation_Of
+           (Op  : Entity_Id;
+            T   : Entity_Id) return Boolean
+         is
+            Formal : Entity_Id;
+
+         begin
+            Formal := First_Formal (Op);
+            while Present (Formal) loop
+               if Etype (Formal) = Class_Wide_Type (T) then
+                  return True;
+               end if;
+               Next_Formal (Formal);
+            end loop;
+
+            if Etype (Op) = Class_Wide_Type (T) then
+               return True;
+            end if;
+
+            return False;
+         end Is_Class_Wide_Operation_Of;
+
+      --  Start of processing for Use_Class_Wide_Operations
+
+      begin
+         Scop := Scope (Typ);
+         if not Is_Hidden (Scop) then
+            Ent := First_Entity (Scop);
+            while Present (Ent) loop
+               if Is_Overloadable (Ent)
+                 and then Is_Class_Wide_Operation_Of (Ent, Typ)
+                 and then not Is_Potentially_Use_Visible (Ent)
+               then
+                  Set_Is_Potentially_Use_Visible (Ent);
+                  Append_Elmt (Ent, Used_Operations (Parent (Id)));
+               end if;
+
+               Next_Entity (Ent);
+            end loop;
+         end if;
+
+         if Is_Derived_Type (Typ) then
+            Use_Class_Wide_Operations (Etype (Base_Type (Typ)));
+         end if;
+      end Use_Class_Wide_Operations;
+
    --  Start of processing for Use_One_Type;
 
    begin
@@ -7654,19 +7702,40 @@ package body Sem_Ch8 is
          Set_Current_Use_Clause (T, Parent (Id));
          Op_List := Collect_Primitive_Operations (T);
 
+         --  Iterate over primitive operations of the type. If an operation is
+         --  already use_visible, it is the result of a previous use_clause,
+         --  and already appears on the corresponding entity chain.
+
          Elmt := First_Elmt (Op_List);
          while Present (Elmt) loop
             if (Nkind (Node (Elmt)) = N_Defining_Operator_Symbol
                  or else Chars (Node (Elmt)) in Any_Operator_Name)
               and then not Is_Hidden (Node (Elmt))
+              and then not Is_Potentially_Use_Visible (Node (Elmt))
             then
                Set_Is_Potentially_Use_Visible (Node (Elmt));
+               Append_Elmt (Node (Elmt), Used_Operations (Parent (Id)));
+
+            elsif Ada_Version >= Ada_2012
+              and then All_Present (Parent (Id))
+              and then not Is_Hidden (Node (Elmt))
+              and then not Is_Potentially_Use_Visible (Node (Elmt))
+            then
+               Set_Is_Potentially_Use_Visible (Node (Elmt));
+               Append_Elmt (Node (Elmt), Used_Operations (Parent (Id)));
             end if;
 
             Next_Elmt (Elmt);
          end loop;
       end if;
 
+      if Ada_Version >= Ada_2012
+        and then All_Present (Parent (Id))
+        and then Is_Tagged_Type (T)
+      then
+         Use_Class_Wide_Operations (T);
+      end if;
+
       --  If warning on redundant constructs, check for unnecessary WITH
 
       if Warn_On_Redundant_Constructs
Index: atree.adb
===================================================================
--- atree.adb	(revision 177052)
+++ atree.adb	(working copy)
@@ -2457,6 +2457,17 @@ package body Atree is
          end if;
       end Elist4;
 
+      function Elist5 (N : Node_Id) return Elist_Id is
+         pragma Assert (N <= Nodes.Last);
+         Value : constant Union_Id := Nodes.Table (N).Field5;
+      begin
+         if Value = 0 then
+            return No_Elist;
+         else
+            return Elist_Id (Value);
+         end if;
+      end Elist5;
+
       function Elist8 (N : Node_Id) return Elist_Id is
          pragma Assert (Nkind (N) in N_Entity);
          Value : constant Union_Id := Nodes.Table (N + 1).Field8;
@@ -4696,6 +4707,11 @@ package body Atree is
          Nodes.Table (N).Field4 := Union_Id (Val);
       end Set_Elist4;
 
+      procedure Set_Elist5 (N : Node_Id; Val : Elist_Id) is
+      begin
+         Nodes.Table (N).Field5 := Union_Id (Val);
+      end Set_Elist5;
+
       procedure Set_Elist8 (N : Node_Id; Val : Elist_Id) is
       begin
          pragma Assert (Nkind (N) in N_Entity);
Index: atree.ads
===================================================================
--- atree.ads	(revision 177028)
+++ atree.ads	(working copy)
@@ -1111,6 +1111,9 @@ package Atree is
       function Elist4 (N : Node_Id) return Elist_Id;
       pragma Inline (Elist4);
 
+      function Elist5 (N : Node_Id) return Elist_Id;
+      pragma Inline (Elist5);
+
       function Elist8 (N : Node_Id) return Elist_Id;
       pragma Inline (Elist8);
 
@@ -2177,6 +2180,9 @@ package Atree is
       procedure Set_Elist4 (N : Node_Id; Val : Elist_Id);
       pragma Inline (Set_Elist4);
 
+      procedure Set_Elist5 (N : Node_Id; Val : Elist_Id);
+      pragma Inline (Set_Elist5);
+
       procedure Set_Elist8 (N : Node_Id; Val : Elist_Id);
       pragma Inline (Set_Elist8);
 
Index: atree.h
===================================================================
--- atree.h	(revision 176998)
+++ atree.h	(working copy)
@@ -431,6 +431,7 @@ extern Node_Id Current_Error_Node;
 #define Elist2(N)     Field2  (N)
 #define Elist3(N)     Field3  (N)
 #define Elist4(N)     Field4  (N)
+#define Elist5(N)     Field5  (N)
 #define Elist8(N)     Field8  (N)
 #define Elist10(N)    Field10 (N)
 #define Elist13(N)    Field13 (N)

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2011-08-02  8:03 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-02  8:03 [Ada] Implementation of AI05-0150 : Use_All_Type Arnaud Charlet

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).