aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada
diff options
context:
space:
mode:
authorJustin Squirek <squirek@adacore.com>2024-05-09 05:04:03 +0000
committerMarc Poulhiès <poulhies@adacore.com>2024-06-14 09:34:19 +0200
commit262a5ffc41471aa4909f23279278dd37724da744 (patch)
treec92e3b98bf066e302e7b26c45398e0136d255889 /gcc/ada
parent1feb6d81a3ab587382817cd7a39222b6c83f68ac (diff)
downloadgcc-262a5ffc41471aa4909f23279278dd37724da744.zip
gcc-262a5ffc41471aa4909f23279278dd37724da744.tar.gz
gcc-262a5ffc41471aa4909f23279278dd37724da744.tar.bz2
ada: Add prototype for mutably tagged types
This patch implements mutably tagged types via the new Size'Class aspect. gcc/ada/ * doc/gnat_rm/gnat_language_extensions.rst: Add documentation for mutably tagged type feature. * aspects.ads: Add registration for 'Size'Class. * einfo.ads: Add documentation for new components Class_Wide_Equivalent_Type and Is_Mutably_Tagged_Type. * exp_aggr.adb (Gen_Assign): Assume associated mutably tagged type when class-wide equivalent type is encountered. (Contains_Mutably_Tagged_Type): New subprogram. (Convert_To_Positional): Assume associated mutably tagged type when class-wide equivalent type is encountered. (Is_Static_Element): Assume associated mutably tagged type when class-wide equivalent type is encountered. (Expand_Array_Aggregate): Assume associated mutably tagged type when class-wide equivalent type is encountered. (Expand_Record_Aggregate): Force mutably tagged records to be expanded into assignments. * exp_ch3.adb (Build_Array_Init_Proc): Assume associated mutably tagged type when class-wide equivalent type is encountered. (Simple_Initialization_OK): Disallow simple initialization for class-wide equivalent types. (Build_Init_Statements): Assume associated mutably tagged type when class-wide equivalent type is encountered. (Expand_Freeze_Array_Type): Ignore building of record init procs for mutably tagged types. (Expand_N_Full_Type_Declaration): Replace mutably tagged type declarations with their associated class-wide equivalent types. (Default_Initialize_Object): Add special handling for mutably tagged types. * exp_ch4.adb (Expand_N_Allocator): Add initialization for mutably tagged types. (Expand_Record_Equality): Generate mutably tagged unchecked conversions. * exp_ch5.adb (Expand_N_Assignment_Statement): Generate a special assignment case for class-wide equivalent types which does tag assignments and ignores certain checks. * exp_ch6.adb (Expand_Call_Helper): Propagate constrained extra formal actuals for mutably tagged types. * exp_ch7.adb (Make_Init_Call): Handle mutably tagged type initialization. * exp_util.adb (Make_CW_Equivalent_Type): Modify to handle mutably tagged objects which contain no initialization expression. (Make_Subtype_From_Expr): Modify call to Make_CW_Equivalent_Type. * exp_util.ads (Make_CW_Equivalent_Type): Move declaration from body to spec. * freeze.adb (Size_Known): No longer return false automatically when a class-wide type is encountered. (Freeze_Entity): Ignore error messages about size not being known for mutably tagged types. * gen_il-fields.ads: Register new fields Class_Wide_Equivalent_Type and Is_Mutably_Tagged_Type. * gen_il-gen-gen_entities.adb: Register new fields Class_Wide_Equivalent_Type and Is_Mutably_Tagged_Type for type entities. * mutably_tagged.adb, mutably_tagged.ads (Corresponding_Mutably_Tagged_Type): New subprogram. (Depends_On_Mutably_Tagged_Ext_Comp): New subprogram. (Get_Corresponding_Mutably_Tagged_Type_If_Present): New subprogram. (Get_Corresponding_Tagged_Type_If_Present): New subprogram. (Is_Mutably_Tagged_Conversion): New subprogram. (Is_Mutably_Tagged_CW_Equivalent_Type): New subprogram. (Make_Mutably_Tagged_Conversion): New subprogram. (Make_CW_Size_Compile_Check): New subprogram. (Make_Mutably_Tagged_CW_Check): New subprogram. * sem_aggr.adb (Resolve_Array_Aggregate): Skip tag checks for class-wide equivalent types. (Resolve_Aggr_Expr): Assume associated mutably tagged type when class-wide equivalent type is encountered. * sem_attr.adb (Analyze_Attribute): Allow 'Tag on mutably tagged types. (Resolve_Attribute): Detect errors for dependence of mutably tagged extension type component. * sem_ch12.adb (Instantiate_Object): Detect errors for dependence of mutably tagged extension type component. * sem_ch13.adb (Analyze_One_Aspect): Propagate 'Size'Class to class-wide type. (Analyze_Attribute_Definition_Clause): Add handling of 'Size'Class by generating class-wide equivalent types and checking for illegal uses. * sem_ch2.adb (Analyze_Identifier): Generate unchecked conversion for class-wide equivalent types. * sem_ch3.adb (Analyze_Component_Declaration): Avoid unconstrained errors on mutably tagged types. (Analyze_Object_Declaration): Rewrite declarations of mutably tagged types to use class-wide equivalent types. (Array_Type_Declaration): Modify arrays of mutably tagged types to use their corresponding class-wide equivalent types. (Derived_Type_Declaration): Add various checks for mutably tagged derived types. * sem_ch4.adb (Analyze_Allocator): Replace reference to mutably tagged type with cooresponding tagged type. (Process_Indexed_Component): Generate unchecked conversion for class-wide equivalent type. (Analyze_One_Call): Generate unchecked conversion for class-wide equivalent types. (Analyze_Selected_Component): Assume reference to class-wide equivalent type is associated mutably tagged type. (Analyze_Type_Conversion): Generate unchecked conversion for class-wide equivalent type. * sem_ch5.adb (Analyze_Assignment): Assume associated mutably tagged type when class-wide equivalent type is encountered. (Analyze_Iterator_Specification): Detect errors for dependence of mutably tagged extension type component. * sem_ch6.adb (Create_Extra_Formals): Add code to generate extra formal for mutably tagged types to signal if they are constrained. * sem_ch8.adb (Analyze_Object_Renaming): Detect error on renaming of mutably tagged extension type component. (Analyze_Renaming_Primitive_Operation): Detect error on renaming of mutably tagged extension type component. * sem_res.adb (Resolve_Actuals): Allow class-wide arguments on class-wide equivalent types. (Valid_Conversion): Assume associated mutably tagged type when class-wide equivalent type is encountered. * sem_util.adb (Is_Fully_Initialized_Type): Flag mutably tagged types as fully initialized. (Needs_Simple_Initalization): Flag class-wide equivalent types as needing initialization. * gnat_rm.texi: Regenerate. * gcc-interface/Make-lang.in: Add entry for mutably_tagged.o.
Diffstat (limited to 'gcc/ada')
-rw-r--r--gcc/ada/aspects.ads1
-rw-r--r--gcc/ada/doc/gnat_rm/gnat_language_extensions.rst38
-rw-r--r--gcc/ada/einfo.ads8
-rw-r--r--gcc/ada/exp_aggr.adb66
-rw-r--r--gcc/ada/exp_ch3.adb64
-rw-r--r--gcc/ada/exp_ch4.adb51
-rw-r--r--gcc/ada/exp_ch5.adb80
-rw-r--r--gcc/ada/exp_ch6.adb6
-rw-r--r--gcc/ada/exp_ch7.adb3
-rw-r--r--gcc/ada/exp_util.adb64
-rw-r--r--gcc/ada/exp_util.ads20
-rw-r--r--gcc/ada/freeze.adb8
-rw-r--r--gcc/ada/gcc-interface/Make-lang.in1
-rw-r--r--gcc/ada/gen_il-fields.ads2
-rw-r--r--gcc/ada/gen_il-gen-gen_entities.adb2
-rw-r--r--gcc/ada/gnat_rm.texi106
-rw-r--r--gcc/ada/mutably_tagged.adb337
-rw-r--r--gcc/ada/mutably_tagged.ads120
-rw-r--r--gcc/ada/sem_aggr.adb24
-rw-r--r--gcc/ada/sem_attr.adb10
-rw-r--r--gcc/ada/sem_ch12.adb5
-rw-r--r--gcc/ada/sem_ch13.adb74
-rw-r--r--gcc/ada/sem_ch2.adb7
-rw-r--r--gcc/ada/sem_ch3.adb122
-rw-r--r--gcc/ada/sem_ch4.adb61
-rw-r--r--gcc/ada/sem_ch5.adb36
-rw-r--r--gcc/ada/sem_ch6.adb10
-rw-r--r--gcc/ada/sem_ch8.adb9
-rw-r--r--gcc/ada/sem_res.adb17
-rw-r--r--gcc/ada/sem_util.adb13
30 files changed, 1235 insertions, 130 deletions
diff --git a/gcc/ada/aspects.ads b/gcc/ada/aspects.ads
index 1acbec8..d4aafb1 100644
--- a/gcc/ada/aspects.ads
+++ b/gcc/ada/aspects.ads
@@ -260,6 +260,7 @@ package Aspects is
Aspect_Post => True,
Aspect_Read => True,
Aspect_Write => True,
+ Aspect_Size => True,
Aspect_Stable_Properties => True,
Aspect_Type_Invariant => True,
others => False);
diff --git a/gcc/ada/doc/gnat_rm/gnat_language_extensions.rst b/gcc/ada/doc/gnat_rm/gnat_language_extensions.rst
index c703e1c..cf1ad60 100644
--- a/gcc/ada/doc/gnat_rm/gnat_language_extensions.rst
+++ b/gcc/ada/doc/gnat_rm/gnat_language_extensions.rst
@@ -496,3 +496,41 @@ case statement with composite selector type".
Link to the original RFC:
https://github.com/AdaCore/ada-spark-rfcs/blob/master/prototyped/rfc-pattern-matching.rst
+
+Mutably Tagged Types with Size'Class Aspect
+-------------------------------------------
+
+The `Size'Class` aspect can be applied to a tagged type to specify a size
+constraint for the type and its descendants. When this aspect is specified
+on a tagged type, the class-wide type of that type is considered to be a
+"mutably tagged" type - meaning that objects of the class-wide type can have
+their tag changed by assignment from objects with a different tag.
+
+When the aspect is applied to a type, the size of each of its descendant types
+must not exceed the size specified for the aspect.
+
+Example:
+
+.. code-block:: ada
+
+ type Base is tagged null record
+ with Size'Class => 16 * 8; -- Size in bits (128 bits, or 16 bytes)
+
+ type Derived_Type is new Base with record
+ Data_Field : Integer;
+ end record; -- ERROR if Derived_Type exceeds 16 bytes
+
+Class-wide types with a specified `Size'Class` can be used as the type of
+array components, record components, and stand-alone objects.
+
+.. code-block:: ada
+
+ Inst : Base'Class;
+ type Array_of_Base is array (Positive range <>) of Base'Class;
+
+Note: Legality of the `Size'Class` aspect is subject to certain restrictions on
+the tagged type, such as being undiscriminated, having no dynamic composite
+subcomponents, among others detailed in the RFC.
+
+Link to the original RFC:
+https://github.com/AdaCore/ada-spark-rfcs/blob/topic/rfc-finally/considered/rfc-class-size.md
diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads
index 0b0529a..8ee419b 100644
--- a/gcc/ada/einfo.ads
+++ b/gcc/ada/einfo.ads
@@ -633,6 +633,10 @@ package Einfo is
-- the corresponding implicitly declared class-wide type. For a
-- class-wide type, returns itself. Set to Empty for untagged types.
+-- Class_Wide_Equivalent_Type
+-- Defined in all type entities. Used to store an internally generated
+-- class-wide equivalent type for an associated mutably tagged type.
+
-- Cloned_Subtype
-- Defined in E_Record_Subtype and E_Class_Wide_Subtype entities.
-- Each such entity can either have a Discriminant_Constraint, in
@@ -2980,6 +2984,10 @@ package Einfo is
-- Is_Modular_Integer_Type (synthesized)
-- Applies to all entities. True if entity is a modular integer type
+-- Is_Mutably_Tagged_Type
+-- Defined in all type entities. Used to signify that a given type is a
+-- "mutably tagged" class-wide type where 'Size'Class has been specified.
+
-- Is_Non_Static_Subtype
-- Defined in all type and subtype entities. It is set in some (but not
-- all) cases in which a subtype is known to be non-static. Before this
diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
index 2686f5b..d564fd4 100644
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -43,6 +43,7 @@ with Exp_Tss; use Exp_Tss;
with Freeze; use Freeze;
with Itypes; use Itypes;
with Lib; use Lib;
+with Mutably_Tagged; use Mutably_Tagged;
with Namet; use Namet;
with Nmake; use Nmake;
with Nlists; use Nlists;
@@ -1370,8 +1371,8 @@ package body Exp_Aggr is
Expr_Q := Unqualify (Expr);
if Present (Etype (N)) and then Etype (N) /= Any_Composite then
- Comp_Typ := Component_Type (Etype (N));
- pragma Assert (Comp_Typ = Ctype); -- AI-287
+ Comp_Typ := Get_Corresponding_Mutably_Tagged_Type_If_Present
+ (Component_Type (Etype (N)));
elsif Present (Next (First (New_Indexes))) then
@@ -4474,7 +4475,8 @@ package body Exp_Aggr is
Dims : constant Nat := Number_Dimensions (Typ);
Max_Others_Replicate : constant Nat := Max_Aggregate_Size (N);
- Static_Components : Boolean := True;
+ Ctyp : Entity_Id := Component_Type (Typ);
+ Static_Components : Boolean := True;
procedure Check_Static_Components;
-- Check whether all components of the aggregate are compile-time known
@@ -4908,9 +4910,9 @@ package body Exp_Aggr is
end if;
end Is_Flat;
- -------------------------
- -- Is_Static_Element --
- -------------------------
+ -----------------------
+ -- Is_Static_Element --
+ -----------------------
function Is_Static_Element (N : Node_Id; Dims : Nat) return Boolean is
Expr : constant Node_Id := Expression (N);
@@ -4935,7 +4937,7 @@ package body Exp_Aggr is
-- but only at the innermost level for a multidimensional array.
elsif Dims = 1 then
- Preanalyze_And_Resolve (Expr, Component_Type (Typ));
+ Preanalyze_And_Resolve (Expr, Ctyp);
return Compile_Time_Known_Value (Expr);
else
@@ -4986,6 +4988,10 @@ package body Exp_Aggr is
return;
end if;
+ -- Special handling for mutably taggeds
+
+ Ctyp := Get_Corresponding_Mutably_Tagged_Type_If_Present (Ctyp);
+
Check_Static_Components;
-- If the size is known, or all the components are static, try to
@@ -5076,9 +5082,10 @@ package body Exp_Aggr is
procedure Expand_Array_Aggregate (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N);
- Typ : constant Entity_Id := Etype (N);
- Ctyp : constant Entity_Id := Component_Type (Typ);
+ Typ : constant Entity_Id := Etype (N);
-- Typ is the correct constrained array subtype of the aggregate
+
+ Ctyp : Entity_Id := Component_Type (Typ);
-- Ctyp is the corresponding component type.
Aggr_Dimension : constant Pos := Number_Dimensions (Typ);
@@ -6027,6 +6034,10 @@ package body Exp_Aggr is
pragma Assert (not Raises_Constraint_Error (N));
+ -- Special handling for mutably taggeds
+
+ Ctyp := Get_Corresponding_Mutably_Tagged_Type_If_Present (Ctyp);
+
-- STEP 1a
-- Check that the index range defined by aggregate bounds is
@@ -7931,6 +7942,10 @@ package body Exp_Aggr is
-- NOTE: This sets the global Static_Components to False in most, but
-- not all, cases when it returns False.
+ function Contains_Mutably_Tagged_Component
+ (Typ : Entity_Id) return Boolean;
+ -- Determine if some component of Typ is mutably tagged
+
function Has_Per_Object_Constraint (L : List_Id) return Boolean;
-- Return True if any element of L has Has_Per_Object_Constraint set.
-- L should be the Choices component of an N_Component_Association.
@@ -8433,6 +8448,30 @@ package body Exp_Aggr is
return True;
end Component_OK_For_Backend;
+ ---------------------------------------
+ -- Contains_Mutably_Tagged_Component --
+ ---------------------------------------
+
+ function Contains_Mutably_Tagged_Component
+ (Typ : Entity_Id) return Boolean
+ is
+ Comp : Entity_Id;
+ begin
+ -- Move through Typ's components looking for mutably tagged ones
+
+ Comp := First_Component (Typ);
+ while Present (Comp) loop
+ -- When we find one, return True
+
+ if Is_Mutably_Tagged_CW_Equivalent_Type (Etype (Comp)) then
+ return True;
+ end if;
+
+ Next_Component (Comp);
+ end loop;
+ return False;
+ end Contains_Mutably_Tagged_Component;
+
-------------------------------
-- Has_Per_Object_Constraint --
-------------------------------
@@ -8515,7 +8554,8 @@ package body Exp_Aggr is
end if;
-- If the pragma Aggregate_Individually_Assign is set, always convert to
- -- assignments.
+ -- assignments so that proper tag assignments and conversions can be
+ -- generated.
if Aggregate_Individually_Assign then
Convert_To_Assignments (N, Typ);
@@ -8554,6 +8594,12 @@ package body Exp_Aggr is
Build_Back_End_Aggregate;
end if;
+ -- When we have any components which are mutably tagged types then
+ -- special processing is required.
+
+ elsif Contains_Mutably_Tagged_Component (Typ) then
+ Convert_To_Assignments (N, Typ);
+
-- Gigi doesn't properly handle temporaries of variable size so we
-- generate it in the front-end
diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb
index f03cda6..3d8b802 100644
--- a/gcc/ada/exp_ch3.adb
+++ b/gcc/ada/exp_ch3.adb
@@ -49,6 +49,7 @@ with Exp_Util; use Exp_Util;
with Freeze; use Freeze;
with Ghost; use Ghost;
with Lib; use Lib;
+with Mutably_Tagged; use Mutably_Tagged;
with Namet; use Namet;
with Nlists; use Nlists;
with Nmake; use Nmake;
@@ -631,8 +632,13 @@ package body Exp_Ch3 is
---------------------------
procedure Build_Array_Init_Proc (A_Type : Entity_Id; Nod : Node_Id) is
- Comp_Type : constant Entity_Id := Component_Type (A_Type);
- Comp_Simple_Init : constant Boolean :=
+ -- Obtain the corresponding mutably tagged type's parent subtype to
+ -- handle default initialization.
+
+ Comp_Type : constant Entity_Id :=
+ Get_Corresponding_Tagged_Type_If_Present (Component_Type (A_Type));
+
+ Comp_Simple_Init : constant Boolean :=
Needs_Simple_Initialization
(Typ => Comp_Type,
Consider_IS =>
@@ -1367,6 +1373,7 @@ package body Exp_Ch3 is
return
not (Present (Obj_Id) and then Is_Internal (Obj_Id))
+ and then not Is_Mutably_Tagged_CW_Equivalent_Type (Typ)
and then
Needs_Simple_Initialization
(Typ => Typ,
@@ -3709,7 +3716,11 @@ package body Exp_Ch3 is
(Subtype_Indication (Component_Definition (Decl)), Checks);
Id := Defining_Identifier (Decl);
- Typ := Etype (Id);
+
+ -- Obtain the corresponding mutably tagged type's parent subtype
+ -- to handle default initialization.
+
+ Typ := Get_Corresponding_Tagged_Type_If_Present (Etype (Id));
-- Leave any processing of component requiring late initialization
-- for the second pass.
@@ -4125,7 +4136,11 @@ package body Exp_Ch3 is
while Present (Decl) loop
Comp_Loc := Sloc (Decl);
Id := Defining_Identifier (Decl);
- Typ := Etype (Id);
+
+ -- Obtain the corresponding mutably tagged type's parent
+ -- subtype to handle default initialization.
+
+ Typ := Get_Corresponding_Tagged_Type_If_Present (Etype (Id));
if Initialization_Control.Requires_Late_Init (Decl, Rec_Type)
then
@@ -5407,7 +5422,12 @@ package body Exp_Ch3 is
procedure Expand_Freeze_Array_Type (N : Node_Id) is
Typ : constant Entity_Id := Entity (N);
Base : constant Entity_Id := Base_Type (Typ);
- Comp_Typ : constant Entity_Id := Component_Type (Typ);
+
+ -- Obtain the corresponding mutably tagged type if necessary
+
+ Comp_Typ : constant Entity_Id :=
+ Get_Corresponding_Mutably_Tagged_Type_If_Present
+ (Component_Type (Typ));
begin
if not Is_Bit_Packed_Array (Typ) then
@@ -6436,7 +6456,9 @@ package body Exp_Ch3 is
-- Do not need init for interfaces on virtual targets since they're
-- abstract.
- if Tagged_Type_Expansion or else not Is_Interface (Typ) then
+ if not Is_Mutably_Tagged_CW_Equivalent_Type (Typ)
+ and then (Tagged_Type_Expansion or else not Is_Interface (Typ))
+ then
Build_Record_Init_Proc (Typ_Decl, Typ);
end if;
@@ -6695,6 +6717,29 @@ package body Exp_Ch3 is
end;
end if;
+ -- Handle mutably tagged types by replacing their declarations with
+ -- their class-wide equivalent types.
+
+ declare
+ Comp : Entity_Id;
+ begin
+ if Is_Array_Type (Def_Id) then
+ Comp := First_Entity (Component_Type (Def_Id));
+ else
+ Comp := First_Entity (Def_Id);
+ end if;
+
+ while Present (Comp) loop
+ if Ekind (Etype (Comp)) /= E_Void
+ and then Is_Mutably_Tagged_Type (Etype (Comp))
+ then
+ Set_Etype
+ (Comp, Class_Wide_Equivalent_Type (Etype (Comp)));
+ end if;
+ Next_Entity (Comp);
+ end loop;
+ end;
+
Par_Id := Etype (B_Id);
-- The parent type is private then we need to inherit any TSS operations
@@ -7244,7 +7289,12 @@ package body Exp_Ch3 is
-- Or else build the fully-fledged initialization if need be
- Init_Stmts := Build_Default_Initialization (N, Typ, Def_Id);
+ if Is_Mutably_Tagged_Type (Typ) then
+ Init_Stmts :=
+ Build_Default_Initialization (N, Etype (Typ), Def_Id);
+ else
+ Init_Stmts := Build_Default_Initialization (N, Typ, Def_Id);
+ end if;
-- Insert the whole initialization sequence into the tree. If the
-- object has a delayed freeze, as will be the case when it has
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index bf90b46..7349dfc 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -47,6 +47,7 @@ with Exp_Util; use Exp_Util;
with Freeze; use Freeze;
with Inline; use Inline;
with Lib; use Lib;
+with Mutably_Tagged; use Mutably_Tagged;
with Namet; use Namet;
with Nlists; use Nlists;
with Nmake; use Nmake;
@@ -4888,10 +4889,17 @@ package body Exp_Ch4 is
Temp := Make_Temporary (Loc, 'P');
- Init_Stmts :=
- Build_Default_Initialization (N, Etyp, Temp,
- For_CW => Is_Class_Wide_Type (Dtyp),
- Target_Ref => Target_Ref);
+ if Is_Mutably_Tagged_Type (Dtyp) then
+ Init_Stmts :=
+ Build_Default_Initialization (N, Etype (Etyp), Temp,
+ For_CW => False,
+ Target_Ref => Target_Ref);
+ else
+ Init_Stmts :=
+ Build_Default_Initialization (N, Etyp, Temp,
+ For_CW => Is_Class_Wide_Type (Dtyp),
+ Target_Ref => Target_Ref);
+ end if;
if Present (Init_Stmts) then
-- We set the allocator as analyzed so that when we analyze
@@ -12743,6 +12751,9 @@ package body Exp_Ch4 is
New_Lhs : Node_Id;
New_Rhs : Node_Id;
Check : Node_Id;
+ Lhs_Sel : Node_Id;
+ Rhs_Sel : Node_Id;
+ C_Typ : Entity_Id := Etype (C);
begin
if First_Time then
@@ -12753,17 +12764,31 @@ package body Exp_Ch4 is
New_Rhs := New_Copy_Tree (Rhs);
end if;
+ Lhs_Sel :=
+ Make_Selected_Component (Loc,
+ Prefix => New_Lhs,
+ Selector_Name => New_Occurrence_Of (C, Loc));
+ Rhs_Sel :=
+ Make_Selected_Component (Loc,
+ Prefix => New_Rhs,
+ Selector_Name => New_Occurrence_Of (C, Loc));
+
+ -- Generate mutably tagged conversions in case we encounter a
+ -- special class-wide equivalent type.
+
+ if Is_Mutably_Tagged_CW_Equivalent_Type (Etype (C)) then
+ C_Typ := Corresponding_Mutably_Tagged_Type (Etype (C));
+ Make_Mutably_Tagged_Conversion (Lhs_Sel, C_Typ);
+ Make_Mutably_Tagged_Conversion (Rhs_Sel, C_Typ);
+ end if;
+
Check :=
Expand_Composite_Equality
- (Outer_Type => Typ, Nod => Nod, Comp_Type => Etype (C),
- Lhs =>
- Make_Selected_Component (Loc,
- Prefix => New_Lhs,
- Selector_Name => New_Occurrence_Of (C, Loc)),
- Rhs =>
- Make_Selected_Component (Loc,
- Prefix => New_Rhs,
- Selector_Name => New_Occurrence_Of (C, Loc)));
+ (Outer_Type => Typ,
+ Nod => Nod,
+ Comp_Type => C_Typ,
+ Lhs => Lhs_Sel,
+ Rhs => Rhs_Sel);
-- If some (sub)component is an unchecked_union, the whole
-- operation will raise program error.
diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb
index b97e3bb..35c2628 100644
--- a/gcc/ada/exp_ch5.adb
+++ b/gcc/ada/exp_ch5.adb
@@ -41,6 +41,7 @@ with Exp_Pakd; use Exp_Pakd;
with Exp_Tss; use Exp_Tss;
with Exp_Util; use Exp_Util;
with Inline; use Inline;
+with Mutably_Tagged; use Mutably_Tagged;
with Namet; use Namet;
with Nlists; use Nlists;
with Nmake; use Nmake;
@@ -2398,8 +2399,14 @@ package body Exp_Ch5 is
Lhs : constant Node_Id := Name (N);
Loc : constant Source_Ptr := Sloc (N);
Rhs : constant Node_Id := Expression (N);
- Typ : constant Entity_Id := Underlying_Type (Etype (Lhs));
- Exp : Node_Id;
+
+ -- Obtain the relevant corresponding mutably tagged type if necessary
+
+ Typ : constant Entity_Id :=
+ Get_Corresponding_Mutably_Tagged_Type_If_Present
+ (Underlying_Type (Etype (Lhs)));
+
+ Exp : Node_Id;
begin
-- Special case to check right away, if the Componentwise_Assignment
@@ -2776,7 +2783,9 @@ package body Exp_Ch5 is
Apply_Discriminant_Check (Rhs, Typ, Lhs);
end if;
- elsif Is_Array_Type (Typ) and then Is_Constrained (Typ) then
+ elsif Is_Array_Type (Typ) and then
+ (Is_Constrained (Typ) or else Is_Mutably_Tagged_Conversion (Lhs))
+ then
Rewrite (Rhs, OK_Convert_To (Base_Type (Typ), Rhs));
Rewrite (Lhs, OK_Convert_To (Base_Type (Typ), Lhs));
if not Suppress_Assignment_Checks (N) then
@@ -3072,13 +3081,64 @@ package body Exp_Ch5 is
Attribute_Name => Name_Address)));
end if;
- Append_To (L,
- Make_Raise_Constraint_Error (Loc,
- Condition =>
- Make_Op_Ne (Loc,
- Left_Opnd => Lhs_Tag,
- Right_Opnd => Rhs_Tag),
- Reason => CE_Tag_Check_Failed));
+ -- Handle assignment to a mutably tagged type
+
+ if Is_Mutably_Tagged_Conversion (Lhs)
+ or else Is_Mutably_Tagged_Type (Typ)
+ or else Is_Mutably_Tagged_Type (Etype (Lhs))
+ then
+ -- Create a tag check when we have the extra
+ -- constrained formal and it is true (meaning we
+ -- are not dealing with a mutably tagged object).
+
+ if Is_Entity_Name (Name (N))
+ and then Is_Formal (Entity (Name (N)))
+ and then Present
+ (Extra_Constrained (Entity (Name (N))))
+ then
+ Append_To (L,
+ Make_If_Statement (Loc,
+ Condition =>
+ New_Occurrence_Of
+ (Extra_Constrained
+ (Entity (Name (N))), Loc),
+ Then_Statements => New_List (
+ Make_Raise_Constraint_Error (Loc,
+ Condition =>
+ Make_Op_Ne (Loc,
+ Left_Opnd => Lhs_Tag,
+ Right_Opnd => Rhs_Tag),
+ Reason => CE_Tag_Check_Failed))));
+ end if;
+
+ -- Generate a tag assignment before the actual
+ -- assignment so we dispatch to the proper
+ -- assign version.
+
+ Append_To (L,
+ Make_Assignment_Statement (Loc,
+ Name =>
+ Make_Selected_Component (Loc,
+ Prefix => Duplicate_Subexpr (Lhs),
+ Selector_Name =>
+ Make_Identifier (Loc, Name_uTag)),
+ Expression =>
+ Make_Selected_Component (Loc,
+ Prefix => Duplicate_Subexpr (Rhs),
+ Selector_Name =>
+ Make_Identifier (Loc, Name_uTag))));
+
+ -- Otherwise generate a normal tag check
+
+ else
+ Append_To (L,
+ Make_Raise_Constraint_Error (Loc,
+ Condition =>
+ Make_Op_Ne (Loc,
+ Left_Opnd => Lhs_Tag,
+ Right_Opnd => Rhs_Tag),
+ Reason => CE_Tag_Check_Failed));
+ end if;
end;
end if;
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index 2e873c9..da19c03 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -4224,8 +4224,10 @@ package body Exp_Ch6 is
-- because the object has underlying discriminants with defaults.
if Present (Extra_Constrained (Formal)) then
- if Is_Private_Type (Etype (Prev))
- and then not Has_Discriminants (Base_Type (Etype (Prev)))
+ if Is_Mutably_Tagged_Type (Etype (Actual))
+ or else (Is_Private_Type (Etype (Prev))
+ and then not Has_Discriminants
+ (Base_Type (Etype (Prev))))
then
Add_Extra_Actual
(Expr => New_Occurrence_Of (Standard_False, Loc),
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index eacdd17..e3e9bac 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -8288,6 +8288,9 @@ package body Exp_Ch7 is
if Has_Controlled_Component (Utyp) then
Proc := TSS (Utyp, Deep_Name_Of (Initialize_Case));
+ elsif Is_Mutably_Tagged_Type (Utyp) then
+ Proc := Find_Prim_Op (Etype (Utyp), Name_Of (Initialize_Case));
+ Check_Visibly_Controlled (Initialize_Case, Etype (Typ), Proc, Ref);
else
Proc := Find_Prim_Op (Utyp, Name_Of (Initialize_Case));
Check_Visibly_Controlled (Initialize_Case, Typ, Proc, Ref);
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index 58ab557..528001e 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -181,22 +181,6 @@ package body Exp_Util is
-- Determine whether pragma Default_Initial_Condition denoted by Prag has
-- an assertion expression that should be verified at run time.
- function Make_CW_Equivalent_Type
- (T : Entity_Id;
- E : Node_Id) return Entity_Id;
- -- T is a class-wide type entity, E is the initial expression node that
- -- constrains T in case such as: " X: T := E" or "new T'(E)". This function
- -- returns the entity of the Equivalent type and inserts on the fly the
- -- necessary declaration such as:
- --
- -- type anon is record
- -- _parent : Root_Type (T); constrained with E discriminants (if any)
- -- Extension : String (1 .. expr to match size of E);
- -- end record;
- --
- -- This record is compatible with any object of the class of T thanks to
- -- the first field and has the same size as E thanks to the second.
-
function Make_Literal_Range
(Loc : Source_Ptr;
Literal_Typ : Entity_Id) return Node_Id;
@@ -10160,13 +10144,13 @@ package body Exp_Util is
-- representation of the extension part.)
function Make_CW_Equivalent_Type
- (T : Entity_Id;
- E : Node_Id) return Entity_Id
+ (T : Entity_Id;
+ E : Node_Id;
+ List_Def : out List_Id) return Entity_Id
is
Loc : constant Source_Ptr := Sloc (E);
Root_Typ : constant Entity_Id := Root_Type (T);
Root_Utyp : constant Entity_Id := Underlying_Type (Root_Typ);
- List_Def : constant List_Id := Empty_List;
Comp_List : constant List_Id := New_List;
Equiv_Type : Entity_Id;
@@ -10177,6 +10161,8 @@ package body Exp_Util is
Size_Expr : Node_Id;
begin
+ List_Def := New_List;
+
-- If the root type is already constrained, there are no discriminants
-- in the expression.
@@ -10214,7 +10200,10 @@ package body Exp_Util is
-- need to convert it first to the class-wide type to force a call to
-- the _Size primitive operation.
- if Has_Tag_Of_Type (E) then
+ if No (E) then
+ Size_Attr := Make_Integer_Literal (Loc, RM_Size (T));
+
+ elsif Has_Tag_Of_Type (E) then
if not Has_Discriminants (Etype (E))
or else Is_Constrained (Etype (E))
then
@@ -10237,7 +10226,7 @@ package body Exp_Util is
Attribute_Name => Name_Size);
end if;
- if not Is_Interface (Root_Typ) then
+ if not Is_Interface (Root_Typ) and then Present (E) then
-- subtype rg__xx is
-- Storage_Offset range 1 .. (Exp'size - Typ'object_size)
@@ -10317,11 +10306,15 @@ package body Exp_Util is
Set_Is_Class_Wide_Equivalent_Type (Equiv_Type);
- -- A class-wide equivalent type does not require initialization
+ -- A class-wide equivalent type does not require initialization unless
+ -- no expression is present - in which case initialization gets
+ -- generated as part of the mutably tagged type machinery.
- Set_Suppress_Initialization (Equiv_Type);
+ if Present (E) then
+ Set_Suppress_Initialization (Equiv_Type);
+ end if;
- if not Is_Interface (Root_Typ) then
+ if not Is_Interface (Root_Typ) and Present (E) then
Append_To (Comp_List,
Make_Component_Declaration (Loc,
Defining_Identifier =>
@@ -10346,6 +10339,8 @@ package body Exp_Util is
Aliased_Present => False,
Subtype_Indication =>
New_Occurrence_Of (RTE (RE_Tag), Loc))));
+
+ Set_Is_Tag (Defining_Identifier (Last (Comp_List)));
end if;
Append_To (Comp_List,
@@ -10366,17 +10361,6 @@ package body Exp_Util is
Component_Items => Comp_List,
Variant_Part => Empty))));
- -- Suppress all checks during the analysis of the expanded code to avoid
- -- the generation of spurious warnings under ZFP run-time.
-
- Insert_Actions (E, List_Def, Suppress => All_Checks);
-
- -- In the case of an interface type mark the tag for First_Tag_Component
-
- if Is_Interface (Root_Typ) then
- Set_Is_Tag (First_Entity (Equiv_Type));
- end if;
-
return Equiv_Type;
end Make_CW_Equivalent_Type;
@@ -10765,6 +10749,7 @@ package body Exp_Util is
declare
CW_Subtype : constant Entity_Id :=
New_Class_Wide_Subtype (Unc_Typ, E);
+ Equiv_Def : List_Id;
begin
-- A class-wide equivalent type is not needed on VM targets
@@ -10788,7 +10773,14 @@ package body Exp_Util is
end if;
Set_Equivalent_Type
- (CW_Subtype, Make_CW_Equivalent_Type (Unc_Typ, E));
+ (CW_Subtype, Make_CW_Equivalent_Type (Unc_Typ, E, Equiv_Def));
+
+ -- Suppress all checks during the analysis of the expanded
+ -- code to avoid the generation of spurious warnings under
+ -- ZFP run-time.
+
+ Insert_Actions
+ (E, Equiv_Def, Suppress => All_Checks);
end if;
Set_Cloned_Subtype (CW_Subtype, Base_Type (Unc_Typ));
diff --git a/gcc/ada/exp_util.ads b/gcc/ada/exp_util.ads
index 8d64b11..16d8e14 100644
--- a/gcc/ada/exp_util.ads
+++ b/gcc/ada/exp_util.ads
@@ -885,6 +885,26 @@ package Exp_Util is
-- list. If Warn is True, a warning will be output at the start of N
-- indicating the deletion of the code.
+ function Make_CW_Equivalent_Type
+ (T : Entity_Id;
+ E : Node_Id;
+ List_Def : out List_Id) return Entity_Id;
+ -- T is a class-wide type entity, and E is the initial expression node that
+ -- constrains T in cases such as: " X: T := E" or "new T'(E)". When there
+ -- is no E present then it is assumed that T is an unconstrained mutably
+ -- tagged class-wide type.
+ --
+ -- This function returns the entity of the Equivalent type and inserts
+ -- on the fly the necessary declaration into List_Def such as:
+ --
+ -- type anon is record
+ -- _parent : Root_Type (T); constrained with E discriminants (if any)
+ -- Extension : String (1 .. expr to match size of E);
+ -- end record;
+ --
+ -- This record is compatible with any object of the class of T thanks to
+ -- the first field and has the same size as E thanks to the second.
+
function Make_Invariant_Call (Expr : Node_Id) return Node_Id;
-- Generate a call to the Invariant_Procedure associated with the type of
-- expression Expr. Expr is passed as an actual parameter in the call.
diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb
index 523b026..5dbf719 100644
--- a/gcc/ada/freeze.adb
+++ b/gcc/ada/freeze.adb
@@ -1012,15 +1012,10 @@ package body Freeze is
elsif Is_Record_Type (T) then
- -- A class-wide type is never considered to have a known size
-
- if Is_Class_Wide_Type (T) then
- return False;
-
-- A subtype of a variant record must not have non-static
-- discriminated components.
- elsif T /= Base_Type (T)
+ if T /= Base_Type (T)
and then not Static_Discriminated_Components (T)
then
return False;
@@ -7819,6 +7814,7 @@ package body Freeze is
if (Has_Size_Clause (E) or else Has_Object_Size_Clause (E))
and then not Size_Known_At_Compile_Time (E)
+ and then not Is_Mutably_Tagged_Type (E)
then
-- Suppress this message if errors posted on E, even if we are
-- in all errors mode, since this is often a junk message
diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in
index 3cbbf50..ebf1f70 100644
--- a/gcc/ada/gcc-interface/Make-lang.in
+++ b/gcc/ada/gcc-interface/Make-lang.in
@@ -376,6 +376,7 @@ GNAT_ADA_OBJS = \
ada/namet.o \
ada/nlists.o \
ada/nmake.o \
+ ada/mutably_tagged.o \
ada/opt.o \
ada/osint-c.o \
ada/osint.o \
diff --git a/gcc/ada/gen_il-fields.ads b/gcc/ada/gen_il-fields.ads
index 54a5703..5aa246d 100644
--- a/gcc/ada/gen_il-fields.ads
+++ b/gcc/ada/gen_il-fields.ads
@@ -460,6 +460,7 @@ package Gen_IL.Fields is
Class_Postconditions,
Class_Preconditions,
Class_Preconditions_Subprogram,
+ Class_Wide_Equivalent_Type,
Class_Wide_Type,
Cloned_Subtype,
Component_Alignment,
@@ -744,6 +745,7 @@ package Gen_IL.Fields is
Is_Local_Anonymous_Access,
Is_Loop_Parameter,
Is_Machine_Code_Subprogram,
+ Is_Mutably_Tagged_Type,
Is_Non_Static_Subtype,
Is_Null_Init_Proc,
Is_Obsolescent,
diff --git a/gcc/ada/gen_il-gen-gen_entities.adb b/gcc/ada/gen_il-gen-gen_entities.adb
index f5b1b43..c3595bb 100644
--- a/gcc/ada/gen_il-gen-gen_entities.adb
+++ b/gcc/ada/gen_il-gen-gen_entities.adb
@@ -459,6 +459,7 @@ begin -- Gen_IL.Gen.Gen_Entities
Sm (Associated_Node_For_Itype, Node_Id),
Sm (Can_Use_Internal_Rep, Flag, Base_Type_Only,
Pre => "Ekind (Base_Type (N)) in Access_Subprogram_Kind"),
+ Sm (Class_Wide_Equivalent_Type, Node_Id),
Sm (Class_Wide_Type, Node_Id),
Sm (Contract, Node_Id),
Sm (Current_Use_Clause, Node_Id),
@@ -504,6 +505,7 @@ begin -- Gen_IL.Gen.Gen_Entities
Sm (Is_Fixed_Lower_Bound_Array_Subtype, Flag),
Sm (Is_Fixed_Lower_Bound_Index_Subtype, Flag),
Sm (Is_Generic_Actual_Type, Flag),
+ Sm (Is_Mutably_Tagged_Type, Flag),
Sm (Is_Non_Static_Subtype, Flag),
Sm (Is_Private_Composite, Flag),
Sm (Is_RACW_Stub_Type, Flag),
diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi
index 2764ebd..4dfb896 100644
--- a/gcc/ada/gnat_rm.texi
+++ b/gcc/ada/gnat_rm.texi
@@ -904,6 +904,7 @@ Experimental Language Extensions
* Pragma Storage_Model::
* Simpler accessibility model::
* Case pattern matching::
+* Mutably Tagged Types with Size’Class Aspect::
Security Hardening Features
@@ -29228,6 +29229,7 @@ particular the @code{Shift_Left} and @code{Shift_Right} intrinsics.
* Pragma Storage_Model::
* Simpler accessibility model::
* Case pattern matching::
+* Mutably Tagged Types with Size’Class Aspect::
@end menu
@@ -29259,7 +29261,7 @@ while removing dynamic accessibility checking.
Here is a link to the full RFC:
@indicateurl{https://github.com/AdaCore/ada-spark-rfcs/blob/master/prototyped/rfc-simpler-accessibility.md}
-@node Case pattern matching,,Simpler accessibility model,Experimental Language Extensions
+@node Case pattern matching,Mutably Tagged Types with Size’Class Aspect,Simpler accessibility model,Experimental Language Extensions
@anchor{gnat_rm/gnat_language_extensions case-pattern-matching}@anchor{44b}
@subsection Case pattern matching
@@ -29391,8 +29393,48 @@ case statement with composite selector type”.
Link to the original RFC:
@indicateurl{https://github.com/AdaCore/ada-spark-rfcs/blob/master/prototyped/rfc-pattern-matching.rst}
+@node Mutably Tagged Types with Size’Class Aspect,,Case pattern matching,Experimental Language Extensions
+@anchor{gnat_rm/gnat_language_extensions mutably-tagged-types-with-size-class-aspect}@anchor{44c}
+@subsection Mutably Tagged Types with Size’Class Aspect
+
+
+The @cite{Size’Class} aspect can be applied to a tagged type to specify a size
+constraint for the type and its descendants. When this aspect is specified
+on a tagged type, the class-wide type of that type is considered to be a
+“mutably tagged” type - meaning that objects of the class-wide type can have
+their tag changed by assignment from objects with a different tag.
+
+When the aspect is applied to a type, the size of each of its descendant types
+must not exceed the size specified for the aspect.
+
+Example:
+
+@example
+type Base is tagged null record
+ with Size'Class => 16 * 8; -- Size in bits (128 bits, or 16 bytes)
+
+type Derived_Type is new Base with record
+ Data_Field : Integer;
+end record; -- ERROR if Derived_Type exceeds 16 bytes
+@end example
+
+Class-wide types with a specified @cite{Size’Class} can be used as the type of
+array components, record components, and stand-alone objects.
+
+@example
+Inst : Base'Class;
+type Array_of_Base is array (Positive range <>) of Base'Class;
+@end example
+
+Note: Legality of the @cite{Size’Class} aspect is subject to certain restrictions on
+the tagged type, such as being undiscriminated, having no dynamic composite
+subcomponents, among others detailed in the RFC.
+
+Link to the original RFC:
+@indicateurl{https://github.com/AdaCore/ada-spark-rfcs/blob/topic/rfc-finally/considered/rfc-class-size.md}
+
@node Security Hardening Features,Obsolescent Features,GNAT language extensions,Top
-@anchor{gnat_rm/security_hardening_features doc}@anchor{44c}@anchor{gnat_rm/security_hardening_features id1}@anchor{44d}@anchor{gnat_rm/security_hardening_features security-hardening-features}@anchor{15}
+@anchor{gnat_rm/security_hardening_features doc}@anchor{44d}@anchor{gnat_rm/security_hardening_features id1}@anchor{44e}@anchor{gnat_rm/security_hardening_features security-hardening-features}@anchor{15}
@chapter Security Hardening Features
@@ -29414,7 +29456,7 @@ change.
@end menu
@node Register Scrubbing,Stack Scrubbing,,Security Hardening Features
-@anchor{gnat_rm/security_hardening_features register-scrubbing}@anchor{44e}
+@anchor{gnat_rm/security_hardening_features register-scrubbing}@anchor{44f}
@section Register Scrubbing
@@ -29450,7 +29492,7 @@ programming languages, see @cite{Using the GNU Compiler Collection (GCC)}.
@c Stack Scrubbing:
@node Stack Scrubbing,Hardened Conditionals,Register Scrubbing,Security Hardening Features
-@anchor{gnat_rm/security_hardening_features stack-scrubbing}@anchor{44f}
+@anchor{gnat_rm/security_hardening_features stack-scrubbing}@anchor{450}
@section Stack Scrubbing
@@ -29594,7 +29636,7 @@ Bar_Callable_Ptr.
@c Hardened Conditionals:
@node Hardened Conditionals,Hardened Booleans,Stack Scrubbing,Security Hardening Features
-@anchor{gnat_rm/security_hardening_features hardened-conditionals}@anchor{450}
+@anchor{gnat_rm/security_hardening_features hardened-conditionals}@anchor{451}
@section Hardened Conditionals
@@ -29684,7 +29726,7 @@ be used with other programming languages supported by GCC.
@c Hardened Booleans:
@node Hardened Booleans,Control Flow Redundancy,Hardened Conditionals,Security Hardening Features
-@anchor{gnat_rm/security_hardening_features hardened-booleans}@anchor{451}
+@anchor{gnat_rm/security_hardening_features hardened-booleans}@anchor{452}
@section Hardened Booleans
@@ -29745,7 +29787,7 @@ and more details on that attribute, see @cite{Using the GNU Compiler Collection
@c Control Flow Redundancy:
@node Control Flow Redundancy,,Hardened Booleans,Security Hardening Features
-@anchor{gnat_rm/security_hardening_features control-flow-redundancy}@anchor{452}
+@anchor{gnat_rm/security_hardening_features control-flow-redundancy}@anchor{453}
@section Control Flow Redundancy
@@ -29913,7 +29955,7 @@ see @cite{Using the GNU Compiler Collection (GCC)}. These options
can be used with other programming languages supported by GCC.
@node Obsolescent Features,Compatibility and Porting Guide,Security Hardening Features,Top
-@anchor{gnat_rm/obsolescent_features doc}@anchor{453}@anchor{gnat_rm/obsolescent_features id1}@anchor{454}@anchor{gnat_rm/obsolescent_features obsolescent-features}@anchor{16}
+@anchor{gnat_rm/obsolescent_features doc}@anchor{454}@anchor{gnat_rm/obsolescent_features id1}@anchor{455}@anchor{gnat_rm/obsolescent_features obsolescent-features}@anchor{16}
@chapter Obsolescent Features
@@ -29932,7 +29974,7 @@ compatibility purposes.
@end menu
@node pragma No_Run_Time,pragma Ravenscar,,Obsolescent Features
-@anchor{gnat_rm/obsolescent_features id2}@anchor{455}@anchor{gnat_rm/obsolescent_features pragma-no-run-time}@anchor{456}
+@anchor{gnat_rm/obsolescent_features id2}@anchor{456}@anchor{gnat_rm/obsolescent_features pragma-no-run-time}@anchor{457}
@section pragma No_Run_Time
@@ -29945,7 +29987,7 @@ preferred usage is to use an appropriately configured run-time that
includes just those features that are to be made accessible.
@node pragma Ravenscar,pragma Restricted_Run_Time,pragma No_Run_Time,Obsolescent Features
-@anchor{gnat_rm/obsolescent_features id3}@anchor{457}@anchor{gnat_rm/obsolescent_features pragma-ravenscar}@anchor{458}
+@anchor{gnat_rm/obsolescent_features id3}@anchor{458}@anchor{gnat_rm/obsolescent_features pragma-ravenscar}@anchor{459}
@section pragma Ravenscar
@@ -29954,7 +29996,7 @@ The pragma @code{Ravenscar} has exactly the same effect as pragma
is part of the new Ada 2005 standard.
@node pragma Restricted_Run_Time,pragma Task_Info,pragma Ravenscar,Obsolescent Features
-@anchor{gnat_rm/obsolescent_features id4}@anchor{459}@anchor{gnat_rm/obsolescent_features pragma-restricted-run-time}@anchor{45a}
+@anchor{gnat_rm/obsolescent_features id4}@anchor{45a}@anchor{gnat_rm/obsolescent_features pragma-restricted-run-time}@anchor{45b}
@section pragma Restricted_Run_Time
@@ -29964,7 +30006,7 @@ preferred since the Ada 2005 pragma @code{Profile} is intended for
this kind of implementation dependent addition.
@node pragma Task_Info,package System Task_Info s-tasinf ads,pragma Restricted_Run_Time,Obsolescent Features
-@anchor{gnat_rm/obsolescent_features id5}@anchor{45b}@anchor{gnat_rm/obsolescent_features pragma-task-info}@anchor{45c}
+@anchor{gnat_rm/obsolescent_features id5}@anchor{45c}@anchor{gnat_rm/obsolescent_features pragma-task-info}@anchor{45d}
@section pragma Task_Info
@@ -29990,7 +30032,7 @@ in the spec of package System.Task_Info in the runtime
library.
@node package System Task_Info s-tasinf ads,,pragma Task_Info,Obsolescent Features
-@anchor{gnat_rm/obsolescent_features package-system-task-info}@anchor{45d}@anchor{gnat_rm/obsolescent_features package-system-task-info-s-tasinf-ads}@anchor{45e}
+@anchor{gnat_rm/obsolescent_features package-system-task-info}@anchor{45e}@anchor{gnat_rm/obsolescent_features package-system-task-info-s-tasinf-ads}@anchor{45f}
@section package System.Task_Info (@code{s-tasinf.ads})
@@ -30000,7 +30042,7 @@ to support the @code{Task_Info} pragma. The predefined Ada package
standard replacement for GNAT’s @code{Task_Info} functionality.
@node Compatibility and Porting Guide,GNU Free Documentation License,Obsolescent Features,Top
-@anchor{gnat_rm/compatibility_and_porting_guide doc}@anchor{45f}@anchor{gnat_rm/compatibility_and_porting_guide compatibility-and-porting-guide}@anchor{17}@anchor{gnat_rm/compatibility_and_porting_guide id1}@anchor{460}
+@anchor{gnat_rm/compatibility_and_porting_guide doc}@anchor{460}@anchor{gnat_rm/compatibility_and_porting_guide compatibility-and-porting-guide}@anchor{17}@anchor{gnat_rm/compatibility_and_porting_guide id1}@anchor{461}
@chapter Compatibility and Porting Guide
@@ -30022,7 +30064,7 @@ applications developed in other Ada environments.
@end menu
@node Writing Portable Fixed-Point Declarations,Compatibility with Ada 83,,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide id2}@anchor{461}@anchor{gnat_rm/compatibility_and_porting_guide writing-portable-fixed-point-declarations}@anchor{462}
+@anchor{gnat_rm/compatibility_and_porting_guide id2}@anchor{462}@anchor{gnat_rm/compatibility_and_porting_guide writing-portable-fixed-point-declarations}@anchor{463}
@section Writing Portable Fixed-Point Declarations
@@ -30144,7 +30186,7 @@ If you follow this scheme you will be guaranteed that your fixed-point
types will be portable.
@node Compatibility with Ada 83,Compatibility between Ada 95 and Ada 2005,Writing Portable Fixed-Point Declarations,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-ada-83}@anchor{463}@anchor{gnat_rm/compatibility_and_porting_guide id3}@anchor{464}
+@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-ada-83}@anchor{464}@anchor{gnat_rm/compatibility_and_porting_guide id3}@anchor{465}
@section Compatibility with Ada 83
@@ -30172,7 +30214,7 @@ following subsections treat the most likely issues to be encountered.
@end menu
@node Legal Ada 83 programs that are illegal in Ada 95,More deterministic semantics,,Compatibility with Ada 83
-@anchor{gnat_rm/compatibility_and_porting_guide id4}@anchor{465}@anchor{gnat_rm/compatibility_and_porting_guide legal-ada-83-programs-that-are-illegal-in-ada-95}@anchor{466}
+@anchor{gnat_rm/compatibility_and_porting_guide id4}@anchor{466}@anchor{gnat_rm/compatibility_and_porting_guide legal-ada-83-programs-that-are-illegal-in-ada-95}@anchor{467}
@subsection Legal Ada 83 programs that are illegal in Ada 95
@@ -30272,7 +30314,7 @@ the fix is usually simply to add the @code{(<>)} to the generic declaration.
@end itemize
@node More deterministic semantics,Changed semantics,Legal Ada 83 programs that are illegal in Ada 95,Compatibility with Ada 83
-@anchor{gnat_rm/compatibility_and_porting_guide id5}@anchor{467}@anchor{gnat_rm/compatibility_and_porting_guide more-deterministic-semantics}@anchor{468}
+@anchor{gnat_rm/compatibility_and_porting_guide id5}@anchor{468}@anchor{gnat_rm/compatibility_and_porting_guide more-deterministic-semantics}@anchor{469}
@subsection More deterministic semantics
@@ -30300,7 +30342,7 @@ which open select branches are executed.
@end itemize
@node Changed semantics,Other language compatibility issues,More deterministic semantics,Compatibility with Ada 83
-@anchor{gnat_rm/compatibility_and_porting_guide changed-semantics}@anchor{469}@anchor{gnat_rm/compatibility_and_porting_guide id6}@anchor{46a}
+@anchor{gnat_rm/compatibility_and_porting_guide changed-semantics}@anchor{46a}@anchor{gnat_rm/compatibility_and_porting_guide id6}@anchor{46b}
@subsection Changed semantics
@@ -30342,7 +30384,7 @@ covers only the restricted range.
@end itemize
@node Other language compatibility issues,,Changed semantics,Compatibility with Ada 83
-@anchor{gnat_rm/compatibility_and_porting_guide id7}@anchor{46b}@anchor{gnat_rm/compatibility_and_porting_guide other-language-compatibility-issues}@anchor{46c}
+@anchor{gnat_rm/compatibility_and_porting_guide id7}@anchor{46c}@anchor{gnat_rm/compatibility_and_porting_guide other-language-compatibility-issues}@anchor{46d}
@subsection Other language compatibility issues
@@ -30375,7 +30417,7 @@ include @code{pragma Interface} and the floating point type attributes
@end itemize
@node Compatibility between Ada 95 and Ada 2005,Implementation-dependent characteristics,Compatibility with Ada 83,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide compatibility-between-ada-95-and-ada-2005}@anchor{46d}@anchor{gnat_rm/compatibility_and_porting_guide id8}@anchor{46e}
+@anchor{gnat_rm/compatibility_and_porting_guide compatibility-between-ada-95-and-ada-2005}@anchor{46e}@anchor{gnat_rm/compatibility_and_porting_guide id8}@anchor{46f}
@section Compatibility between Ada 95 and Ada 2005
@@ -30447,7 +30489,7 @@ can declare a function returning a value from an anonymous access type.
@end itemize
@node Implementation-dependent characteristics,Compatibility with Other Ada Systems,Compatibility between Ada 95 and Ada 2005,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide id9}@anchor{46f}@anchor{gnat_rm/compatibility_and_porting_guide implementation-dependent-characteristics}@anchor{470}
+@anchor{gnat_rm/compatibility_and_porting_guide id9}@anchor{470}@anchor{gnat_rm/compatibility_and_porting_guide implementation-dependent-characteristics}@anchor{471}
@section Implementation-dependent characteristics
@@ -30470,7 +30512,7 @@ transition from certain Ada 83 compilers.
@end menu
@node Implementation-defined pragmas,Implementation-defined attributes,,Implementation-dependent characteristics
-@anchor{gnat_rm/compatibility_and_porting_guide id10}@anchor{471}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-pragmas}@anchor{472}
+@anchor{gnat_rm/compatibility_and_porting_guide id10}@anchor{472}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-pragmas}@anchor{473}
@subsection Implementation-defined pragmas
@@ -30492,7 +30534,7 @@ avoiding compiler rejection of units that contain such pragmas; they are not
relevant in a GNAT context and hence are not otherwise implemented.
@node Implementation-defined attributes,Libraries,Implementation-defined pragmas,Implementation-dependent characteristics
-@anchor{gnat_rm/compatibility_and_porting_guide id11}@anchor{473}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-attributes}@anchor{474}
+@anchor{gnat_rm/compatibility_and_porting_guide id11}@anchor{474}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-attributes}@anchor{475}
@subsection Implementation-defined attributes
@@ -30506,7 +30548,7 @@ Ada 83, GNAT supplies the attributes @code{Bit}, @code{Machine_Size} and
@code{Type_Class}.
@node Libraries,Elaboration order,Implementation-defined attributes,Implementation-dependent characteristics
-@anchor{gnat_rm/compatibility_and_porting_guide id12}@anchor{475}@anchor{gnat_rm/compatibility_and_porting_guide libraries}@anchor{476}
+@anchor{gnat_rm/compatibility_and_porting_guide id12}@anchor{476}@anchor{gnat_rm/compatibility_and_porting_guide libraries}@anchor{477}
@subsection Libraries
@@ -30535,7 +30577,7 @@ be preferable to retrofit the application using modular types.
@end itemize
@node Elaboration order,Target-specific aspects,Libraries,Implementation-dependent characteristics
-@anchor{gnat_rm/compatibility_and_porting_guide elaboration-order}@anchor{477}@anchor{gnat_rm/compatibility_and_porting_guide id13}@anchor{478}
+@anchor{gnat_rm/compatibility_and_porting_guide elaboration-order}@anchor{478}@anchor{gnat_rm/compatibility_and_porting_guide id13}@anchor{479}
@subsection Elaboration order
@@ -30571,7 +30613,7 @@ pragmas either globally (as an effect of the `-gnatE' switch) or locally
@end itemize
@node Target-specific aspects,,Elaboration order,Implementation-dependent characteristics
-@anchor{gnat_rm/compatibility_and_porting_guide id14}@anchor{479}@anchor{gnat_rm/compatibility_and_porting_guide target-specific-aspects}@anchor{47a}
+@anchor{gnat_rm/compatibility_and_porting_guide id14}@anchor{47a}@anchor{gnat_rm/compatibility_and_porting_guide target-specific-aspects}@anchor{47b}
@subsection Target-specific aspects
@@ -30584,10 +30626,10 @@ on the robustness of the original design. Moreover, Ada 95 (and thus
Ada 2005 and Ada 2012) are sometimes
incompatible with typical Ada 83 compiler practices regarding implicit
packing, the meaning of the Size attribute, and the size of access values.
-GNAT’s approach to these issues is described in @ref{47b,,Representation Clauses}.
+GNAT’s approach to these issues is described in @ref{47c,,Representation Clauses}.
@node Compatibility with Other Ada Systems,Representation Clauses,Implementation-dependent characteristics,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-other-ada-systems}@anchor{47c}@anchor{gnat_rm/compatibility_and_porting_guide id15}@anchor{47d}
+@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-other-ada-systems}@anchor{47d}@anchor{gnat_rm/compatibility_and_porting_guide id15}@anchor{47e}
@section Compatibility with Other Ada Systems
@@ -30630,7 +30672,7 @@ far beyond this minimal set, as described in the next section.
@end itemize
@node Representation Clauses,Compatibility with HP Ada 83,Compatibility with Other Ada Systems,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide id16}@anchor{47e}@anchor{gnat_rm/compatibility_and_porting_guide representation-clauses}@anchor{47b}
+@anchor{gnat_rm/compatibility_and_porting_guide id16}@anchor{47f}@anchor{gnat_rm/compatibility_and_porting_guide representation-clauses}@anchor{47c}
@section Representation Clauses
@@ -30723,7 +30765,7 @@ with thin pointers.
@end itemize
@node Compatibility with HP Ada 83,,Representation Clauses,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-hp-ada-83}@anchor{47f}@anchor{gnat_rm/compatibility_and_porting_guide id17}@anchor{480}
+@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-hp-ada-83}@anchor{480}@anchor{gnat_rm/compatibility_and_porting_guide id17}@anchor{481}
@section Compatibility with HP Ada 83
@@ -30753,7 +30795,7 @@ extension of package System.
@end itemize
@node GNU Free Documentation License,Index,Compatibility and Porting Guide,Top
-@anchor{share/gnu_free_documentation_license doc}@anchor{481}@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{482}
+@anchor{share/gnu_free_documentation_license doc}@anchor{482}@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{483}
@chapter GNU Free Documentation License
diff --git a/gcc/ada/mutably_tagged.adb b/gcc/ada/mutably_tagged.adb
new file mode 100644
index 0000000..34b032f0
--- /dev/null
+++ b/gcc/ada/mutably_tagged.adb
@@ -0,0 +1,337 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- M U T A B L Y _ T A G G E D --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2024-2024, 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- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with Atree; use Atree;
+with Casing; use Casing;
+with Einfo; use Einfo;
+with Einfo.Entities; use Einfo.Entities;
+with Einfo.Utils; use Einfo.Utils;
+with Exp_Util; use Exp_Util;
+with Namet; use Namet;
+with Nlists; use Nlists;
+with Nmake; use Nmake;
+with Rtsfind; use Rtsfind;
+with Snames; use Snames;
+with Sem_Util; use Sem_Util;
+with Sinfo; use Sinfo;
+with Sinfo.Nodes; use Sinfo.Nodes;
+with Sinfo.Utils; use Sinfo.Utils;
+with Stringt; use Stringt;
+with Tbuild; use Tbuild;
+
+package body Mutably_Tagged is
+
+ ---------------------------------------
+ -- Corresponding_Mutably_Tagged_Type --
+ ---------------------------------------
+
+ function Corresponding_Mutably_Tagged_Type
+ (CW_Equiv_Typ : Entity_Id) return Entity_Id
+ is
+ begin
+ return Class_Wide_Type (Parent_Subtype (CW_Equiv_Typ));
+ end Corresponding_Mutably_Tagged_Type;
+
+ ----------------------------------------
+ -- Depends_On_Mutably_Tagged_Ext_Comp --
+ ----------------------------------------
+
+ function Depends_On_Mutably_Tagged_Ext_Comp (N : Node_Id) return Boolean is
+ Typ : Entity_Id;
+ Typ_Comp : Entity_Id;
+ Curr : Node_Id;
+ Prev : Node_Id;
+ begin
+ -- Move through each prefix until we hit a type conversion from a
+ -- mutably tagged type then check if the referenced component exists in
+ -- the root type or an extension.
+
+ Curr := N;
+ while Has_Prefix (Curr) loop
+ Prev := Curr;
+ Curr := Prefix (Curr);
+
+ -- Find a prefix which is a type conversion from a mutably tagged
+ -- type in some form - either class-wide equivalent type or
+ -- directly a mutably tagged type.
+
+ if Nkind (Curr) in N_Unchecked_Type_Conversion
+ | N_Type_Conversion
+ and then (Is_Mutably_Tagged_CW_Equivalent_Type
+ (Etype (Expression (Curr)))
+ or else Is_Mutably_Tagged_Type
+ (Etype (Expression (Curr))))
+
+ -- Verify that the prefix references a component
+
+ and then Is_Entity_Name (Selector_Name (Prev))
+ and then Ekind (Entity (Selector_Name (Prev)))
+ = E_Component
+ then
+ -- Obtain the root type
+
+ Typ := Etype (if Is_Mutably_Tagged_Type
+ (Etype (Expression (Curr)))
+ then
+ Etype (Expression (Curr))
+ else
+ Corresponding_Mutably_Tagged_Type
+ (Etype (Expression (Curr))));
+
+ -- Move through the components of the root type looking for a
+ -- match to the reference component.
+
+ Typ_Comp := First_Component (Typ);
+ while Present (Typ_Comp) loop
+
+ -- When there is a match we know the component reference
+ -- doesn't depend on a type extension.
+
+ if Chars (Typ_Comp) = Chars (Entity (Selector_Name (Prev))) then
+ return False;
+ end if;
+
+ Next_Component (Typ_Comp);
+ end loop;
+
+ -- Otherwise, the component must depend on an extension
+
+ return True;
+ end if;
+ end loop;
+
+ -- If we get here then we know we don't have any sort of relevant type
+ -- conversion from a mutably tagged object.
+
+ return False;
+ end Depends_On_Mutably_Tagged_Ext_Comp;
+
+ ------------------------------------------------------
+ -- Get_Corresponding_Mutably_Tagged_Type_If_Present --
+ ------------------------------------------------------
+
+ function Get_Corresponding_Mutably_Tagged_Type_If_Present
+ (Typ : Entity_Id) return Entity_Id
+ is
+ begin
+ if Is_Mutably_Tagged_CW_Equivalent_Type (Typ) then
+ return Corresponding_Mutably_Tagged_Type (Typ);
+ end if;
+
+ return Typ;
+ end Get_Corresponding_Mutably_Tagged_Type_If_Present;
+
+ ----------------------------------------------
+ -- Get_Corresponding_Tagged_Type_If_Present --
+ ----------------------------------------------
+
+ function Get_Corresponding_Tagged_Type_If_Present
+ (Typ : Entity_Id) return Entity_Id
+ is
+ begin
+ -- Obtain the related tagged type for the class-wide mutably
+ -- tagged type associated with the class-wide equivalent type.
+
+ if Is_Mutably_Tagged_CW_Equivalent_Type (Typ) then
+ return Parent_Subtype (Typ);
+ end if;
+
+ return Typ;
+ end Get_Corresponding_Tagged_Type_If_Present;
+
+ ----------------------------------
+ -- Is_Mutably_Tagged_Conversion --
+ ----------------------------------
+
+ function Is_Mutably_Tagged_Conversion (N : Node_Id) return Boolean is
+ begin
+ return Nkind (N) = N_Unchecked_Type_Conversion
+ and then Is_Mutably_Tagged_CW_Equivalent_Type
+ (Etype (Expression (N)));
+ end Is_Mutably_Tagged_Conversion;
+
+ ------------------------------------------
+ -- Is_Mutably_Tagged_CW_Equivalent_Type --
+ ------------------------------------------
+
+ function Is_Mutably_Tagged_CW_Equivalent_Type
+ (Typ : Entity_Id) return Boolean
+ is
+ begin
+ -- First assure Typ is OK to test since this function can be called in
+ -- a context where analysis failed.
+
+ return Present (Typ)
+ and then not Error_Posted (Typ)
+
+ -- Finally check Typ is a class-wide equivalent type which has an
+ -- associated mutably tagged class-wide type (e.g. it is a class-wide
+ -- type with a size clause).
+
+ and then Is_Class_Wide_Equivalent_Type (Typ)
+ and then Present (Parent_Subtype (Typ))
+ and then Present (Class_Wide_Type (Parent_Subtype (Typ)))
+ and then Has_Size_Clause (Corresponding_Mutably_Tagged_Type (Typ));
+ end Is_Mutably_Tagged_CW_Equivalent_Type;
+
+ --------------------------------
+ -- Make_CW_Size_Compile_Check --
+ --------------------------------
+
+ function Make_CW_Size_Compile_Check
+ (New_Typ : Entity_Id;
+ Mut_Tag_Typ : Entity_Id) return Node_Id
+ is
+ Loc : constant Source_Ptr := Sloc (New_Typ);
+ begin
+ -- Generate a string literal for New_Typ's name which is needed for
+ -- printing within the Compile_Time_Error.
+
+ Get_Decoded_Name_String (Chars (New_Typ));
+ Set_Casing (Mixed_Case);
+
+ -- Build a pragma Compile_Time_Error to force the backend to
+ -- preform appropriate sizing checks.
+
+ -- Generate:
+ -- pragma Compile_Time_Error
+ -- (New_Typ'Size < Mut_Tag_Typ'Size,
+ -- "class size for by-reference type ""New_Typ"" too small")
+
+ return
+ Make_Pragma (Loc,
+ Chars => Name_Compile_Time_Error,
+ Pragma_Argument_Associations => New_List (
+ Make_Pragma_Argument_Association (Loc,
+ Expression => (
+ Make_Op_Gt (Loc,
+ Left_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Attribute_Name => Name_Size,
+ Prefix =>
+ New_Occurrence_Of (New_Typ, Loc)),
+ Right_Opnd =>
+ Make_Integer_Literal (Loc,
+ RM_Size (Mut_Tag_Typ))))),
+ Make_Pragma_Argument_Association (Loc,
+ Expression =>
+
+ -- Is it possible to print the size of New_Typ via
+ -- Validate_Compile_Time_Warning_Or_Error after the back-end
+ -- has run to generate the error message manually ???
+
+ Make_String_Literal (Loc,
+ "class size for by-reference type """
+ & To_String (String_From_Name_Buffer)
+ & """ too small"))));
+ end Make_CW_Size_Compile_Check;
+
+ ------------------------------------
+ -- Make_Mutably_Tagged_Conversion --
+ ------------------------------------
+
+ procedure Make_Mutably_Tagged_Conversion
+ (N : Node_Id;
+ Typ : Entity_Id := Empty;
+ Force : Boolean := False)
+ is
+ Conv_Typ : constant Entity_Id :=
+
+ -- When Typ is not present, we obtain it at this point
+
+ (if Present (Typ) then
+ Typ
+ else
+ Corresponding_Mutably_Tagged_Type (Etype (N)));
+
+ begin
+ -- Allow "forcing" the rewrite to an unchecked conversion
+
+ if Force
+
+ -- Otherwise, don't make the conversion when N is on the left-hand
+ -- side of the assignment, is already part of an unchecked conversion,
+ -- or is part of a renaming.
+
+ or else (not Known_To_Be_Assigned (N, Only_LHS => True)
+ and then (No (Parent (N))
+ or else Nkind (Parent (N))
+ not in N_Selected_Component
+ | N_Unchecked_Type_Conversion
+ | N_Object_Renaming_Declaration))
+ then
+ -- Exclude the case where we have a 'Size so that we get the proper
+ -- size of the class-wide equivalent type. Are there other cases ???
+
+ if Present (Parent (N))
+ and then Nkind (Parent (N)) = N_Attribute_Reference
+ and then Attribute_Name (Parent (N)) in Name_Size
+ then
+ return;
+ end if;
+
+ -- Create the conversion
+
+ Rewrite (N,
+ Unchecked_Convert_To
+ (Conv_Typ, Relocate_Node (N)));
+ end if;
+ end Make_Mutably_Tagged_Conversion;
+
+ ----------------------------------
+ -- Make_Mutably_Tagged_CW_Check --
+ ----------------------------------
+
+ function Make_Mutably_Tagged_CW_Check
+ (N : Node_Id;
+ Tag : Node_Id) return Node_Id
+ is
+ Loc : constant Source_Ptr := Sloc (N);
+
+ -- Displace the pointer to the base of the objects applying 'Address,
+ -- which is later expanded into a call to RE_Base_Address.
+
+ N_Tag : constant Node_Id :=
+ Make_Explicit_Dereference (Loc,
+ Prefix =>
+ Unchecked_Convert_To (RTE (RE_Tag_Ptr),
+ Make_Attribute_Reference (Loc,
+ Prefix => Duplicate_Subexpr (N),
+ Attribute_Name => Name_Address)));
+ begin
+ -- Generate the runtime call to test class-wide membership
+
+ return
+ Make_Raise_Constraint_Error (Loc,
+ Reason => CE_Tag_Check_Failed,
+ Condition =>
+ Make_Op_Not (Loc,
+ Make_Function_Call (Loc,
+ Parameter_Associations => New_List (N_Tag, Tag),
+ Name =>
+ New_Occurrence_Of (RTE (RE_CW_Membership), Loc))));
+ end Make_Mutably_Tagged_CW_Check;
+
+end Mutably_Tagged;
diff --git a/gcc/ada/mutably_tagged.ads b/gcc/ada/mutably_tagged.ads
new file mode 100644
index 0000000..b1e393f
--- /dev/null
+++ b/gcc/ada/mutably_tagged.ads
@@ -0,0 +1,120 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- M U T A B L Y _ T A G G E D --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2024-2024, 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- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- Semantic and expansion utility routines dealing with mutably tagged types
+
+with Types; use Types;
+
+package Mutably_Tagged is
+
+ --------------------------------------------
+ -- Implementation of Mutably Tagged Types --
+ --------------------------------------------
+
+ -- This package implements mutably tagged types via the Size'class aspect
+ -- which enables the creation of class-wide types with a specific maximum
+ -- size. This allows such types to be used directly in record components,
+ -- in object declarations without an initial expression, and to be
+ -- assigned a value from any type in a mutably tagged type's hierarchy.
+
+ -- For example, this structure allows Base_Type and its derivatives to be
+ -- treated as components with a predictable size:
+
+ -- type Base_Type is tagged null record
+ -- with Size'Class => 128;
+
+ -- type Container is record
+ -- Component : Base_Type'Class;
+ -- end record;
+
+ -- The core of thier implementation involve creating an "equivalent" type
+ -- for each class-wide type that adheres to the Size'Class constraint. This
+ -- is achieved using the function Make_CW_Equivalent_Type, which
+ -- generates a type that is compatible in size and structure with any
+ -- derived type of the base class-wide type.
+
+ -- Once the class-wide equivalent type is generated, all references to
+ -- mutably tagged typed object declarations get rewritten to be
+ -- declarations of said equivalent type. References to these objects also
+ -- then get wrapped in unchecked conversions to the proper mutably tagged
+ -- class-wide type.
+
+ function Corresponding_Mutably_Tagged_Type
+ (CW_Equiv_Typ : Entity_Id) return Entity_Id;
+ -- Given a class-wide equivalent type obtain the related mutably tagged
+ -- class-wide type.
+
+ function Depends_On_Mutably_Tagged_Ext_Comp (N : Node_Id) return Boolean;
+ -- Return true if the given node N contains a reference to a component
+ -- of a mutably tagged object which comes from a type extension.
+
+ function Get_Corresponding_Mutably_Tagged_Type_If_Present
+ (Typ : Entity_Id) return Entity_Id;
+ -- Obtain the corresponding mutably tagged type associated with Typ when
+ -- Typ is a mutably tagged class-wide equivalent type. Otherwise, just
+ -- return Typ.
+
+ function Get_Corresponding_Tagged_Type_If_Present
+ (Typ : Entity_Id) return Entity_Id;
+ -- Obtain the corresponding tag type associated with Typ when
+ -- Typ is a mutably tagged class-wide equivalent type. Otherwise, Just
+ -- return Typ.
+
+ -- This function is mostly used when we need a concrete type to generate
+ -- initialization for mutably tagged types.
+
+ function Is_Mutably_Tagged_Conversion (N : Node_Id) return Boolean;
+ -- Return True if expression N is an object of a mutably tagged class-wide
+ -- equivalent type which has been expanded into a type conversion to
+ -- its related mutably tagged class-wide type.
+
+ function Is_Mutably_Tagged_CW_Equivalent_Type
+ (Typ : Entity_Id) return Boolean;
+ -- Determine if Typ is a class-wide equivalent type
+
+ procedure Make_Mutably_Tagged_Conversion
+ (N : Node_Id;
+ Typ : Entity_Id := Empty;
+ Force : Boolean := False);
+ -- Expand a reference N to a given mutably tagged type Typ. When Typ is not
+ -- present the closest associated mutably tagged type in the hierarchy is
+ -- used.
+
+ -- Force is used to ignore certain predicates which avoid generating the
+ -- conversion (e.g. when N is on the left-hand side of an assignment).
+
+ function Make_CW_Size_Compile_Check
+ (New_Typ : Entity_Id;
+ Mut_Tag_Typ : Entity_Id) return Node_Id;
+ -- Generate a type size check on New_Typ based on the size set in
+ -- the mutably tagged type Mut_Tag_Typ.
+
+ function Make_Mutably_Tagged_CW_Check
+ (N : Node_Id;
+ Tag : Node_Id) return Node_Id;
+ -- Generate class-wide membership test for a given expression N based on
+ -- Tag.
+
+end Mutably_Tagged;
diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb
index 249350d..1dbde1f 100644
--- a/gcc/ada/sem_aggr.adb
+++ b/gcc/ada/sem_aggr.adb
@@ -37,6 +37,7 @@ with Freeze; use Freeze;
with Itypes; use Itypes;
with Lib; use Lib;
with Lib.Xref; use Lib.Xref;
+with Mutably_Tagged; use Mutably_Tagged;
with Namet; use Namet;
with Namet.Sp; use Namet.Sp;
with Nmake; use Nmake;
@@ -2699,7 +2700,18 @@ package body Sem_Aggr is
Full_Analysis := Save_Analysis;
Expander_Mode_Restore;
- if Is_Tagged_Type (Etype (Expr)) then
+ -- Skip tagged checking for mutably tagged CW equivalent
+ -- types.
+
+ if Is_Tagged_Type (Etype (Expr))
+ and then Is_Class_Wide_Equivalent_Type
+ (Component_Type (Etype (N)))
+ then
+ null;
+
+ -- Otherwise perform the dynamic tag check
+
+ elsif Is_Tagged_Type (Etype (Expr)) then
Check_Dynamically_Tagged_Expression
(Expr => Expr,
Typ => Component_Type (Etype (N)),
@@ -5344,6 +5356,12 @@ package body Sem_Aggr is
Relocate := True;
end if;
+ -- Obtain the corresponding mutably tagged types if we are looking
+ -- at a special internally generated class-wide equivalent type.
+
+ Expr_Type :=
+ Get_Corresponding_Mutably_Tagged_Type_If_Present (Expr_Type);
+
Analyze_And_Resolve (Expr, Expr_Type);
Check_Expr_OK_In_Limited_Aggregate (Expr);
Check_Non_Static_Context (Expr);
@@ -5351,7 +5369,9 @@ package body Sem_Aggr is
-- Check wrong use of class-wide types
- if Is_Class_Wide_Type (Etype (Expr)) then
+ if Is_Class_Wide_Type (Etype (Expr))
+ and then not Is_Mutably_Tagged_Type (Expr_Type)
+ then
Error_Msg_N ("dynamically tagged expression not allowed", Expr);
end if;
diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index 2563a92..9c3bc62 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -46,6 +46,7 @@ with Gnatvsn; use Gnatvsn;
with Itypes; use Itypes;
with Lib; use Lib;
with Lib.Xref; use Lib.Xref;
+with Mutably_Tagged; use Mutably_Tagged;
with Nlists; use Nlists;
with Nmake; use Nmake;
with Opt; use Opt;
@@ -6753,7 +6754,10 @@ package body Sem_Attr is
Check_E0;
Check_Dereference;
- if not Is_Tagged_Type (P_Type) then
+ if Is_Mutably_Tagged_CW_Equivalent_Type (P_Type) then
+ null;
+
+ elsif not Is_Tagged_Type (P_Type) then
Error_Attr_P ("prefix of % attribute must be tagged");
-- Next test does not apply to generated code why not, and what does
@@ -11785,6 +11789,10 @@ package body Sem_Attr is
Error_Msg_F
("illegal attribute for discriminant-dependent component",
P);
+
+ elsif Depends_On_Mutably_Tagged_Ext_Comp (P) then
+ Error_Msg_F
+ ("illegal attribute for mutably tagged component", P);
end if;
-- Check static matching rule of 3.10.2(27). Nominal subtype
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb
index 93e81fd..d05c7b6 100644
--- a/gcc/ada/sem_ch12.adb
+++ b/gcc/ada/sem_ch12.adb
@@ -40,6 +40,7 @@ with Itypes; use Itypes;
with Lib; use Lib;
with Lib.Load; use Lib.Load;
with Lib.Xref; use Lib.Xref;
+with Mutably_Tagged; use Mutably_Tagged;
with Nlists; use Nlists;
with Namet; use Namet;
with Nmake; use Nmake;
@@ -11497,6 +11498,10 @@ package body Sem_Ch12 is
Error_Msg_N
("illegal discriminant-dependent component for in out parameter",
Actual);
+ elsif Depends_On_Mutably_Tagged_Ext_Comp (Actual) then
+ Error_Msg_N
+ ("illegal mutably tagged component for in out parameter",
+ Actual);
end if;
-- The actual has to be resolved in order to check that it is a
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index caebe2e..2fbddf3 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -43,6 +43,7 @@ with Freeze; use Freeze;
with Ghost; use Ghost;
with Lib; use Lib;
with Lib.Xref; use Lib.Xref;
+with Mutably_Tagged; use Mutably_Tagged;
with Namet; use Namet;
with Nlists; use Nlists;
with Nmake; use Nmake;
@@ -3069,6 +3070,15 @@ package body Sem_Ch13 is
end if;
end if;
+ -- Propagate the 'Size'Class aspect to the class-wide type
+
+ if A_Id = Aspect_Size and then Class_Present (Aspect) then
+ Ent :=
+ Make_Attribute_Reference (Loc,
+ Prefix => Ent,
+ Attribute_Name => Name_Class);
+ end if;
+
-- Construct the attribute_definition_clause. The expression
-- in the aspect specification is simply shared with the
-- constructed attribute, because it will be fully analyzed
@@ -7337,6 +7347,70 @@ package body Sem_Ch13 is
& "supported", N);
end if;
+ -- Handle extension aspect 'Size'Class which allows for
+ -- "mutably tagged" types.
+
+ if Ekind (Etyp) = E_Class_Wide_Type then
+ Error_Msg_GNAT_Extension
+ ("attribute size class", Sloc (N));
+
+ -- Check for various restrictions applied to mutably
+ -- tagged types.
+
+ if Is_Derived_Type (Etype (Etyp)) then
+ Error_Msg_N
+ ("cannot be specified on derived types", Nam);
+
+ elsif Ekind (Etype (Prefix (Nam))) = E_Record_Subtype then
+ Error_Msg_N
+ ("cannot be specified on a subtype", Nam);
+
+ elsif Is_Interface (Etype (Etyp)) then
+ Error_Msg_N
+ ("cannot be specified on interface types", Nam);
+
+ elsif Has_Discriminants (Etype (Etyp)) then
+ Error_Msg_N
+ ("cannot be specified on discriminated type", Nam);
+
+ elsif Present (Incomplete_Or_Partial_View (Etype (Etyp)))
+ and then Is_Tagged_Type
+ (Incomplete_Or_Partial_View (Etype (Etyp)))
+ then
+ Error_Msg_N
+ ("cannot be specified on a type whose partial view"
+ & " is tagged", Nam);
+
+ -- Otherwise, the declaration is valid
+
+ else
+ declare
+ Actions : List_Id;
+ begin
+ -- Generate our class-wide equivalent type which
+ -- is sized according to the value specified by
+ -- 'Size'Class.
+
+ Set_Class_Wide_Equivalent_Type (Etyp,
+ Make_CW_Equivalent_Type (Etyp, Empty, Actions));
+
+ -- Add a Compile_Time_Error sizing check as a hint
+ -- to the backend.
+
+ Append_To (Actions,
+ Make_CW_Size_Compile_Check
+ (Etype (Etyp), U_Ent));
+
+ -- Set the expansion to occur during freezing when
+ -- everything is analyzed
+
+ Append_Freeze_Actions (Etyp, Actions);
+
+ Set_Is_Mutably_Tagged_Type (Etyp);
+ end;
+ end if;
+ end if;
+
Set_Has_Size_Clause (U_Ent);
end;
end if;
diff --git a/gcc/ada/sem_ch2.adb b/gcc/ada/sem_ch2.adb
index db17023..aae9990 100644
--- a/gcc/ada/sem_ch2.adb
+++ b/gcc/ada/sem_ch2.adb
@@ -27,6 +27,7 @@ with Atree; use Atree;
with Einfo; use Einfo;
with Einfo.Utils; use Einfo.Utils;
with Ghost; use Ghost;
+with Mutably_Tagged; use Mutably_Tagged;
with Namet; use Namet;
with Nlists; use Nlists;
with Opt; use Opt;
@@ -81,6 +82,12 @@ package body Sem_Ch2 is
Find_Direct_Name (N);
end if;
+ -- Generate a conversion when we see an expanded mutably tagged type
+
+ if Is_Mutably_Tagged_CW_Equivalent_Type (Etype (N)) then
+ Make_Mutably_Tagged_Conversion (N);
+ end if;
+
-- A Ghost entity must appear in a specific context. Only do this
-- checking on non-overloaded expressions, as otherwise we need to
-- wait for resolution, and the checking is done in Resolve_Entity_Name.
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index 633e136..76e5cdc 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -48,6 +48,7 @@ with Itypes; use Itypes;
with Layout; use Layout;
with Lib; use Lib;
with Lib.Xref; use Lib.Xref;
+with Mutably_Tagged; use Mutably_Tagged;
with Namet; use Namet;
with Nlists; use Nlists;
with Nmake; use Nmake;
@@ -2162,6 +2163,7 @@ package body Sem_Ch3 is
-- and thus unconstrained. Regular components must be constrained.
if not Is_Definite_Subtype (T)
+ and then not Is_Mutably_Tagged_Type (T)
and then Chars (Id) /= Name_uParent
then
if Is_Class_Wide_Type (T) then
@@ -4802,8 +4804,30 @@ package body Sem_Ch3 is
null;
elsif Is_Class_Wide_Type (T) then
- Error_Msg_N
- ("initialization required in class-wide declaration", N);
+
+ -- Case of a mutably tagged type
+
+ if Is_Mutably_Tagged_Type (T) then
+ Act_T := Class_Wide_Equivalent_Type (T);
+
+ Rewrite (Object_Definition (N),
+ New_Occurrence_Of (Act_T, Loc));
+
+ Insert_After (N,
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Occurrence_Of (Init_Proc (Etype (T)), Loc),
+ Parameter_Associations => New_List (
+ Unchecked_Convert_To
+ (Etype (T), New_Occurrence_Of (Id, Loc)))));
+
+ Freeze_Before (N, Act_T);
+
+ -- Otherwise an initial expression is required
+
+ else
+ Error_Msg_N
+ ("initialization required in class-wide declaration", N);
+ end if;
else
Error_Msg_N
@@ -4900,6 +4924,17 @@ package body Sem_Ch3 is
goto Leave;
end if;
+ -- Rewrite mutably tagged class-wide type declarations to be that
+ -- of the corresponding class-wide equivalent type.
+
+ elsif Is_Mutably_Tagged_Type (T) then
+ Act_T := Class_Wide_Equivalent_Type (T);
+
+ Rewrite (Object_Definition (N),
+ New_Occurrence_Of (Act_T, Loc));
+
+ Freeze_Before (N, Act_T);
+
else
-- Ensure that the generated subtype has a unique external name
-- when the related object is public. This guarantees that the
@@ -6679,7 +6714,11 @@ package body Sem_Ch3 is
-- that all the indexes are unconstrained but we still need to make sure
-- that the element type is constrained.
- if not Is_Definite_Subtype (Element_Type) then
+ if Is_Mutably_Tagged_Type (Element_Type) then
+ Set_Component_Type (T,
+ Class_Wide_Equivalent_Type (Element_Type));
+
+ elsif not Is_Definite_Subtype (Element_Type) then
Error_Msg_N
("unconstrained element type in array declaration",
Subtype_Indication (Component_Def));
@@ -17774,6 +17813,83 @@ package body Sem_Ch3 is
Build_Derived_Type (N, Parent_Type, T, Is_Completion,
Derive_Subps => not Is_Underlying_Record_View (T));
+ -- Check for special mutably tagged type declarations
+
+ if Is_Tagged_Type (Parent_Type)
+ and then not Error_Posted (T)
+ then
+ declare
+ Actions : List_Id;
+ CW_Typ : constant Entity_Id := Class_Wide_Type (T);
+ Root_Class_Typ : constant Entity_Id :=
+ Class_Wide_Type (Root_Type (Parent_Type));
+ begin
+ -- Perform various checks when we are indeed looking at a
+ -- mutably tagged declaration.
+
+ if Present (Root_Class_Typ)
+ and then Is_Mutably_Tagged_Type (Root_Class_Typ)
+ then
+ -- Verify the level of the descendant's declaration is not
+ -- deeper than the root type since this could cause leaking
+ -- of the type.
+
+ if Scope (Root_Class_Typ) /= Scope (T)
+ and then Deepest_Type_Access_Level (Root_Class_Typ)
+ < Deepest_Type_Access_Level (T)
+ then
+ Error_Msg_NE
+ ("descendant of mutably tagged type cannot be deeper than"
+ & " its root", N, Root_Type (T));
+
+ elsif Present (Incomplete_Or_Partial_View (T))
+ and then Is_Tagged_Type (Incomplete_Or_Partial_View (T))
+ then
+ Error_Msg_N
+ ("descendant of mutably tagged type cannot a have partial"
+ & " view which is tagged", N);
+
+ -- Mutably tagged types cannot have discriminants
+
+ elsif Present (Discriminant_Specifications (N)) then
+ Error_Msg_N
+ ("descendant of mutably tagged type cannot have"
+ & " discriminates", N);
+
+ elsif Present (Interfaces (T))
+ and then not Is_Empty_Elmt_List (Interfaces (T))
+ then
+ Error_Msg_N
+ ("descendant of mutably tagged type cannot implement"
+ & " an interface", N);
+
+ -- We have a valid descendant type
+
+ else
+ -- Set inherited attributes
+
+ Set_Has_Size_Clause (CW_Typ);
+ Set_RM_Size (CW_Typ, RM_Size (Root_Class_Typ));
+ Set_Is_Mutably_Tagged_Type (CW_Typ);
+
+ -- Generate a new class-wide equivalent type
+
+ Set_Class_Wide_Equivalent_Type (CW_Typ,
+ Make_CW_Equivalent_Type (CW_Typ, Empty, Actions));
+
+ Insert_List_After_And_Analyze (N, Actions);
+
+ -- Add a Compile_Time_Error sizing check as a hint
+ -- to the backend since we don't know the true size of
+ -- anything at this point.
+
+ Insert_After_And_Analyze (N,
+ Make_CW_Size_Compile_Check (T, Root_Class_Typ));
+ end if;
+ end if;
+ end;
+ end if;
+
-- AI-419: The parent type of an explicitly limited derived type must
-- be a limited type or a limited interface.
diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb
index b59a56c..e75f8df 100644
--- a/gcc/ada/sem_ch4.adb
+++ b/gcc/ada/sem_ch4.adb
@@ -36,6 +36,7 @@ with Exp_Util; use Exp_Util;
with Itypes; use Itypes;
with Lib; use Lib;
with Lib.Xref; use Lib.Xref;
+with Mutably_Tagged; use Mutably_Tagged;
with Namet; use Namet;
with Namet.Sp; use Namet.Sp;
with Nlists; use Nlists;
@@ -623,6 +624,12 @@ package body Sem_Ch4 is
Make_Index_Or_Discriminant_Constraint (Loc,
Constraints => Constr)));
end;
+
+ -- Rewrite the mutably tagged type to a non-class-wide type for
+ -- proper initialization.
+
+ elsif Is_Mutably_Tagged_Type (Type_Id) then
+ Rewrite (E, New_Occurrence_Of (Etype (Type_Id), Loc));
end if;
end if;
@@ -2885,6 +2892,12 @@ package body Sem_Ch4 is
Set_Etype (N, Component_Type (Array_Type));
Check_Implicit_Dereference (N, Etype (N));
+ -- Generate conversion to class-wide type
+
+ if Is_Mutably_Tagged_CW_Equivalent_Type (Etype (N)) then
+ Make_Mutably_Tagged_Conversion (N);
+ end if;
+
if Present (Index) then
Error_Msg_N
("too few subscripts in array reference", First (Exprs));
@@ -4069,6 +4082,17 @@ package body Sem_Ch4 is
Next_Actual (Actual);
Next_Formal (Formal);
+ -- Generate a class-wide type conversion for instances of
+ -- class-wide equivalent types to their corresponding
+ -- mutably tagged type.
+
+ elsif Is_Mutably_Tagged_CW_Equivalent_Type (Etype (Actual))
+ and then Etype (Formal) = Parent_Subtype (Etype (Actual))
+ then
+ Make_Mutably_Tagged_Conversion (Actual);
+ Next_Actual (Actual);
+ Next_Formal (Formal);
+
-- Handle failed type check
else
@@ -5294,6 +5318,11 @@ package body Sem_Ch4 is
Prefix_Type := Implicitly_Designated_Type (Prefix_Type);
end if;
+ -- Handle mutably tagged types
+
+ elsif Is_Class_Wide_Equivalent_Type (Prefix_Type) then
+ Prefix_Type := Parent_Subtype (Prefix_Type);
+
-- If we have an explicit dereference of a remote access-to-class-wide
-- value, then issue an error (see RM-E.2.2(16/1)). However we first
-- have to check for the case of a prefix that is a controlling operand
@@ -5389,7 +5418,6 @@ package body Sem_Ch4 is
Check_Implicit_Dereference (N, Etype (Comp));
elsif Is_Record_Type (Prefix_Type) then
-
-- Find a component with the given name. If the node is a prefixed
-- call, do not examine components whose visibility may be
-- accidental.
@@ -5559,6 +5587,13 @@ package body Sem_Ch4 is
Set_Etype (N, Etype (Comp));
end if;
+ -- Force the generation of a mutably tagged type conversion
+ -- when we encounter a special class-wide equivalent type.
+
+ if Is_Mutably_Tagged_CW_Equivalent_Type (Etype (Name)) then
+ Make_Mutably_Tagged_Conversion (Name, Force => True);
+ end if;
+
Check_Implicit_Dereference (N, Etype (N));
return;
end if;
@@ -6328,6 +6363,30 @@ package body Sem_Ch4 is
("formal parameter cannot be converted to class-wide type when "
& "Extensions_Visible is False", Expr);
end if;
+
+ -- Perform special checking for access to mutably tagged type since they
+ -- are not compatible with interfaces.
+
+ if Is_Access_Type (Typ)
+ and then Is_Access_Type (Etype (Expr))
+ and then not Error_Posted (N)
+ then
+
+ if Is_Mutably_Tagged_Type (Directly_Designated_Type (Typ))
+ and then Is_Interface (Directly_Designated_Type (Etype (Expr)))
+ then
+ Error_Msg_N
+ ("argument of conversion to mutably tagged access type cannot "
+ & "be access to interface", Expr);
+
+ elsif Is_Mutably_Tagged_Type (Directly_Designated_Type (Etype (Expr)))
+ and then Is_Interface (Directly_Designated_Type (Typ))
+ then
+ Error_Msg_N
+ ("argument of conversion to interface access type cannot "
+ & "be access to mutably tagged type", Expr);
+ end if;
+ end if;
end Analyze_Type_Conversion;
----------------------
diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb
index 1e09e57..b92ceb1 100644
--- a/gcc/ada/sem_ch5.adb
+++ b/gcc/ada/sem_ch5.adb
@@ -39,6 +39,7 @@ with Freeze; use Freeze;
with Ghost; use Ghost;
with Lib; use Lib;
with Lib.Xref; use Lib.Xref;
+with Mutably_Tagged; use Mutably_Tagged;
with Namet; use Namet;
with Nlists; use Nlists;
with Nmake; use Nmake;
@@ -676,11 +677,17 @@ package body Sem_Ch5 is
Set_Assignment_Type (Lhs, T1);
- -- If the target of the assignment is an entity of a mutable type and
- -- the expression is a conditional expression, its alternatives can be
- -- of different subtypes of the nominal type of the LHS, so they must be
- -- resolved with the base type, given that their subtype may differ from
- -- that of the target mutable object.
+ -- When analyzing a mutably tagged class-wide equivalent type pretend we
+ -- are actually looking at the mutably tagged type itself for proper
+ -- analysis.
+
+ T1 := Get_Corresponding_Mutably_Tagged_Type_If_Present (T1);
+
+ -- If the target of the assignment is an entity of a mutably tagged type
+ -- and the expression is a conditional expression, its alternatives can
+ -- be of different subtypes of the nominal type of the LHS, so they must
+ -- be resolved with the base type, given that their subtype may differ
+ -- from that of the target mutable object.
if Is_Entity_Name (Lhs)
and then Is_Assignable (Entity (Lhs))
@@ -2500,6 +2507,13 @@ package body Sem_Ch5 is
Error_Msg_N
("iterable name cannot be a discriminant-dependent "
& "component of a mutable object", N);
+
+ elsif Depends_On_Mutably_Tagged_Ext_Comp
+ (Original_Node (Iter_Name))
+ then
+ Error_Msg_N
+ ("iterable name cannot depend on a mutably tagged component",
+ N);
end if;
Check_Subtype_Definition (Component_Type (Typ));
@@ -2630,6 +2644,13 @@ package body Sem_Ch5 is
Error_Msg_N
("container cannot be a discriminant-dependent "
& "component of a mutable object", N);
+
+ elsif Depends_On_Mutably_Tagged_Ext_Comp
+ (Orig_Iter_Name)
+ then
+ Error_Msg_N
+ ("container cannot depend on a mutably tagged "
+ & "component", N);
end if;
end if;
end;
@@ -2716,6 +2737,11 @@ package body Sem_Ch5 is
Error_Msg_N
("container cannot be a discriminant-dependent "
& "component of a mutable object", N);
+
+ elsif Depends_On_Mutably_Tagged_Ext_Comp (Obj) then
+ Error_Msg_N
+ ("container cannot depend on a mutably tagged"
+ & " component", N);
end if;
end;
end if;
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index 3252af7..e97afda 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -9182,9 +9182,15 @@ package body Sem_Ch6 is
-- If the type does not have a completion yet, treat as prior to
-- Ada 2012 for consistency.
- if Has_Discriminants (Formal_Type)
+ -- Note that we need also to handle mutably tagged types in the
+ -- same way as discriminated types since they can be constrained
+ -- or unconstrained as well.
+
+ if (Has_Discriminants (Formal_Type)
+ or else Is_Mutably_Tagged_Type (Formal_Type))
and then not Is_Constrained (Formal_Type)
- and then Is_Definite_Subtype (Formal_Type)
+ and then (Is_Definite_Subtype (Formal_Type)
+ or else Is_Mutably_Tagged_Type (Formal_Type))
and then (Ada_Version < Ada_2012
or else No (Underlying_Type (Formal_Type))
or else not
diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb
index 125ccc6..d2752af 100644
--- a/gcc/ada/sem_ch8.adb
+++ b/gcc/ada/sem_ch8.adb
@@ -39,6 +39,7 @@ with Lib; use Lib;
with Lib.Load; use Lib.Load;
with Lib.Xref; use Lib.Xref;
with Local_Restrict;
+with Mutably_Tagged; use Mutably_Tagged;
with Namet; use Namet;
with Namet.Sp; use Namet.Sp;
with Nlists; use Nlists;
@@ -1511,6 +1512,10 @@ package body Sem_Ch8 is
if Is_Dependent_Component_Of_Mutable_Object (Nam) then
Error_Msg_N
("illegal renaming of discriminant-dependent component", Nam);
+ elsif Depends_On_Mutably_Tagged_Ext_Comp (Nam) then
+ Error_Msg_N
+ ("illegal renaming of mutably tagged dependent component",
+ Nam);
end if;
-- If the renaming comes from source and the renamed object is a
@@ -2094,6 +2099,10 @@ package body Sem_Ch8 is
Error_Msg_N
("illegal renaming of discriminant-dependent component",
Nam);
+ elsif Depends_On_Mutably_Tagged_Ext_Comp (Nam) then
+ Error_Msg_N
+ ("illegal renaming of mutably tagged dependent component",
+ Nam);
end if;
else
Error_Msg_N ("expect object name in renaming", Nam);
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index d2eca7c..a0dd1f7 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -47,6 +47,7 @@ with Itypes; use Itypes;
with Lib; use Lib;
with Lib.Xref; use Lib.Xref;
with Local_Restrict;
+with Mutably_Tagged; use Mutably_Tagged;
with Namet; use Namet;
with Nmake; use Nmake;
with Nlists; use Nlists;
@@ -5034,12 +5035,21 @@ package body Sem_Res is
-- Skip this check on helpers and indirect-call wrappers built to
-- support class-wide preconditions.
+ -- We make special exception here for mutably tagged types and
+ -- related calls to their initialization procedures.
+
if (Is_Class_Wide_Type (A_Typ) or else Is_Dynamically_Tagged (A))
and then not Is_Class_Wide_Type (F_Typ)
and then not Is_Controlling_Formal (F)
and then not In_Instance
and then (not Is_Subprogram (Nam)
or else No (Class_Preconditions_Subprogram (Nam)))
+
+ -- Ignore mutably tagged types and their use in calls to init
+ -- procs.
+
+ and then not Is_Mutably_Tagged_CW_Equivalent_Type (A_Typ)
+ and then not Is_Init_Proc (Nam)
then
Error_Msg_N ("class-wide argument not allowed here!", A);
@@ -14069,6 +14079,13 @@ package body Sem_Res is
end;
end if;
+ -- When we encounter a class-wide equivalent type used to represent
+ -- a fully sized mutably tagged type, pretend we are actually looking
+ -- at the class-wide mutably tagged type instead.
+
+ Opnd_Type :=
+ Get_Corresponding_Mutably_Tagged_Type_If_Present (Opnd_Type);
+
-- Deal with conversion of integer type to address if the pragma
-- Allow_Integer_Address is in effect. We convert the conversion to
-- an unchecked conversion in this case and we are all done.
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 1705b58..b1d47f2 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -38,6 +38,7 @@ with Freeze; use Freeze;
with Itypes; use Itypes;
with Lib; use Lib;
with Lib.Xref; use Lib.Xref;
+with Mutably_Tagged; use Mutably_Tagged;
with Namet.Sp; use Namet.Sp;
with Nlists; use Nlists;
with Nmake; use Nmake;
@@ -17166,6 +17167,13 @@ package body Sem_Util is
-- Record types
elsif Is_Record_Type (Typ) then
+ -- Mutably tagged types get default initialized to their parent
+ -- subtype's default values.
+
+ if Is_Mutably_Tagged_CW_Equivalent_Type (Typ) then
+ return True;
+ end if;
+
if Has_Defaulted_Discriminants (Typ)
and then Is_Fully_Initialized_Variant (Typ)
then
@@ -22684,6 +22692,11 @@ package body Sem_Util is
then
return True;
+ -- Mutably tagged types require default initialization
+
+ elsif Is_Mutably_Tagged_CW_Equivalent_Type (Typ) then
+ return True;
+
-- If Initialize/Normalize_Scalars is in effect, string objects also
-- need initialization, unless they are created in the course of
-- expanding an aggregate (since in the latter case they will be