[multiple changes]
authorArnaud Charlet <charlet@gcc.gnu.org>
Thu, 21 Apr 2016 08:25:21 +0000 (10:25 +0200)
committerArnaud Charlet <charlet@gcc.gnu.org>
Thu, 21 Apr 2016 08:25:21 +0000 (10:25 +0200)
2016-04-21  Hristian Kirtchev  <kirtchev@adacore.com>

* sem_aux.ads, sem_aux.adb (Has_Rep_Item): New variant.
* sem_util.adb (Inherit_Rep_Item_Chain): Reimplemented.

2016-04-21  Hristian Kirtchev  <kirtchev@adacore.com>

* exp_ch6.adb: Minor reformatting.

2016-04-21  Ed Schonberg  <schonberg@adacore.com>

* sem_ch13.adb: Minor comment update.

2016-04-21  Ed Schonberg  <schonberg@adacore.com>

* freeze.ads, freeze.adb (Freeze_Entity, Freeze_Before): Add
boolean parameter to determine whether freezing an overloadable
entity freezes its profile as well. This is required by
AI05-019. The call to Freeze_Profile within Freeze_Entity is
conditioned by the value of this flag, whose default is True.
* sem_attr.adb (Resolve_Attribute, case 'Access): The attribute
reference freezes the prefix, but it the prefix is a subprogram
it does not freeze its profile.

From-SVN: r235308

gcc/ada/ChangeLog
gcc/ada/exp_ch6.adb
gcc/ada/freeze.adb
gcc/ada/freeze.ads
gcc/ada/sem_attr.adb
gcc/ada/sem_aux.adb
gcc/ada/sem_aux.ads
gcc/ada/sem_ch13.adb
gcc/ada/sem_util.adb

index c349a060dea4d5e8018ef28a0188204fe6af7075..c44e72cd2f4b3cba9abbeb446b99384b467e29f6 100644 (file)
@@ -1,3 +1,27 @@
+2016-04-21  Hristian Kirtchev  <kirtchev@adacore.com>
+
+       * sem_aux.ads, sem_aux.adb (Has_Rep_Item): New variant.
+       * sem_util.adb (Inherit_Rep_Item_Chain): Reimplemented.
+
+2016-04-21  Hristian Kirtchev  <kirtchev@adacore.com>
+
+       * exp_ch6.adb: Minor reformatting.
+
+2016-04-21  Ed Schonberg  <schonberg@adacore.com>
+
+       * sem_ch13.adb: Minor comment update.
+
+2016-04-21  Ed Schonberg  <schonberg@adacore.com>
+
+       * freeze.ads, freeze.adb (Freeze_Entity, Freeze_Before): Add
+       boolean parameter to determine whether freezing an overloadable
+       entity freezes its profile as well. This is required by
+       AI05-019. The call to Freeze_Profile within Freeze_Entity is
+       conditioned by the value of this flag, whose default is True.
+       * sem_attr.adb (Resolve_Attribute, case 'Access): The attribute
+       reference freezes the prefix, but it the prefix is a subprogram
+       it does not freeze its profile.
+
 2016-04-21  Javier Miranda  <miranda@adacore.com>
 
        * exp_util.adb (Build_Procedure_Form): No action needed for
index d084c3791235bc45d354f44c63349a27c9462f89..ff9530b931f69e2b082ddd464653a87bcf4b9146 100644 (file)
@@ -706,11 +706,10 @@ package body Exp_Ch6 is
                   Stmts   : List_Id;
 
                begin
-                  --  The extended return may just contain the declaration.
+                  --  The extended return may just contain the declaration
 
                   if Present (Handled_Statement_Sequence (Stmt)) then
-                     Stmts :=  Statements (Handled_Statement_Sequence (Stmt));
-
+                     Stmts := Statements (Handled_Statement_Sequence (Stmt));
                   else
                      Stmts := New_List;
                   end if;
@@ -2697,10 +2696,9 @@ package body Exp_Ch6 is
          --  See for example Expand_Boolean_Operator().
 
          if not (Comes_From_Source (Call_Node))
-           and then Nkind
-                      (Unit_Declaration_Node
-                        (Ultimate_Alias (Entity (Name (Call_Node)))))
-                      = N_Subprogram_Body
+           and then Nkind (Unit_Declaration_Node
+                            (Ultimate_Alias (Entity (Name (Call_Node))))) =
+                              N_Subprogram_Body
          then
             Set_Entity (Name (Call_Node),
               Rewritten_For_C_Func_Id
index 572b194e6876032d90ed005a040ccbefb7f605c7..f5e114a0cabe6f07bebd687b536e01a45d5ab84e 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2015, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2016, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -1908,8 +1908,16 @@ package body Freeze is
    -- Freeze_Before --
    -------------------
 
-   procedure Freeze_Before (N : Node_Id; T : Entity_Id) is
-      Freeze_Nodes : constant List_Id := Freeze_Entity (T, N);
+   procedure Freeze_Before
+     (N   : Node_Id;
+      T   : Entity_Id;
+      F_P : Boolean := True)
+   is
+   --  Freeze T, then insert the generated Freeze nodes before the node N.
+   --  The flag F_P is used when T is an overloadable entity, and indicates
+   --  whether its profile should be frozen at the same time.
+
+      Freeze_Nodes : constant List_Id := Freeze_Entity (T, N, F_P);
 
    begin
       if Ekind (T) = E_Function then
@@ -1925,7 +1933,11 @@ package body Freeze is
    -- Freeze_Entity --
    -------------------
 
-   function Freeze_Entity (E : Entity_Id; N : Node_Id) return List_Id is
+   function Freeze_Entity
+     (E : Entity_Id;
+      N : Node_Id;
+      F_P : Boolean := True) return List_Id
+   is
       Loc    : constant Source_Ptr := Sloc (N);
       Atype  : Entity_Id;
       Comp   : Entity_Id;
@@ -4990,12 +5002,13 @@ package body Freeze is
 
             --  In Ada 2012, freezing a subprogram does not always freeze
             --  the corresponding profile (see AI05-019). An attribute
-            --  reference is not a freezing point of the profile.
+            --  reference is not a freezing point of the profile. The boolean
+            --  Flag F_P indicates whether the profile should be frozen now.
             --  Other constructs that should not freeze ???
 
             --  This processing doesn't apply to internal entities (see below)
 
-            if not Is_Internal (E) then
+            if not Is_Internal (E) and then F_P then
                if not Freeze_Profile (E) then
                   Ghost_Mode := Save_Ghost_Mode;
                   return Result;
index f11347d5ed0117a99384ea6e5b16f4b9d7bb670c..d95038152fce8d96c0e4aee7cfcb1f8fe330b485 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 1992-2015, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2016, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -187,13 +187,19 @@ package Freeze is
    --  If Initialization_Statements (E) is an N_Compound_Statement, insert its
    --  actions in the enclosing list and reset the attribute.
 
-   function Freeze_Entity (E : Entity_Id; N : Node_Id) return List_Id;
+   function Freeze_Entity
+     (E : Entity_Id;
+      N : Node_Id;
+      F_P : Boolean := True) return List_Id;
    --  Freeze an entity, and return Freeze nodes, to be inserted at the point
    --  of call. N is a node whose source location corresponds to the freeze
    --  point. This is used in placing warning messages in the situation where
    --  it appears that a type has been frozen too early, e.g. when a primitive
    --  operation is declared after the freezing point of its tagged type.
    --  Returns No_List if no freeze nodes needed.
+   --  The defaulted parameter F_P is used when E is a subprogram, and
+   --  determines whether the profile of the subprogram should be frozen as
+   --  well.
 
    procedure Freeze_All (From : Entity_Id; After : in out Node_Id);
    --  Before a non-instance body, or at the end of a declarative part,
@@ -209,8 +215,13 @@ package Freeze is
    --  in the scope. It is used to prevent a quadratic traversal over already
    --  frozen entities.
 
-   procedure Freeze_Before (N : Node_Id; T : Entity_Id);
+   procedure Freeze_Before
+     (N   : Node_Id;
+      T   : Entity_Id;
+      F_P : Boolean := True);
    --  Freeze T then Insert the generated Freeze nodes before the node N
+   --  The flag F_P is used when T is an overloadable entity, and indicates
+   --  whether its profile should be frozen at the same time.
 
    procedure Freeze_Expression (N : Node_Id);
    --  Freezes the required entities when the Expression N causes freezing.
index e8483b9eebdae94b08b6f605209c7307e710183b..099a1b84bc3db6cada414a11389f515ca4fb856d 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2015, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2016, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -10161,18 +10161,20 @@ package body Sem_Attr is
                   end loop;
 
                   --  If Prefix is a subprogram name, this reference freezes,
-                  --  but not if within spec expression mode
+                  --  but not if within spec expression mode. The profile of
+                  --  the subprogram is not frozen at this point.
 
                   if not In_Spec_Expression then
-                     Freeze_Before (N, Entity (P));
+                     Freeze_Before (N, Entity (P), False);
                   end if;
 
-               --  If it is a type, there is nothing to resolve. If it is an
-               --  object, complete its resolution.
+               --  If it is a type, there is nothing to resolve.
+               --  If it is a subprogram, do not freeze its profile.
+               --  If it is an object, complete its resolution.
 
                elsif Is_Overloadable (Entity (P)) then
                   if not In_Spec_Expression then
-                     Freeze_Before (N, Entity (P));
+                     Freeze_Before (N, Entity (P), False);
                   end if;
 
                --  Nothing to do if prefix is a type name
index 79a3b9996a0f94c158d1330c68e85d0f7b7d0636..b9aa2df04a0b0da337224b63374f3a3356baf1cc 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2015, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2016, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -708,6 +708,29 @@ package body Sem_Aux is
       return Present (Get_Rep_Item (E, Nam1, Nam2, Check_Parents));
    end Has_Rep_Item;
 
+   function Has_Rep_Item (E : Entity_Id; N : Node_Id) return Boolean is
+      Item : Node_Id;
+
+   begin
+      pragma Assert
+        (Nkind_In (N, N_Aspect_Specification,
+                      N_Attribute_Definition_Clause,
+                      N_Enumeration_Representation_Clause,
+                      N_Pragma,
+                      N_Record_Representation_Clause));
+
+      Item := First_Rep_Item (E);
+      while Present (Item) loop
+         if Item = N then
+            return True;
+         end if;
+
+         Item := Next_Rep_Item (Item);
+      end loop;
+
+      return False;
+   end Has_Rep_Item;
+
    --------------------
    -- Has_Rep_Pragma --
    --------------------
index ba60284daac2179a856b9b06b51acfe9ef6b85b1..97a4f142d0ff8ca63ae9b117116d12f6f949f598 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 1992-2015, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2016, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -246,6 +246,10 @@ package Sem_Aux is
    --  not inherited from its parents, if any). If found then True is returned,
    --  otherwise False indicates that no matching entry was found.
 
+   function Has_Rep_Item (E : Entity_Id; N : Node_Id) return Boolean;
+   --  Determine whether the Rep_Item chain of arbitrary entity E contains item
+   --  N. N must denote a valid rep item.
+
    function Has_Rep_Pragma
      (E             : Entity_Id;
       Nam           : Name_Id;
index 352742aeae33712d3e2171076cb1943b8ac96b11..0fe363546441af4778e347b5762e1d15365cc573 100644 (file)
@@ -3926,7 +3926,8 @@ package body Sem_Ch13 is
                return;
 
             --  A stream subprogram for an interface type must be a null
-            --  procedure (RM 13.13.2 (38/3)).
+            --  procedure (RM 13.13.2 (38/3)). Note that the class-wide type
+            --  of an interface is not an interface type (3.9.4 (6.b/2)).
 
             elsif Is_Interface (U_Ent)
               and then not Is_Class_Wide_Type (U_Ent)
index 0702cc71970af1f6b05368b2cf6cd53c744b07e2..a10671144bfb9fce946dee35ba9d4b44981cae7c 100644 (file)
@@ -10733,57 +10733,143 @@ package body Sem_Util is
    ----------------------------
 
    procedure Inherit_Rep_Item_Chain (Typ : Entity_Id; From_Typ : Entity_Id) is
-      From_Item : constant Node_Id := First_Rep_Item (From_Typ);
-      Item      : Node_Id := Empty;
-      Last_Item : Node_Id := Empty;
+      Item      : Node_Id;
+      Next_Item : Node_Id;
 
    begin
-      --  Reach the end of the destination type's chain (if any) and capture
-      --  the last item.
+      --  There are several inheritance scenarios to consider depending on
+      --  whether both types have rep item chains and whether the destination
+      --  type already inherits part of the source type's rep item chain.
 
-      Item := First_Rep_Item (Typ);
-      while Present (Item) loop
+      --  1) The source type lacks a rep item chain
+      --     From_Typ ---> Empty
+      --
+      --     Typ --------> Item (or Empty)
 
-         --  Do not inherit a chain that has been inherited already
+      --  In this case inheritance cannot take place because there are no items
+      --  to inherit.
 
-         if Item = From_Item then
-            return;
-         end if;
+      --  2) The destination type lacks a rep item chain
+      --     From_Typ ---> Item ---> ...
+      --
+      --     Typ --------> Empty
 
-         Last_Item := Item;
-         Item := Next_Rep_Item (Item);
-      end loop;
+      --  Inheritance takes place by setting the First_Rep_Item of the
+      --  destination type to the First_Rep_Item of the source type.
+      --     From_Typ ---> Item ---> ...
+      --                    ^
+      --     Typ -----------+
 
-      Item := First_Rep_Item (From_Typ);
+      --  3.1) Both source and destination types have at least one rep item.
+      --  The destination type does NOT inherit a rep item from the source
+      --  type.
+      --     From_Typ ---> Item ---> Item
+      --
+      --     Typ --------> Item ---> Item
 
