From: Eric Botcazou <ebotca...@adacore.com>

The support of the Default_Component_Value aspect on derived constrained
array types is broken because of a couple of issues: 1) the derived types
incorrectly inherit the initialization procedure of the ancestor types
and 2) the propagation of the aspect does not work for constrained array
types (unlike for unconstrained array types).

gcc/ada/

        * exp_tss.adb (Base_Init_Proc): Do not return the Init_Proc of the
        ancestor type for a derived array type.
        * sem_ch13.adb (Inherit_Aspects_At_Freeze_Point): Factor out the
        common processing done on representation items.
        For Default_Component_Value and Default_Value, look into the first
        subtype to find out the representation items.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/exp_tss.adb  |   5 +-
 gcc/ada/sem_ch13.adb | 205 +++++++++++++++++++++++++++----------------
 2 files changed, 133 insertions(+), 77 deletions(-)

diff --git a/gcc/ada/exp_tss.adb b/gcc/ada/exp_tss.adb
index 09bb133a41f..23ee3496b23 100644
--- a/gcc/ada/exp_tss.adb
+++ b/gcc/ada/exp_tss.adb
@@ -78,8 +78,11 @@ package body Exp_Tss is
       else
          Proc := Init_Proc (Base_Type (Full_Type), Ref);
 
+         --  For derived record types, if the base type does not have one,
+         --  we use the Init_Proc of the ancestor type.
+
          if No (Proc)
-           and then Is_Composite_Type (Full_Type)
+           and then Is_Record_Type (Full_Type)
            and then Is_Derived_Type (Full_Type)
          then
             return Init_Proc (Root_Type (Full_Type), Ref);
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index 618f935e4fe..e5f0ebcd6a2 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -13493,12 +13493,68 @@ package body Sem_Ch13 is
    -------------------------------------
 
    procedure Inherit_Aspects_At_Freeze_Point (Typ : Entity_Id) is
+      function Get_Inherited_Rep_Item
+        (E   : Entity_Id;
+         Nam : Name_Id) return Node_Id;
+      --  Search the Rep_Item chain of entity E for an instance of a rep item
+      --  (pragma, attribute definition clause, or aspect specification) whose
+      --  name matches the given name Nam, and that has been inherited from its
+      --  parent, i.e. that has not been directly specified for E . If one is
+      --  found, it is returned, otherwise Empty is returned.
+
+      function Get_Inherited_Rep_Item
+        (E    : Entity_Id;
+         Nam1 : Name_Id;
+         Nam2 : Name_Id) return Node_Id;
+      --  Search the Rep_Item chain of entity E for an instance of a rep item
+      --  (pragma, attribute definition clause, or aspect specification) whose
+      --  name matches one of the given names Nam1 or Nam2, and that has been
+      --  inherited from its parent, i.e. that has not been directly specified
+      --  for E . If one is found, it is returned, otherwise Empty is returned.
+
       function Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item
         (Rep_Item : Node_Id) return Boolean;
       --  This routine checks if Rep_Item is either a pragma or an aspect
       --  specification node whose corresponding pragma (if any) is present in
       --  the Rep Item chain of the entity it has been specified to.
 
+      ----------------------------
+      -- Get_Inherited_Rep_Item --
+      ----------------------------
+
+      function Get_Inherited_Rep_Item
+        (E   : Entity_Id;
+         Nam : Name_Id) return Node_Id
+      is
+         Rep : constant Node_Id
+                 := Get_Rep_Item (E, Nam, Check_Parents => True);
+      begin
+         if Present (Rep)
+           and then not Has_Rep_Item (E, Nam, Check_Parents => False)
+         then
+            return Rep;
+         else
+            return Empty;
+         end if;
+      end Get_Inherited_Rep_Item;
+
+      function Get_Inherited_Rep_Item
+        (E    : Entity_Id;
+         Nam1 : Name_Id;
+         Nam2 : Name_Id) return Node_Id
+      is
+         Rep : constant Node_Id
+                 := Get_Rep_Item (E, Nam1, Nam2, Check_Parents => True);
+      begin
+         if Present (Rep)
+           and then not Has_Rep_Item (E, Nam1, Nam2, Check_Parents => False)
+         then
+            return Rep;
+         else
+            return Empty;
+         end if;
+      end Get_Inherited_Rep_Item;
+
       --------------------------------------------------
       -- Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item --
       --------------------------------------------------
@@ -13513,6 +13569,8 @@ package body Sem_Ch13 is
            Present_In_Rep_Item (Entity (Rep_Item), Aspect_Rep_Item (Rep_Item));
       end Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item;
 
+      Rep : Node_Id;
+
    --  Start of processing for Inherit_Aspects_At_Freeze_Point
 
    begin
@@ -13543,40 +13601,36 @@ package body Sem_Ch13 is
 
       --  Ada_05/Ada_2005
 
