1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2008-2023, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with Atree
; use Atree
;
27 with Einfo
; use Einfo
;
28 with Einfo
.Entities
; use Einfo
.Entities
;
29 with Einfo
.Utils
; use Einfo
.Utils
;
30 with Namet
; use Namet
;
31 with Nlists
; use Nlists
;
33 with Sinfo
; use Sinfo
;
34 with Sinfo
.Nodes
; use Sinfo
.Nodes
;
35 with Sinfo
.Utils
; use Sinfo
.Utils
;
36 with Sinput
; use Sinput
;
37 with Snames
; use Snames
;
38 with Uintp
; use Uintp
;
40 with System
.Case_Util
;
42 package body Pprint
is
44 List_Name_Count
: Natural := 0;
45 -- Counter used to prevent infinite recursion while computing name of
46 -- complex expressions.
48 ----------------------
49 -- Expression_Image --
50 ----------------------
52 function Expression_Image
54 Default
: String) return String
56 From_Source
: constant Boolean :=
57 Comes_From_Source
(Expr
)
58 and then not Opt
.Debug_Generated_Code
;
59 Append_Paren
: Natural := 0;
60 Left
: Node_Id
:= Original_Node
(Expr
);
61 Right
: Node_Id
:= Original_Node
(Expr
);
65 Take_Prefix
: Boolean := True;
66 Expand_Type
: Boolean := True) return String;
67 -- Return string corresponding to Expr. If no string can be extracted,
68 -- return "...". If Take_Prefix is True, go back to prefix when needed,
69 -- otherwise only consider the right-hand side of an expression. If
70 -- Expand_Type is True and Expr is a type, try to expand Expr (an
71 -- internally generated type) into a user understandable name.
73 Max_List
: constant := 3;
74 -- Limit number of list elements to dump
76 Max_Expr_Elements
: constant := 24;
77 -- Limit number of elements in an expression for use by Expr_Name
79 Num_Elements
: Natural := 0;
80 -- Current number of elements processed by Expr_Name
84 Add_Space
: Boolean := True;
85 Add_Paren
: Boolean := True) return String;
86 -- Return a string corresponding to List
94 Add_Space
: Boolean := True;
95 Add_Paren
: Boolean := True) return String
97 function Internal_List_Name
99 First
: Boolean := True;
100 Add_Space
: Boolean := True;
101 Add_Paren
: Boolean := True;
102 Num
: Natural := 1) return String;
103 -- Created for purposes of recursing on embedded lists
105 ------------------------
106 -- Internal_List_Name --
107 ------------------------
109 function Internal_List_Name
111 First
: Boolean := True;
112 Add_Space
: Boolean := True;
113 Add_Paren
: Boolean := True;
114 Num
: Natural := 1) return String
118 if First
or else not Add_Paren
then
123 elsif Num
> Max_List
then
131 -- Continue recursing on the list - handling the first element
136 (if Add_Space
and Add_Paren
then " ("
137 elsif Add_Paren
then "("
138 elsif Add_Space
then " "
143 (List
=> Next
(List
),
145 Add_Paren
=> Add_Paren
,
147 end Internal_List_Name
;
149 -- Start of processing for List_Name
152 -- Prevent infinite recursion by limiting depth to 3
154 if List_Name_Count
> 3 then
158 List_Name_Count
:= List_Name_Count
+ 1;
161 Result
: constant String :=
164 Add_Space
=> Add_Space
,
165 Add_Paren
=> Add_Paren
);
167 List_Name_Count
:= List_Name_Count
- 1;
178 Take_Prefix
: Boolean := True;
179 Expand_Type
: Boolean := True) return String
182 Num_Elements
:= Num_Elements
+ 1;
184 if Num_Elements
> Max_Expr_Elements
then
189 when N_Defining_Identifier
192 return Ident_Image
(Expr
, Expression_Image
.Expr
, Expand_Type
);
194 when N_Character_Literal
=>
196 Char
: constant Int
:= UI_To_Int
(Char_Literal_Value
(Expr
));
198 if Char
in 32 .. 127 then
199 return "'" & Character'Val (Char
) & "'";
201 UI_Image
(Char_Literal_Value
(Expr
));
203 "'\" & UI_Image_Buffer (1 .. UI_Image_Length) & "'";
207 when N_Integer_Literal =>
208 return UI_Image (Intval (Expr));
210 when N_Real_Literal =>
211 return Real_Image (Realval (Expr));
213 when N_String_Literal =>
214 return String_Image (Strval (Expr));
217 return "new " & Expr_Name (Expression (Expr));
220 if Present (Expressions (Expr)) then
223 (List => First (Expressions (Expr)),
226 -- Do not return empty string for (others => <>) aggregate
227 -- of a componentless record type. At least one caller (the
228 -- recursive call below in the N_Qualified_Expression case)
229 -- is not prepared to deal with a zero-length result.
231 elsif Null_Record_Present (Expr)
232 or else No (First (Component_Associations (Expr)))
234 return ("(null record)");
239 (List => First (Component_Associations (Expr)),
244 when N_Extension_Aggregate =>
245 return "(" & Expr_Name (Ancestor_Part (Expr)) & " with "
247 (List => First (Expressions (Expr)),
249 Add_Paren => False) & ")";
251 when N_Attribute_Reference =>
254 Id : constant Attribute_Id :=
255 Get_Attribute_Id (Attribute_Name (Expr));
257 -- Always use mixed case for attributes
259 Str : constant String :=
260 Expr_Name (Prefix (Expr))
262 & System.Case_Util.To_Mixed
263 (Get_Name_String (Attribute_Name (Expr)));
269 if (Id = Attribute_First or else Id = Attribute_Last)
270 and then Str (Str'First) = '$'
272 N := Associated_Node_For_Itype (Etype (Prefix (Expr)));
275 if Nkind (N) = N_Full_Type_Declaration then
276 N := Type_Definition (N);
279 if Nkind (N) = N_Subtype_Declaration then
282 (Constraint (Subtype_Indication (N)));
284 if List_Length (Ranges) = 1
285 and then Nkind (First (Ranges)) in
287 N_Real_Range_Specification |
288 N_Signed_Integer_Type_Definition
290 if Id = Attribute_First then
293 (Low_Bound (First (Ranges)), Str);
297 (High_Bound (First (Ranges)), Str);
307 return "'" & Get_Name_String (Attribute_Name (Expr));
310 when N_Explicit_Dereference =>
311 Explicit_Dereference : declare
312 function Deref_Suffix return String;
313 -- Usually returns ".all", but will return "" if
314 -- Hide_Temp_Derefs is true and the prefix is a use of a
315 -- not-from-source object declared as
316 -- X : constant Some_Access_Type := Some_Expr'Reference;
317 -- (as is sometimes done in Exp_Util.Remove_Side_Effects).
323 function Deref_Suffix return String is
328 and then Nkind (Prefix (Expr)) = N_Identifier
329 and then Nkind (Entity (Prefix (Expr))) =
330 N_Defining_Identifier
332 Decl := Parent (Entity (Prefix (Expr)));
335 and then Nkind (Decl) = N_Object_Declaration
336 and then not Comes_From_Source (Decl)
337 and then Constant_Present (Decl)
338 and then Present (Expression (Decl))
339 and then Nkind (Expression (Decl)) = N_Reference
350 -- Start of processing for Explicit_Dereference
353 if Hide_Parameter_Blocks
354 and then Nkind (Prefix (Expr)) = N_Selected_Component
355 and then Present (Etype (Prefix (Expr)))
356 and then Is_Access_Type (Etype (Prefix (Expr)))
357 and then Is_Param_Block_Component_Type
358 (Etype (Prefix (Expr)))
360 -- Return "Foo" instead of "Parameter_Block.Foo.all"
362 return Expr_Name (Selector_Name (Prefix (Expr)));
364 elsif Take_Prefix then
365 return Expr_Name (Prefix (Expr)) & Deref_Suffix;
369 end Explicit_Dereference;
372 | N_Selected_Component
376 Expr_Name (Prefix (Expr)) & "." &
377 Expr_Name (Selector_Name (Expr));
379 return "." & Expr_Name (Selector_Name (Expr));
382 when N_Component_Association =>
385 (List => First (Choices (Expr)),
388 & " => " & Expr_Name (Expression (Expr)) & ")";
390 when N_If_Expression =>
392 Cond_Expr : constant Node_Id := First (Expressions (Expr));
393 Then_Expr : constant Node_Id := Next (Cond_Expr);
394 Else_Expr : constant Node_Id := Next (Then_Expr);
397 "if " & Expr_Name (Cond_Expr) & " then "
398 & Expr_Name (Then_Expr) & " else "
399 & Expr_Name (Else_Expr);
402 when N_Qualified_Expression =>
404 Mark : constant String :=
406 (Subtype_Mark (Expr), Expand_Type => False);
407 Str : constant String := Expr_Name (Expression (Expr));
409 if Str (Str'First) = '(' and then Str (Str'Last) = ')' then
410 return Mark & "'" & Str;
412 return Mark & "'(" & Str & ")";
416 when N_Expression_With_Actions
417 | N_Unchecked_Expression
419 return Expr_Name (Expression (Expr));
421 when N_Raise_Constraint_Error =>
422 if Present (Condition (Expr)) then
424 "[constraint_error when "
425 & Expr_Name (Condition (Expr)) & "]";
427 return "[constraint_error]";
430 when N_Raise_Program_Error =>
431 if Present (Condition (Expr)) then
433 "[program_error when "
434 & Expr_Name (Condition (Expr)) & "]";
436 return "[program_error]";
441 Expr_Name (Low_Bound (Expr)) & ".." &
442 Expr_Name (High_Bound (Expr));
446 Expr_Name (Prefix (Expr)) & " (" &
447 Expr_Name (Discrete_Range (Expr)) & ")";
451 Expr_Name (Left_Opnd (Expr)) & " and then " &
452 Expr_Name (Right_Opnd (Expr));
456 Expr_Name (Left_Opnd (Expr)) & " in " &
457 Expr_Name (Right_Opnd (Expr));
461 Expr_Name (Left_Opnd (Expr)) & " not in " &
462 Expr_Name (Right_Opnd (Expr));
466 Expr_Name (Left_Opnd (Expr)) & " or else " &
467 Expr_Name (Right_Opnd (Expr));
471 Expr_Name (Left_Opnd (Expr)) & " and " &
472 Expr_Name (Right_Opnd (Expr));
476 Expr_Name (Left_Opnd (Expr)) & " or " &
477 Expr_Name (Right_Opnd (Expr));
481 Expr_Name (Left_Opnd (Expr)) & " xor " &
482 Expr_Name (Right_Opnd (Expr));
486 Expr_Name (Left_Opnd (Expr)) & " = " &
487 Expr_Name (Right_Opnd (Expr));
491 Expr_Name (Left_Opnd (Expr)) & " /= " &
492 Expr_Name (Right_Opnd (Expr));
496 Expr_Name (Left_Opnd (Expr)) & " < " &
497 Expr_Name (Right_Opnd (Expr));
501 Expr_Name (Left_Opnd (Expr)) & " <= " &
502 Expr_Name (Right_Opnd (Expr));
506 Expr_Name (Left_Opnd (Expr)) & " > " &
507 Expr_Name (Right_Opnd (Expr));
511 Expr_Name (Left_Opnd (Expr)) & " >= " &
512 Expr_Name (Right_Opnd (Expr));
516 Expr_Name (Left_Opnd (Expr)) & " + " &
517 Expr_Name (Right_Opnd (Expr));
519 when N_Op_Subtract =>
521 Expr_Name (Left_Opnd (Expr)) & " - " &
522 Expr_Name (Right_Opnd (Expr));
524 when N_Op_Multiply =>
526 Expr_Name (Left_Opnd (Expr)) & " * " &
527 Expr_Name (Right_Opnd (Expr));
531 Expr_Name (Left_Opnd (Expr)) & " / " &
532 Expr_Name (Right_Opnd (Expr));
536 Expr_Name (Left_Opnd (Expr)) & " mod " &
537 Expr_Name (Right_Opnd (Expr));
541 Expr_Name (Left_Opnd (Expr)) & " rem " &
542 Expr_Name (Right_Opnd (Expr));
546 Expr_Name (Left_Opnd (Expr)) & " ** " &
547 Expr_Name (Right_Opnd (Expr));
549 when N_Op_Shift_Left =>
551 Expr_Name (Left_Opnd (Expr)) & " << " &
552 Expr_Name (Right_Opnd (Expr));
554 when N_Op_Shift_Right | N_Op_Shift_Right_Arithmetic =>
556 Expr_Name (Left_Opnd (Expr)) & " >> " &
557 Expr_Name (Right_Opnd (Expr));
561 Expr_Name (Left_Opnd (Expr)) & " & " &
562 Expr_Name (Right_Opnd (Expr));
565 return "+" & Expr_Name (Right_Opnd (Expr));
568 return "-" & Expr_Name (Right_Opnd (Expr));
571 return "abs " & Expr_Name (Right_Opnd (Expr));
574 return "not (" & Expr_Name (Right_Opnd (Expr)) & ")";
576 when N_Parameter_Association =>
577 return Expr_Name (Explicit_Actual_Parameter (Expr));
579 when N_Type_Conversion =>
581 -- Most conversions are not very interesting (used inside
582 -- expanded checks to convert to larger ranges), so skip them.
584 return Expr_Name (Expression (Expr));
586 when N_Unchecked_Type_Conversion =>
588 -- Only keep the type conversion in complex cases
590 if not Is_Scalar_Type (Etype (Expr))
591 or else not Is_Scalar_Type (Etype (Expression (Expr)))
592 or else Is_Modular_Integer_Type (Etype (Expr)) /=
593 Is_Modular_Integer_Type (Etype (Expression (Expr)))
595 return Expr_Name (Subtype_Mark (Expr)) &
596 "(" & Expr_Name (Expression (Expr)) & ")";
598 return Expr_Name (Expression (Expr));
601 when N_Indexed_Component =>
604 Expr_Name (Prefix (Expr))
605 & List_Name (First (Expressions (Expr)));
607 return List_Name (First (Expressions (Expr)));
610 when N_Function_Call =>
612 -- If Default = "", it means we're expanding the name of
613 -- a gnat temporary (and not really a function call), so add
614 -- parentheses around function call to mark it specially.
618 & Expr_Name (Name (Expr))
619 & List_Name (First (Parameter_Associations (Expr)))
623 Expr_Name (Name (Expr))
624 & List_Name (First (Parameter_Associations (Expr)));
630 when N_Others_Choice =>
638 -- Start of processing for Expression_Image
641 if not From_Source then
643 S : constant String := Expr_Name (Expr);
653 -- Reach to the underlying expression for an expression-with-actions
655 if Nkind (Expr) = N_Expression_With_Actions then
656 return Expression_Image (Expression (Expr), Default);
659 -- Compute left (start) and right (end) slocs for the expression
660 -- Consider using Sinput.Sloc_Range instead, except that it does not
661 -- work properly currently???
670 Left := Original_Node (Left_Opnd (Left));
672 when N_Attribute_Reference
674 | N_Explicit_Dereference
675 | N_Indexed_Component
677 | N_Selected_Component
680 Left := Original_Node (Prefix (Left));
682 when N_Defining_Program_Unit_Name
686 Left := Original_Node (Name (Left));
689 Left := Original_Node (Low_Bound (Left));
691 when N_Qualified_Expression
694 Left := Original_Node (Subtype_Mark (Left));
696 -- For any other item, quit loop
704 case Nkind (Right) is
710 Right := Original_Node (Right_Opnd (Right));
713 | N_Selected_Component
715 Right := Original_Node (Selector_Name (Right));
717 when N_Qualified_Expression
720 Right := Original_Node (Expression (Right));
722 -- If argument does not already account for a closing
723 -- parenthesis, count one here.
725 if Nkind (Right) not in N_Aggregate | N_Quantified_Expression
727 Append_Paren := Append_Paren + 1;
731 Right := Original_Node (Identifier (Right));
733 when N_Defining_Program_Unit_Name =>
734 Right := Original_Node (Defining_Identifier (Right));
737 Right := Original_Node (High_Bound (Right));
739 when N_Parameter_Association =>
740 Right := Original_Node (Explicit_Actual_Parameter (Right));
742 when N_Component_Association =>
743 if Present (Expression (Right)) then
744 Right := Expression (Right);
746 Right := Last (Choices (Right));
749 when N_Indexed_Component =>
750 Right := Original_Node (Last (Expressions (Right)));
751 Append_Paren := Append_Paren + 1;
753 when N_Function_Call =>
754 if Present (Parameter_Associations (Right)) then
760 -- Avoid source position confusion associated with
761 -- parameters for which Comes_From_Source is False.
763 Rover := First (Parameter_Associations (Right));
765 while Present (Rover) loop
766 if Comes_From_Source (Original_Node (Rover)) then
767 Right := Original_Node (Rover);
775 Append_Paren := Append_Paren + 1;
778 -- Quit loop if no Comes_From_Source parameters
783 -- Quit loop if no parameters
789 when N_Quantified_Expression =>
790 Right := Original_Node (Condition (Right));
791 Append_Paren := Append_Paren + 1;
795 Aggr : constant Node_Id := Right;
799 Sub := First (Expressions (Aggr));
800 while Present (Sub) loop
801 if Sloc (Sub) > Sloc (Right) then
808 Sub := First (Component_Associations (Aggr));
809 while Present (Sub) loop
810 if Sloc (Sub) > Sloc (Right) then
817 exit when Right = Aggr;
819 Append_Paren := Append_Paren + 1;
822 -- For all other items, quit the loop
830 Scn : Source_Ptr := Original_Location (Sloc (Left));
831 End_Sloc : constant Source_Ptr :=
832 Original_Location (Sloc (Right));
833 Src : constant Source_Buffer_Ptr :=
834 Source_Text (Get_Source_File_Index (Scn));
837 if Scn > End_Sloc then
842 Threshold : constant := 256;
843 Buffer : String (1 .. Natural (End_Sloc - Scn));
844 Index : Natural := 0;
845 Skipping_Comment : Boolean := False;
846 Underscore : Boolean := False;
849 if Right /= Expr then
850 while Scn < End_Sloc loop
853 -- Give up on non ASCII characters
855 when Character'Val (128) .. Character'Last =>
864 if not Skipping_Comment and then not Underscore then
867 Buffer (Index) := ' ';
870 -- CR/LF/FF is the end of any comment
876 Skipping_Comment := False;
881 if not Skipping_Comment then
885 if Src (Scn) = '-' and then Src (Scn + 1) = '-' then
886 Skipping_Comment := True;
890 Buffer (Index) := Src (Scn);
895 -- Give up on too long strings
897 if Index >= Threshold then
898 return Buffer (1 .. Index) & "...";
907 S : constant String := Expr_Name (Right);
919 & Expr_Name (Right, False)
920 & (1 .. Append_Paren => ')');
924 end Expression_Image;