-      --  Additional check when both parent and current type have rep.
-      --  items, to prevent circularities when the derivation completes
-      --  a private declaration and inherits from both views of the parent.
-      --  There may be a remaining problem with the proper ordering of
-      --  attribute specifications and aspects on the chains of the four
-      --  entities involved. ???
+      --  Inheritance takes place by setting the Next_Rep_Item of the last item
+      --  of the destination type to the First_Rep_Item of the source type.
+      --     From_Typ -------------------> Item ---> Item
+      --                                    ^
+      --     Typ --------> Item ---> Item --+
 
-      if Present (Item) and then Present (From_Item) then
-         while Present (Item) loop
-            if Item = First_Rep_Item (Typ) then
-               return;
-            end if;
+      --  3.2) Both source and destination types have at least one rep item.
+      --  The destination type DOES inherit part of the rep item chain of the
+      --  source type.
+      --     From_Typ ---> Item ---> Item ---> Item
+      --                              ^
+      --     Typ --------> Item ------+
 
-            Item := Next_Rep_Item (Item);
-         end loop;
-      end if;
+      --  This rare case arises when the full view of a private extension must
+      --  inherit the rep item chain from the full view of its parent type and
+      --  the full view of the parent type contains extra rep items. Currently
+      --  only invariants may lead to such form of inheritance.
+
+      --     type From_Typ is tagged private
+      --       with Type_Invariant'Class => Item_2;
+
+      --     type Typ is new From_Typ with private
+      --       with Type_Invariant => Item_4;
+
+      --  At this point the rep item chains contain the following items
+
+      --     From_Typ -----------> Item_2 ---> Item_3
+      --                            ^
+      --     Typ --------> Item_4 --+
+
+      --  The full views of both types may introduce extra invariants
+
+      --     type From_Typ is tagged null record
+      --       with Type_Invariant => Item_1;
+
+      --     type Typ is new From_Typ with null record;
 