-      if not Has_Rep_Item (Typ, Name_Ada_05, Name_Ada_2005, False)
-        and then Has_Rep_Item (Typ, Name_Ada_05, Name_Ada_2005)
-        and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item
-                   (Get_Rep_Item (Typ, Name_Ada_05, Name_Ada_2005))
+      Rep := Get_Inherited_Rep_Item (Typ, Name_Ada_05, Name_Ada_2005);
+      if Present (Rep)
+        and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item (Rep)
       then
          Set_Is_Ada_2005_Only (Typ);
       end if;
 
       --  Ada_12/Ada_2012
 
-      if not Has_Rep_Item (Typ, Name_Ada_12, Name_Ada_2012, False)
-        and then Has_Rep_Item (Typ, Name_Ada_12, Name_Ada_2012)
-        and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item
-                   (Get_Rep_Item (Typ, Name_Ada_12, Name_Ada_2012))
+      Rep := Get_Inherited_Rep_Item (Typ, Name_Ada_12, Name_Ada_2012);
+      if Present (Rep)
+        and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item (Rep)
       then
          Set_Is_Ada_2012_Only (Typ);
       end if;
 
       --  Ada_2022
 
-      if not Has_Rep_Item (Typ, Name_Ada_2022, False)
-        and then Has_Rep_Item (Typ, Name_Ada_2022)
-        and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item
-                   (Get_Rep_Item (Typ, Name_Ada_2022))
+      Rep := Get_Inherited_Rep_Item (Typ, Name_Ada_2022);
+      if Present (Rep)
+        and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item (Rep)
       then
          Set_Is_Ada_2022_Only (Typ);
       end if;
 
       --  Atomic/Shared
 
-      if not Has_Rep_Item (Typ, Name_Atomic, Name_Shared, False)
-        and then Has_Rep_Pragma (Typ, Name_Atomic, Name_Shared)
-        and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item
-                   (Get_Rep_Item (Typ, Name_Atomic, Name_Shared))
+      Rep := Get_Inherited_Rep_Item (Typ,  Name_Atomic, Name_Shared);
+      if Present (Rep)
+        and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item (Rep)
       then
          Set_Is_Atomic (Typ);
          Set_Is_Volatile (Typ);
@@ -13591,74 +13645,80 @@ package body Sem_Ch13 is
          Set_Convention (Typ, Convention (Base_Type (Typ)));
       end if;
 
-      --  Default_Component_Value
+      --  Default_Component_Value (for base types only)
 
-      --  Verify that there is no rep_item declared for the type, and there
-      --  is one coming from an ancestor.
+      --  Note that we need to look into the first subtype because the base
+      --  type may be the implicit base type built by the compiler for the
+      --  declaration of a constrained subtype with the aspect.
 
-      if Is_Array_Type (Typ)
-        and then Is_Base_Type (Typ)
-        and then not Has_Rep_Item (Typ, Name_Default_Component_Value, False)
-        and then Has_Rep_Item (Typ, Name_Default_Component_Value)
-      then
+      if Is_Array_Type (Typ) and then Is_Base_Type (Typ) then
          declare
+            F_Typ : constant Entity_Id := First_Subtype (Typ);
+
             E : Entity_Id;
 
          begin
-            E := Entity (Get_Rep_Item (Typ, Name_Default_Component_Value));
+            Rep :=
+              Get_Inherited_Rep_Item (F_Typ, Name_Default_Component_Value);
+            if Present (Rep) then
+               E := Entity (Rep);
 
-            --  Deal with private types
+               --  Deal with private types
 
-            if Is_Private_Type (E) then
-               E := Full_View (E);
-            end if;
+               if Is_Private_Type (E) then
+                  E := Full_View (E);
+               end if;
 
-            Set_Default_Aspect_Component_Value (Typ,
-              Default_Aspect_Component_Value (E));
+               Set_Default_Aspect_Component_Value
+                 (Typ, Default_Aspect_Component_Value (E));
+               Set_Has_Default_Aspect (Typ);
+            end if;
          end;
       end if;
 
-      --  Default_Value
+      --  Default_Value (for base types only)
 
-      if Is_Scalar_Type (Typ)
-        and then Is_Base_Type (Typ)
-        and then not Has_Rep_Item (Typ, Name_Default_Value, False)
-        and then Has_Rep_Item (Typ, Name_Default_Value)
-      then
-         Set_Has_Default_Aspect (Typ);
+      --  Note that we need to look into the first subtype because the base
+      --  type may be the implicit base type built by the compiler for the
+      --  declaration of a constrained subtype with the aspect.
 
+      if Is_Scalar_Type (Typ) and then Is_Base_Type (Typ) then
          declare
+            F_Typ : constant Entity_Id := First_Subtype (Typ);
+
             E : Entity_Id;
 
          begin
-            E := Entity (Get_Rep_Item (Typ, Name_Default_Value));
+            Rep := Get_Inherited_Rep_Item (F_Typ, Name_Default_Value);
+            if Present (Rep) then
+               E := Entity (Rep);
 
-            --  Deal with private types
+               --  Deal with private types
 
-            if Is_Private_Type (E) then
-               E := Full_View (E);
-            end if;
+               if Is_Private_Type (E) then
+                  E := Full_View (E);
+               end if;
 
