aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/sem_ch13.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/sem_ch13.adb')
-rw-r--r--gcc/ada/sem_ch13.adb308
1 files changed, 302 insertions, 6 deletions
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index bdb2b6a..bd3010c 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -186,6 +186,12 @@ package body Sem_Ch13 is
-- We can't allow this, otherwise we have predicate-static applying to a
-- larger class than static expressions, which was never intended.
+ procedure New_Put_Image_Subprogram
+ (N : Node_Id;
+ Ent : Entity_Id;
+ Subp : Entity_Id);
+ -- Similar to New_Stream_Subprogram, but for the Put_Image attribute
+
procedure New_Stream_Subprogram
(N : Node_Id;
Ent : Entity_Id;
@@ -2227,6 +2233,7 @@ package body Sem_Ch13 is
| Aspect_Machine_Radix
| Aspect_Object_Size
| Aspect_Output
+ | Aspect_Put_Image
| Aspect_Read
| Aspect_Scalar_Storage_Order
| Aspect_Simple_Storage_Pool
@@ -4149,6 +4156,8 @@ package body Sem_Ch13 is
-- Storage_Size for derived task types, but that is also clearly
-- unintentional.
+ procedure Analyze_Put_Image_TSS_Definition;
+
procedure Analyze_Stream_TSS_Definition (TSS_Nam : TSS_Name_Type);
-- Common processing for 'Read, 'Write, 'Input and 'Output attribute
-- definition clauses.
@@ -4172,6 +4181,152 @@ package body Sem_Ch13 is
-- Common legality check for the previous two
-----------------------------------
+ -- Analyze_Put_Image_TSS_Definition --
+ -----------------------------------
+
+ procedure Analyze_Put_Image_TSS_Definition is
+ Subp : Entity_Id := Empty;
+ I : Interp_Index;
+ It : Interp;
+ Pnam : Entity_Id;
+
+ function Has_Good_Profile
+ (Subp : Entity_Id;
+ Report : Boolean := False) return Boolean;
+ -- Return true if the entity is a subprogram with an appropriate
+ -- profile for the attribute being defined. If result is False and
+ -- Report is True, function emits appropriate error.
+
+ ----------------------
+ -- Has_Good_Profile --
+ ----------------------
+
+ function Has_Good_Profile
+ (Subp : Entity_Id;
+ Report : Boolean := False) return Boolean
+ is
+ F : Entity_Id;
+ Typ : Entity_Id;
+
+ begin
+ if Ekind (Subp) /= E_Procedure then
+ return False;
+ end if;
+
+ F := First_Formal (Subp);
+
+ if No (F) or else Etype (F) /= Class_Wide_Type (RTE (RE_Sink)) then
+ return False;
+ end if;
+
+ Next_Formal (F);
+
+ if Parameter_Mode (F) /= E_In_Parameter then
+ return False;
+ end if;
+
+ Typ := Etype (F);
+
+ -- Verify that the prefix of the attribute and the local name for
+ -- the type of the formal match.
+
+ if Typ /= Ent then
+ return False;
+ end if;
+
+ if Present (Next_Formal (F)) then
+ return False;
+
+ elsif not Is_Scalar_Type (Typ)
+ and then not Is_First_Subtype (Typ)
+ then
+ if Report and not Is_First_Subtype (Typ) then
+ Error_Msg_N
+ ("subtype of formal in Put_Image operation must be a "
+ & "first subtype", Parameter_Type (Parent (F)));
+ end if;
+
+ return False;
+
+ else
+ return True;
+ end if;
+ end Has_Good_Profile;
+
+ -- Start of processing for Analyze_Put_Image_TSS_Definition
+
+ begin
+ if not Is_Type (U_Ent) then
+ Error_Msg_N ("local name must be a subtype", Nam);
+ return;
+
+ elsif not Is_First_Subtype (U_Ent) then
+ Error_Msg_N ("local name must be a first subtype", Nam);
+ return;
+ end if;
+
+ Pnam := TSS (Base_Type (U_Ent), TSS_Put_Image);
+
+ -- If Pnam is present, it can be either inherited from an ancestor
+ -- type (in which case it is legal to redefine it for this type), or
+ -- be a previous definition of the attribute for the same type (in
+ -- which case it is illegal).
+
+ -- In the first case, it will have been analyzed already, and we can
+ -- check that its profile does not match the expected profile for the
+ -- Put_Image attribute of U_Ent. In the second case, either Pnam has
+ -- been analyzed (and has the expected profile), or it has not been
+ -- analyzed yet (case of a type that has not been frozen yet and for
+ -- which Put_Image has been set using Set_TSS).
+
+ if Present (Pnam)
+ and then (No (First_Entity (Pnam)) or else Has_Good_Profile (Pnam))
+ then
+ Error_Msg_Sloc := Sloc (Pnam);
+ Error_Msg_Name_1 := Attr;
+ Error_Msg_N ("% attribute already defined #", Nam);
+ return;
+ end if;
+
+ Analyze (Expr);
+
+ if Is_Entity_Name (Expr) then
+ if not Is_Overloaded (Expr) then
+ if Has_Good_Profile (Entity (Expr), Report => True) then
+ Subp := Entity (Expr);
+ end if;
+
+ else
+ Get_First_Interp (Expr, I, It);
+ while Present (It.Nam) loop
+ if Has_Good_Profile (It.Nam) then
+ Subp := It.Nam;
+ exit;
+ end if;
+
+ Get_Next_Interp (I, It);
+ end loop;
+ end if;
+ end if;
+
+ if Present (Subp) then
+ if Is_Abstract_Subprogram (Subp) then
+ Error_Msg_N ("Put_Image subprogram must not be abstract", Expr);
+ return;
+ end if;
+
+ Set_Entity (Expr, Subp);
+ Set_Etype (Expr, Etype (Subp));
+
+ New_Put_Image_Subprogram (N, U_Ent, Subp);
+
+ else
+ Error_Msg_Name_1 := Attr;
+ Error_Msg_N ("incorrect expression for% attribute", Expr);
+ end if;
+ end Analyze_Put_Image_TSS_Definition;
+
+ -----------------------------------
-- Analyze_Stream_TSS_Definition --
-----------------------------------
@@ -4891,6 +5046,7 @@ package body Sem_Ch13 is
when Attribute_External_Tag
| Attribute_Input
| Attribute_Output
+ | Attribute_Put_Image
| Attribute_Read
| Attribute_Simple_Storage_Pool
| Attribute_Storage_Pool
@@ -5892,6 +6048,13 @@ package body Sem_Ch13 is
("attribute& cannot be set with definition clause", N);
end if;
+ ---------------
+ -- Put_Image --
+ ---------------
+
+ when Attribute_Put_Image =>
+ Analyze_Put_Image_TSS_Definition;
+
----------
-- Read --
----------
@@ -9299,16 +9462,16 @@ package body Sem_Ch13 is
elsif A_Id = Aspect_Synchronization then
return;
- -- Case of stream attributes, just have to compare entities. However,
- -- the expression is just a name (possibly overloaded), and there may
- -- be stream operations declared for unrelated types, so we just need
- -- to verify that one of these interpretations is the one available at
- -- at the freeze point.
+ -- Case of stream attributes and Put_Image, just have to compare
+ -- entities. However, the expression is just a possibly-overloaded
+ -- name, so we need to verify that one of these interpretations is
+ -- the one available at at the freeze point.
elsif A_Id = Aspect_Input or else
A_Id = Aspect_Output or else
A_Id = Aspect_Read or else
- A_Id = Aspect_Write
+ A_Id = Aspect_Write or else
+ A_Id = Aspect_Put_Image
then
Analyze (End_Decl_Expr);
Check_Overloaded_Name;
@@ -9564,6 +9727,7 @@ package body Sem_Ch13 is
when Aspect_Input
| Aspect_Output
+ | Aspect_Put_Image
| Aspect_Read
| Aspect_Suppress
| Aspect_Unsuppress
@@ -12515,6 +12679,138 @@ package body Sem_Ch13 is
end Minimum_Size;
---------------------------
+ -- New_Put_Image_Subprogram --
+ ---------------------------
+
+ procedure New_Put_Image_Subprogram
+ (N : Node_Id;
+ Ent : Entity_Id;
+ Subp : Entity_Id)
+ is
+ Loc : constant Source_Ptr := Sloc (N);
+ Sname : constant Name_Id :=
+ Make_TSS_Name (Base_Type (Ent), TSS_Put_Image);
+ Subp_Id : Entity_Id;
+ Subp_Decl : Node_Id;
+ F : Entity_Id;
+ Etyp : Entity_Id;
+
+ Defer_Declaration : constant Boolean :=
+ Is_Tagged_Type (Ent) or else Is_Private_Type (Ent);
+ -- For a tagged type, there is a declaration at the freeze point, and
+ -- we must generate only a completion of this declaration. We do the
+ -- same for private types, because the full view might be tagged.
+ -- Otherwise we generate a declaration at the point of the attribute
+ -- definition clause. If the attribute definition comes from an aspect
+ -- specification the declaration is part of the freeze actions of the
+ -- type.
+
+ function Build_Spec return Node_Id;
+ -- Used for declaration and renaming declaration, so that this is
+ -- treated as a renaming_as_body.
+
+ ----------------
+ -- Build_Spec --
+ ----------------
+
+ function Build_Spec return Node_Id is
+ Formals : List_Id;
+ Spec : Node_Id;
+ T_Ref : constant Node_Id := New_Occurrence_Of (Etyp, Loc);
+
+ begin
+ Subp_Id := Make_Defining_Identifier (Loc, Sname);
+
+ -- S : Sink'Class
+
+ Formals := New_List (
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc, Name_S),
+ In_Present => True,
+ Out_Present => True,
+ Parameter_Type =>
+ New_Occurrence_Of (Etype (F), Loc)));
+
+ -- V : T
+
+ Append_To (Formals,
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
+ Parameter_Type => T_Ref));
+
+ Spec :=
+ Make_Procedure_Specification (Loc,
+ Defining_Unit_Name => Subp_Id,
+ Parameter_Specifications => Formals);
+
+ return Spec;
+ end Build_Spec;
+
+ -- Start of processing for New_Put_Image_Subprogram
+
+ begin
+ F := First_Formal (Subp);
+
+ Etyp := Etype (Next_Formal (F));
+
+ -- Prepare subprogram declaration and insert it as an action on the
+ -- clause node. The visibility for this entity is used to test for
+ -- visibility of the attribute definition clause (in the sense of
+ -- 8.3(23) as amended by AI-195).
+
+ if not Defer_Declaration then
+ Subp_Decl :=
+ Make_Subprogram_Declaration (Loc,
+ Specification => Build_Spec);
+
+ -- For a tagged type, there is always a visible declaration for the
+ -- Put_Image TSS (it is a predefined primitive operation), and the
+ -- completion of this declaration occurs at the freeze point, which is
+ -- not always visible at places where the attribute definition clause is
+ -- visible. So, we create a dummy entity here for the purpose of
+ -- tracking the visibility of the attribute definition clause itself.
+
+ else
+ Subp_Id :=
+ Make_Defining_Identifier (Loc, New_External_Name (Sname, 'V'));
+ Subp_Decl :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Subp_Id,
+ Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc));
+ end if;
+
+ if not Defer_Declaration
+ and then From_Aspect_Specification (N)
+ and then Has_Delayed_Freeze (Ent)
+ then
+ Append_Freeze_Action (Ent, Subp_Decl);
+
+ else
+ Insert_Action (N, Subp_Decl);
+ Set_Entity (N, Subp_Id);
+ end if;
+
+ Subp_Decl :=
+ Make_Subprogram_Renaming_Declaration (Loc,
+ Specification => Build_Spec,
+ Name => New_Occurrence_Of (Subp, Loc));
+
+ if Defer_Declaration then
+ Set_TSS (Base_Type (Ent), Subp_Id);
+
+ else
+ if From_Aspect_Specification (N) then
+ Append_Freeze_Action (Ent, Subp_Decl);
+ else
+ Insert_Action (N, Subp_Decl);
+ end if;
+
+ Copy_TSS (Subp_Id, Base_Type (Ent));
+ end if;
+ end New_Put_Image_Subprogram;
+
+ ---------------------------
-- New_Stream_Subprogram --
---------------------------