-      --  When the destination type has a rep item chain, the chain of the
-      --  source type is appended to it.
+      --  The full view of Typ would have to inherit any new rep items added to
+      --  the full view of From_Typ.
 
-      if Present (Last_Item) then
-         Set_Next_Rep_Item (Last_Item, From_Item);
+      --     From_Typ -----------> Item_1 ---> Item_2 ---> Item_3
+      --                            ^
+      --     Typ --------> Item_4 --+
 
-      --  Otherwise the destination type directly inherits the rep item chain
-      --  of the source type (if any).
+      --  To achieve this form of inheritance, the destination type must first
+      --  sever the link between its own rep chain and that of the source type,
+      --  then inheritance 3.1 takes place.
+
+      --  Case 1: The source type lacks a rep item chain
+
+      if No (First_Rep_Item (From_Typ)) then
+         return;
+
+      --  Case 2: The destination type lacks a rep item chain
+
+      elsif No (First_Rep_Item (Typ)) then
+         Set_First_Rep_Item (Typ, First_Rep_Item (From_Typ));
+
+      --  Case 3: Both the source and destination types have at least one rep
+      --  item. Traverse the rep item chain of the destination type to find the
+      --  last rep item.
 
       else
-         Set_First_Rep_Item (Typ, From_Item);
+         Item      := Empty;
+         Next_Item := First_Rep_Item (Typ);
+         while Present (Next_Item) loop
+
+            --  Detect a link between the destination type's rep chain and that
+            --  of the source type. There are two possibilities:
+
+            --    Variant 1
+            --                  Next_Item
+            --                      V
+            --       From_Typ ---> Item_1 --->
+            --                      ^
+            --       Typ -----------+
+            --
+            --       Item is Empty
+
+            --    Variant 2
+            --                              Next_Item
+            --                                  V
+            --       From_Typ ---> Item_1 ---> Item_2 --->
+            --                                  ^
+            --       Typ --------> Item_3 ------+
+            --                      ^
+            --                     Item
+
+            if Has_Rep_Item (From_Typ, Next_Item) then
+               exit;
+            end if;
+
+            Item      := Next_Item;
+            Next_Item := Next_Rep_Item (Next_Item);
+         end loop;
+
+         --  Inherit the source type's rep item chain
+
+         if Present (Item) then
+            Set_Next_Rep_Item (Item, First_Rep_Item (From_Typ));
+         else
+            Set_First_Rep_Item (Typ, First_Rep_Item (From_Typ));
+         end if;
       end if;
    end Inherit_Rep_Item_Chain;