-            Set_Default_Aspect_Value (Typ, Default_Aspect_Value (E));
+               Set_Default_Aspect_Value (Typ, Default_Aspect_Value (E));
+               Set_Has_Default_Aspect (Typ);
+            end if;
          end;
       end if;
 
       --  Discard_Names
 
-      if not Has_Rep_Item (Typ, Name_Discard_Names, False)
-        and then Has_Rep_Item (Typ, Name_Discard_Names)
-        and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item
-                   (Get_Rep_Item (Typ, Name_Discard_Names))
+      Rep := Get_Inherited_Rep_Item (Typ, Name_Discard_Names);
+      if Present (Rep)
+        and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item (Rep)
       then
          Set_Discard_Names (Typ);
       end if;
 
       --  Volatile
 
-      if not Has_Rep_Item (Typ, Name_Volatile, False)
-        and then Has_Rep_Item (Typ, Name_Volatile)
-        and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item
-                   (Get_Rep_Item (Typ, Name_Volatile))
+      Rep := Get_Inherited_Rep_Item (Typ, Name_Volatile);
+      if Present (Rep)
+        and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item (Rep)
       then
          Set_Is_Volatile (Typ);
          Set_Treat_As_Volatile (Typ);
@@ -13666,12 +13726,10 @@ package body Sem_Ch13 is
 
       --  Volatile_Full_Access and Full_Access_Only
 
-      if not Has_Rep_Item (Typ, Name_Volatile_Full_Access, False)
-        and then not Has_Rep_Item (Typ, Name_Full_Access_Only, False)
-        and then (Has_Rep_Item (Typ, Name_Volatile_Full_Access)
-                    or else Has_Rep_Item (Typ, Name_Full_Access_Only))
-        and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item
-                   (Get_Rep_Item (Typ, Name_Volatile_Full_Access))
+      Rep := Get_Inherited_Rep_Item
+               (Typ, Name_Volatile_Full_Access, Name_Full_Access_Only);
+      if Present (Rep)
+        and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item (Rep)
       then
          Set_Is_Volatile_Full_Access (Typ);
          Set_Is_Volatile (Typ);
@@ -13688,38 +13746,34 @@ package body Sem_Ch13 is
          begin
             --  Atomic_Components
 
-            if not Has_Rep_Item (Typ, Name_Atomic_Components, False)
-              and then Has_Rep_Item (Typ, Name_Atomic_Components)
-              and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item
-                   (Get_Rep_Item (Typ, Name_Atomic_Components))
+            Rep := Get_Inherited_Rep_Item (Typ, Name_Atomic_Components);
+            if Present (Rep)
+              and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item (Rep)
             then
                Set_Has_Atomic_Components (Imp_Bas_Typ);
             end if;
 
             --  Volatile_Components
 
-            if not Has_Rep_Item (Typ, Name_Volatile_Components, False)
-              and then Has_Rep_Item (Typ, Name_Volatile_Components)
-              and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item
-                   (Get_Rep_Item (Typ, Name_Volatile_Components))
+            Rep := Get_Inherited_Rep_Item (Typ, Name_Volatile_Components);
+            if Present (Rep)
+              and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item (Rep)
             then
                Set_Has_Volatile_Components (Imp_Bas_Typ);
             end if;
 
             --  Finalize_Storage_Only
 
-            if not Has_Rep_Pragma (Typ, Name_Finalize_Storage_Only, False)
-              and then Has_Rep_Pragma (Typ, Name_Finalize_Storage_Only)
-            then
+            Rep := Get_Inherited_Rep_Item (Typ, Name_Finalize_Storage_Only);
+            if Present (Rep) then
                Set_Finalize_Storage_Only (Bas_Typ);
             end if;
 
             --  Universal_Aliasing
 
-            if not Has_Rep_Item (Typ, Name_Universal_Aliasing, False)
-              and then Has_Rep_Item (Typ, Name_Universal_Aliasing)
-              and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item
-                   (Get_Rep_Item (Typ, Name_Universal_Aliasing))
+            Rep := Get_Inherited_Rep_Item (Typ, Name_Universal_Aliasing);
+            if Present (Rep)
+              and then Is_Pragma_Or_Corr_Pragma_Present_In_Rep_Item (Rep)
             then
                Set_Universal_Aliasing (Imp_Bas_Typ);
             end if;
@@ -13727,9 +13781,8 @@ package body Sem_Ch13 is
             --  Bit_Order
 
             if Is_Record_Type (Typ) and then Typ = Bas_Typ then
-               if not Has_Rep_Item (Typ, Name_Bit_Order, False)
-                 and then Has_Rep_Item (Typ, Name_Bit_Order)
-               then
+               Rep := Get_Inherited_Rep_Item (Typ, Name_Bit_Order);
+               if Present (Rep) then
                   Set_Reverse_Bit_Order (Bas_Typ,
                     Reverse_Bit_Order
                       (Implementation_Base_Type (Etype (Bas_Typ))));
-- 
2.34.1

Reply via email to