Commit d2d3604c by Thomas Quinot Committed by Arnaud Charlet

exp_ch3.adb (Check_Attr): New subprogram.

2005-03-17  Thomas Quinot  <quinot@adacore.com>

	* exp_ch3.adb (Check_Attr): New subprogram.
	(Check_Stream_Attribute): Move the code for 13.13.2(9/1) enforcement
	into a new Check_Attr subprogram, in order to provide a more
	explanatory error message (including the name of the missing attribute).
	(Stream_Operation_OK): Renamed from Stream_Operations_OK. This
	subprogram determines whether a default implementation exists for a
	given stream attribute.
	(Make_Predefined_Primitive_Specs, Predefined_Primitive_Bodies):
	Determine whether to generate a default implementation for each stream
	attribute separately, as this depends on the specific attribute.

	* exp_strm.adb (Make_Field_Attribute): For the case of an illegal
	limited extension where a stream attribute is missing for a limited
	component (which will have been flagged in Exp_Ch3.Sem_Attr), do not
	generate a bogus reference to the missing attribute to prevent
	cascaded errors. Instead, generate a null statement.

	* sem_attr.adb (Check_Stream_Attribute): A stream attribute is
	available for a limited type if it has been specified for an ancestor
	of the type.

From-SVN: r96666
parent 2b599687
...@@ -285,10 +285,14 @@ package body Exp_Ch3 is ...@@ -285,10 +285,14 @@ package body Exp_Ch3 is
-- Freeze entities of all predefined primitive operations. This is needed -- Freeze entities of all predefined primitive operations. This is needed
-- because the bodies of these operations do not normally do any freezeing. -- because the bodies of these operations do not normally do any freezeing.
function Stream_Operations_OK (Typ : Entity_Id) return Boolean; function Stream_Operation_OK
-- Check whether stream operations must be emitted for a given type. (Typ : Entity_Id;
-- Various restrictions prevent the generation of these operations, as Operation : TSS_Name_Type) return Boolean;
-- a useful optimization or for certification purposes. -- Check whether the named stream operation must be emitted for a given
-- type. The rules for inheritance of stream attributes by type extensions
-- are enforced by this function. Furthermore, various restrictions prevent
-- the generation of these operations, as a useful optimization or for
-- certification purposes.
-------------------------- --------------------------
-- Adjust_Discriminants -- -- Adjust_Discriminants --
...@@ -3012,23 +3016,32 @@ package body Exp_Ch3 is ...@@ -3012,23 +3016,32 @@ package body Exp_Ch3 is
Par_Read : constant Boolean := Present (TSS (Par, TSS_Stream_Read)); Par_Read : constant Boolean := Present (TSS (Par, TSS_Stream_Read));
Par_Write : constant Boolean := Present (TSS (Par, TSS_Stream_Write)); Par_Write : constant Boolean := Present (TSS (Par, TSS_Stream_Write));
procedure Check_Attr (Nam : Name_Id; TSS_Nam : TSS_Name_Type);
-- Check that Comp has a user-specified Nam stream attribute
procedure Check_Attr (Nam : Name_Id; TSS_Nam : TSS_Name_Type) is
begin
if No (TSS (Base_Type (Etype (Comp)), TSS_Nam)) then
Error_Msg_Name_1 := Nam;
Error_Msg_N
("|component& in limited extension must have% attribute", Comp);
end if;
end Check_Attr;
begin begin
if Par_Read or else Par_Write then if Par_Read or else Par_Write then
Comp := First_Component (Typ); Comp := First_Component (Typ);
while Present (Comp) loop while Present (Comp) loop
if Comes_From_Source (Comp) if Comes_From_Source (Comp)
and then Original_Record_Component (Comp) = Comp and then Original_Record_Component (Comp) = Comp
and then Is_Limited_Type (Etype (Comp)) and then Is_Limited_Type (Etype (Comp))
then then
if (Par_Read and then if Par_Read then
No (TSS (Base_Type (Etype (Comp)), TSS_Stream_Read))) Check_Attr (Name_Read, TSS_Stream_Read);
or else end if;
(Par_Write and then
No (TSS (Base_Type (Etype (Comp)), TSS_Stream_Write))) if Par_Write then
then Check_Attr (Name_Write, TSS_Stream_Write);
Error_Msg_N
("|component must have Stream attribute",
Parent (Comp));
end if; end if;
end if; end if;
...@@ -5543,22 +5556,24 @@ package body Exp_Ch3 is ...@@ -5543,22 +5556,24 @@ package body Exp_Ch3 is
Ret_Type => Standard_Integer)); Ret_Type => Standard_Integer));
-- Specs for dispatching stream attributes. We skip these for limited -- Specs for dispatching stream attributes.
-- types, since there is no question of dispatching in the limited case.
declare
-- We also skip these operations if dispatching is not available Stream_Op_TSS_Names :
-- or if streams are not available (since what's the point?) constant array (Integer range <>) of TSS_Name_Type :=
(TSS_Stream_Read,
if Stream_Operations_OK (Tag_Typ) then TSS_Stream_Write,
Append_To (Res, TSS_Stream_Input,
Predef_Stream_Attr_Spec (Loc, Tag_Typ, TSS_Stream_Read)); TSS_Stream_Output);
Append_To (Res, begin
Predef_Stream_Attr_Spec (Loc, Tag_Typ, TSS_Stream_Write)); for Op in Stream_Op_TSS_Names'Range loop
Append_To (Res, if Stream_Operation_OK (Tag_Typ, Stream_Op_TSS_Names (Op)) then
Predef_Stream_Attr_Spec (Loc, Tag_Typ, TSS_Stream_Input)); Append_To (Res,
Append_To (Res, Predef_Stream_Attr_Spec (Loc, Tag_Typ,
Predef_Stream_Attr_Spec (Loc, Tag_Typ, TSS_Stream_Output)); Stream_Op_TSS_Names (Op)));
end if; end if;
end loop;
end;
-- Spec of "=" if expanded if the type is not limited and if a -- Spec of "=" if expanded if the type is not limited and if a
-- user defined "=" was not already declared for the non-full -- user defined "=" was not already declared for the non-full
...@@ -6004,32 +6019,38 @@ package body Exp_Ch3 is ...@@ -6004,32 +6019,38 @@ package body Exp_Ch3 is
-- non-limited types (in the limited case there is no dispatching). -- non-limited types (in the limited case there is no dispatching).
-- We also skip them if dispatching or finalization are not available. -- We also skip them if dispatching or finalization are not available.
if Stream_Operations_OK (Tag_Typ) then if Stream_Operation_OK (Tag_Typ, TSS_Stream_Read)
if No (TSS (Tag_Typ, TSS_Stream_Read)) then and then No (TSS (Tag_Typ, TSS_Stream_Read))
Build_Record_Read_Procedure (Loc, Tag_Typ, Decl, Ent); then
Append_To (Res, Decl); Build_Record_Read_Procedure (Loc, Tag_Typ, Decl, Ent);
end if; Append_To (Res, Decl);
end if;
if No (TSS (Tag_Typ, TSS_Stream_Write)) then if Stream_Operation_OK (Tag_Typ, TSS_Stream_Write)
Build_Record_Write_Procedure (Loc, Tag_Typ, Decl, Ent); and then No (TSS (Tag_Typ, TSS_Stream_Write))
Append_To (Res, Decl); then
end if; Build_Record_Write_Procedure (Loc, Tag_Typ, Decl, Ent);
Append_To (Res, Decl);
end if;
-- Skip bodies of _Input and _Output for the abstract case, since -- Skip bodies of _Input and _Output for the abstract case, since
-- the corresponding specs are abstract (see Predef_Spec_Or_Body) -- the corresponding specs are abstract (see Predef_Spec_Or_Body)
if not Is_Abstract (Tag_Typ) then if not Is_Abstract (Tag_Typ) then
if No (TSS (Tag_Typ, TSS_Stream_Input)) then if Stream_Operation_OK (Tag_Typ, TSS_Stream_Input)
Build_Record_Or_Elementary_Input_Function and then No (TSS (Tag_Typ, TSS_Stream_Input))
(Loc, Tag_Typ, Decl, Ent); then
Append_To (Res, Decl); Build_Record_Or_Elementary_Input_Function
end if; (Loc, Tag_Typ, Decl, Ent);
Append_To (Res, Decl);
end if;
if No (TSS (Tag_Typ, TSS_Stream_Output)) then if Stream_Operation_OK (Tag_Typ, TSS_Stream_Output)
Build_Record_Or_Elementary_Output_Procedure and then No (TSS (Tag_Typ, TSS_Stream_Output))
(Loc, Tag_Typ, Decl, Ent); then
Append_To (Res, Decl); Build_Record_Or_Elementary_Output_Procedure
end if; (Loc, Tag_Typ, Decl, Ent);
Append_To (Res, Decl);
end if; end if;
end if; end if;
...@@ -6216,17 +6237,35 @@ package body Exp_Ch3 is ...@@ -6216,17 +6237,35 @@ package body Exp_Ch3 is
return Res; return Res;
end Predefined_Primitive_Freeze; end Predefined_Primitive_Freeze;
-------------------------- -------------------------
-- Stream_Operations_OK -- -- Stream_Operation_OK --
-------------------------- -------------------------
function Stream_Operation_OK
(Typ : Entity_Id;
Operation : TSS_Name_Type) return Boolean
is
Has_Inheritable_Stream_Attribute : Boolean := False;
function Stream_Operations_OK (Typ : Entity_Id) return Boolean is
begin begin
if Is_Limited_Type (Typ)
and then Is_Tagged_Type (Typ)
and then Is_Derived_Type (Typ)
then
-- Special case of a limited type extension: a default implementation
-- of the stream attributes Read and Write exists if the attribute
-- has been specified for an ancestor type.
Has_Inheritable_Stream_Attribute :=
Present (Find_Inherited_TSS (Base_Type (Etype (Typ)), Operation));
end if;
return return
not Is_Limited_Type (Typ) not (Is_Limited_Type (Typ)
and then not Has_Inheritable_Stream_Attribute)
and then RTE_Available (RE_Tag) and then RTE_Available (RE_Tag)
and then RTE_Available (RE_Root_Stream_Type) and then RTE_Available (RE_Root_Stream_Type)
and then not Restriction_Active (No_Dispatch) and then not Restriction_Active (No_Dispatch)
and then not Restriction_Active (No_Streams); and then not Restriction_Active (No_Streams);
end Stream_Operations_OK; end Stream_Operation_OK;
end Exp_Ch3; end Exp_Ch3;
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
with Atree; use Atree; with Atree; use Atree;
with Einfo; use Einfo; with Einfo; use Einfo;
with Exp_Tss; use Exp_Tss;
with Namet; use Namet; with Namet; use Namet;
with Nlists; use Nlists; with Nlists; use Nlists;
with Nmake; use Nmake; with Nmake; use Nmake;
...@@ -36,7 +37,6 @@ with Snames; use Snames; ...@@ -36,7 +37,6 @@ with Snames; use Snames;
with Stand; use Stand; with Stand; use Stand;
with Tbuild; use Tbuild; with Tbuild; use Tbuild;
with Ttypes; use Ttypes; with Ttypes; use Ttypes;
with Exp_Tss; use Exp_Tss;
with Uintp; use Uintp; with Uintp; use Uintp;
package body Exp_Strm is package body Exp_Strm is
...@@ -1173,6 +1173,11 @@ package body Exp_Strm is ...@@ -1173,6 +1173,11 @@ package body Exp_Strm is
Stms : List_Id; Stms : List_Id;
Typt : Entity_Id; Typt : Entity_Id;
In_Limited_Extension : Boolean := False;
-- Set to True while processing the record extension definition
-- for an extension of a limited type (for which an ancestor type
-- has an explicit Nam attribute definition).
function Make_Component_List_Attributes (CL : Node_Id) return List_Id; function Make_Component_List_Attributes (CL : Node_Id) return List_Id;
-- Returns a sequence of attributes to process the components that -- Returns a sequence of attributes to process the components that
-- are referenced in the given component list. -- are referenced in the given component list.
...@@ -1254,7 +1259,29 @@ package body Exp_Strm is ...@@ -1254,7 +1259,29 @@ package body Exp_Strm is
-------------------------- --------------------------
function Make_Field_Attribute (C : Entity_Id) return Node_Id is function Make_Field_Attribute (C : Entity_Id) return Node_Id is
Field_Typ : constant Entity_Id := Stream_Base_Type (Etype (C));
TSS_Names : constant array (Name_Input .. Name_Write) of
TSS_Name_Type :=
(Name_Read => TSS_Stream_Read,
Name_Write => TSS_Stream_Write,
Name_Input => TSS_Stream_Input,
Name_Output => TSS_Stream_Output,
others => TSS_Null);
pragma Assert (TSS_Names (Nam) /= TSS_Null);
begin begin
if In_Limited_Extension
and then Is_Limited_Type (Field_Typ)
and then No (Find_Inherited_TSS (Field_Typ, TSS_Names (Nam)))
then
-- The declaration is illegal per 13.13.2(9/1), and this is
-- enforced in Exp_Ch3.Check_Stream_Attributes. Keep the
-- caller happy by returning a null statement.
return Make_Null_Statement (Loc);
end if;
return return
Make_Attribute_Reference (Loc, Make_Attribute_Reference (Loc,
Prefix => Prefix =>
...@@ -1331,6 +1358,10 @@ package body Exp_Strm is ...@@ -1331,6 +1358,10 @@ package body Exp_Strm is
if Nkind (Rdef) = N_Derived_Type_Definition then if Nkind (Rdef) = N_Derived_Type_Definition then
Rdef := Record_Extension_Part (Rdef); Rdef := Record_Extension_Part (Rdef);
if Is_Limited_Type (Typt) then
In_Limited_Extension := True;
end if;
end if; end if;
if Present (Component_List (Rdef)) then if Present (Component_List (Rdef)) then
......
...@@ -1244,12 +1244,14 @@ package body Sem_Attr is ...@@ -1244,12 +1244,14 @@ package body Sem_Attr is
Btyp := Implementation_Base_Type (P_Type); Btyp := Implementation_Base_Type (P_Type);
-- Stream attributes not allowed on limited types unless the -- Stream attributes not allowed on limited types unless the
-- stream attribute was generated by the expander (in which -- attribute reference was generated by the expander (in which
-- case the underlying type will be used, as described in Sinfo). -- case the underlying type will be used, as described in Sinfo),
-- or the attribute was specified explicitly for the type itself
-- or one of its ancestors.
if Is_Limited_Type (P_Type) if Is_Limited_Type (P_Type)
and then Comes_From_Source (N) and then Comes_From_Source (N)
and then not Present (TSS (Btyp, Nam)) and then not Present (Find_Inherited_TSS (Btyp, Nam))
and then not Has_Rep_Pragma (Btyp, Name_Stream_Convert) and then not Has_Rep_Pragma (Btyp, Name_Stream_Convert)
then then
Error_Msg_Name_1 := Aname; Error_Msg_Name_1 := Aname;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment