function Find_Aspect
(Id : Entity_Id;
A : Aspect_Id;
- Class_Present : Boolean := False) return Node_Id
+ Class_Present : Boolean := False;
+ Or_Rep_Item : Boolean := False) return Node_Id
is
- Decl : Node_Id;
- Item : Node_Id;
- Owner : Entity_Id;
- Spec : Node_Id;
-
+ Decl : Node_Id;
+ Item : Node_Id;
+ Owner : Entity_Id;
+ Spec : Node_Id;
+ Alternative_Rep_Item : Node_Id := Empty;
begin
Owner := Id;
and then Class_Present = Sinfo.Nodes.Class_Present (Item)
then
return Item;
+
+ -- We could do something similar here for an N_Pragma node
+ -- when Get_Aspect_Id (Pragma_Name (Item)) = A, but let's
+ -- wait for a demonstrated need.
+
+ elsif Or_Rep_Item
+ and then not Class_Present
+ and then Nkind (Item) = N_Attribute_Definition_Clause
+ and then Get_Aspect_Id (Chars (Item)) = A
+ then
+ -- Remember this candidate in case we don't find anything better
+ Alternative_Rep_Item := Item;
end if;
Next_Rep_Item (Item);
end if;
-- The entity does not carry any aspects or the desired aspect was not
- -- found.
+ -- found. We have no N_Aspect_Specification node to return, but
+ -- Alternative_Rep_Item may have been set (if Or_Rep_Item is True).
- return Empty;
+ return Alternative_Rep_Item;
end Find_Aspect;
--------------------------
function Find_Aspect (Id : Entity_Id;
A : Aspect_Id;
- Class_Present : Boolean := False) return Node_Id;
+ Class_Present : Boolean := False;
+ Or_Rep_Item : Boolean := False) return Node_Id;
-- Find the aspect specification of aspect A (or A'Class if Class_Present)
-- associated with entity I.
- -- Return Empty if Id does not have the requested aspect.
+ -- If found, then return the aspect specification.
+ -- If not found and Or_Rep_Item is true, then look for a representation
+ -- item (as opposed to an N_Aspect_Specification node) which specifies
+ -- the given aspect; if found, then return the representation item.
+ -- [Currently only N_Attribute_Definition_Clause representation items
+ -- are checked for, but support for detecting N_Pragma representation
+ -- items could easily be added in the future if there is a need.]
+ -- Otherwise, return Empty.
function Find_Value_Of_Aspect
(Id : Entity_Id;
if No (Pname) then
-- If Put_Image is disabled, call the "unknown" version
- if not Enable_Put_Image (U_Type) then
+ if not Put_Image_Enabled (U_Type) then
Rewrite (N, Build_Unknown_Put_Image_Call (N));
Analyze (N);
return;
-- ????Need Find_Optional_Prim_Op instead of Find_Prim_Op,
-- because we might be deriving from a predefined type, which
- -- currently has Enable_Put_Image False.
+ -- currently has Put_Image_Enabled False.
if No (Pname) then
Rewrite (N, Build_Unknown_Put_Image_Call (N));
begin
if Ada_Version < Ada_2022
- or else not Enable_Put_Image (Btyp)
+ or else not Put_Image_Enabled (Btyp)
then
-- generate a very simple Put_Image implementation
Parameter_Associations => New_List
(Make_Identifier (Loc, Name_S),
Make_String_Literal (Loc, "(NULL RECORD)"))));
+
+ elsif Is_Derived_Type (Btyp)
+ and then (not Is_Tagged_Type (Btyp) or else Is_Null_Extension (Btyp))
+ then
+ declare
+ Parent_Type : constant Entity_Id := Base_Type (Etype (Btyp));
+ begin
+ Append_To (Stms,
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Parent_Type, Loc),
+ Attribute_Name => Name_Put_Image,
+ Expressions => New_List (
+ Make_Identifier (Loc, Name_S),
+ Make_Type_Conversion (Loc,
+ Subtype_Mark => New_Occurrence_Of
+ (Parent_Type, Loc),
+ Expression => Make_Identifier
+ (Loc, Name_V)))));
+ end;
+
else
Append_To (Stms,
Make_Procedure_Call_Statement (Loc,
Entity (Prefix (N)), Append_NUL => False))));
end Build_Unknown_Put_Image_Call;
- ----------------------
- -- Enable_Put_Image --
- ----------------------
+ -----------------------
+ -- Put_Image_Enabled --
+ -----------------------
- function Enable_Put_Image (Typ : Entity_Id) return Boolean is
+ function Put_Image_Enabled (Typ : Entity_Id) return Boolean is
begin
-- If this function returns False for a non-scalar type Typ, then
-- a) calls to Typ'Image will result in calls to
-- The name "Sink" here is a short nickname for
-- "Ada.Strings.Text_Buffers.Root_Buffer_Type".
--
+
-- Put_Image does not work for Remote_Types. We check the containing
-- package, rather than the type itself, because we want to include
-- types in the private part of a Remote_Types package.
if Is_Remote_Types (Scope (Typ))
or else Is_Remote_Call_Interface (Typ)
- or else (Is_Tagged_Type (Typ) and then In_Predefined_Unit (Typ))
then
return False;
end if;
return False;
end if;
+ if Is_Tagged_Type (Typ) then
+ if Is_Class_Wide_Type (Typ) then
+ return Put_Image_Enabled (Find_Specific_Type (Base_Type (Typ)));
+ elsif Present (Find_Aspect (Typ, Aspect_Put_Image,
+ Or_Rep_Item => True))
+ then
+ null;
+ elsif Is_Derived_Type (Typ) then
+ return Put_Image_Enabled (Etype (Base_Type (Typ)));
+ elsif In_Predefined_Unit (Typ) then
+ return False;
+ end if;
+ end if;
+
-- ???Disable Put_Image on type Root_Buffer_Type declared in
-- Ada.Strings.Text_Buffers. Note that we can't call Is_RTU on
-- Ada_Strings_Text_Buffers, because it's not known yet (we might be
end if;
return True;
- end Enable_Put_Image;
+ end Put_Image_Enabled;
-------------------------
-- Make_Put_Image_Name --