1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2008-2018, 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 Namet
; use Namet
;
29 with Nlists
; use Nlists
;
31 with Sinfo
; use Sinfo
;
32 with Sinput
; use Sinput
;
33 with Snames
; use Snames
;
34 with Uintp
; use Uintp
;
36 package body Pprint
is
38 List_Name_Count
: Integer := 0;
39 -- Counter used to prevent infinite recursion while computing name of
40 -- complex expressions.
42 ----------------------
43 -- Expression_Image --
44 ----------------------
46 function Expression_Image
48 Default
: String) return String
50 From_Source
: constant Boolean :=
51 Comes_From_Source
(Expr
)
52 and then not Opt
.Debug_Generated_Code
;
53 Append_Paren
: Boolean := False;
54 Left
: Node_Id
:= Original_Node
(Expr
);
55 Right
: Node_Id
:= Original_Node
(Expr
);
59 Take_Prefix
: Boolean := True;
60 Expand_Type
: Boolean := True) return String;
61 -- Return string corresponding to Expr. If no string can be extracted,
62 -- return "...". If Take_Prefix is True, go back to prefix when needed,
63 -- otherwise only consider the right-hand side of an expression. If
64 -- Expand_Type is True and Expr is a type, try to expand Expr (an
65 -- internally generated type) into a user understandable name.
67 Max_List
: constant := 3;
68 -- Limit number of list elements to dump
70 Max_Expr_Elements
: constant := 24;
71 -- Limit number of elements in an expression for use by Expr_Name
73 Num_Elements
: Natural := 0;
74 -- Current number of elements processed by Expr_Name
78 Add_Space
: Boolean := True;
79 Add_Paren
: Boolean := True) return String;
80 -- Return a string corresponding to List
88 Add_Space
: Boolean := True;
89 Add_Paren
: Boolean := True) return String
91 function Internal_List_Name
93 First
: Boolean := True;
94 Add_Space
: Boolean := True;
95 Add_Paren
: Boolean := True;
96 Num
: Natural := 1) return String;
97 -- ??? what does this do
99 ------------------------
100 -- Internal_List_Name --
101 ------------------------
103 function Internal_List_Name
105 First
: Boolean := True;
106 Add_Space
: Boolean := True;
107 Add_Paren
: Boolean := True;
108 Num
: Natural := 1) return String
110 function Prepend
(S
: String) return String;
111 -- ??? what does this do
117 function Prepend
(S
: String) return String is
132 -- Start of processing for Internal_List_Name
135 if not Present
(List
) then
136 if First
or else not Add_Paren
then
141 elsif Num
> Max_List
then
149 -- ??? the Internal_List_Name calls can be factored out
152 return Prepend
(Expr_Name
(List
)
154 (List
=> Next
(List
),
156 Add_Paren
=> Add_Paren
,
159 return ", " & Expr_Name
(List
)
161 (List
=> Next
(List
),
163 Add_Paren
=> Add_Paren
,
166 end Internal_List_Name
;
168 -- Start of processing for List_Name
171 -- Prevent infinite recursion by limiting depth to 3
173 if List_Name_Count
> 3 then
177 List_Name_Count
:= List_Name_Count
+ 1;
180 Result
: constant String :=
183 Add_Space
=> Add_Space
,
184 Add_Paren
=> Add_Paren
);
186 List_Name_Count
:= List_Name_Count
- 1;
197 Take_Prefix
: Boolean := True;
198 Expand_Type
: Boolean := True) return String
201 Num_Elements
:= Num_Elements
+ 1;
203 if Num_Elements
> Max_Expr_Elements
then
208 when N_Defining_Identifier
211 return Ident_Image
(Expr
, Expression_Image
.Expr
, Expand_Type
);
213 when N_Character_Literal
=>
215 Char
: constant Int
:=
216 UI_To_Int
(Char_Literal_Value
(Expr
));
218 if Char
in 32 .. 127 then
219 return "'" & Character'Val (Char
) & "'";
221 UI_Image
(Char_Literal_Value
(Expr
));
223 "'\" & UI_Image_Buffer (1 .. UI_Image_Length) & "'";
227 when N_Integer_Literal =>
228 UI_Image (Intval (Expr));
229 return UI_Image_Buffer (1 .. UI_Image_Length);
231 when N_Real_Literal =>
232 return Real_Image (Realval (Expr));
234 when N_String_Literal =>
235 return String_Image (Strval (Expr));
238 return "new " & Expr_Name (Expression (Expr));
241 if Present (Sinfo.Expressions (Expr)) then
244 (List => First (Sinfo.Expressions (Expr)),
247 -- Do not return empty string for (others => <>) aggregate
248 -- of a componentless record type. At least one caller (the
249 -- recursive call below in the N_Qualified_Expression case)
250 -- is not prepared to deal with a zero-length result.
252 elsif Null_Record_Present (Expr)
253 or else not Present (First (Component_Associations (Expr)))
255 return ("(null record)");
260 (List => First (Component_Associations (Expr)),
265 when N_Extension_Aggregate =>
266 return "(" & Expr_Name (Ancestor_Part (Expr)) & " with "
268 (List => First (Sinfo.Expressions (Expr)),
270 Add_Paren => False) & ")";
272 when N_Attribute_Reference =>
275 Id : constant Attribute_Id :=
276 Get_Attribute_Id (Attribute_Name (Expr));
277 Str : constant String :=
278 Expr_Name (Prefix (Expr)) & "'"
279 & Get_Name_String (Attribute_Name (Expr));
284 if (Id = Attribute_First or else Id = Attribute_Last)
285 and then Str (Str'First) = '$'
287 N := Associated_Node_For_Itype (Etype (Prefix (Expr)));
290 if Nkind (N) = N_Full_Type_Declaration then
291 N := Type_Definition (N);
294 if Nkind (N) = N_Subtype_Declaration then
297 (Constraint (Subtype_Indication (N)));
299 if List_Length (Ranges) = 1
304 N_Real_Range_Specification,
305 N_Signed_Integer_Type_Definition)
307 if Id = Attribute_First then
310 (Low_Bound (First (Ranges)), Str);
314 (High_Bound (First (Ranges)), Str);
324 return "'" & Get_Name_String (Attribute_Name (Expr));
327 when N_Explicit_Dereference =>
328 Explicit_Dereference : declare
329 function Deref_Suffix return String;
330 -- Usually returns ".all", but will return "" if
331 -- Hide_Temp_Derefs is true and the prefix is a use of a
332 -- not-from-source object declared as
333 -- X : constant Some_Access_Type := Some_Expr'Reference;
334 -- (as is sometimes done in Exp_Util.Remove_Side_Effects).
340 function Deref_Suffix return String is
345 and then Nkind (Prefix (Expr)) = N_Identifier
346 and then Nkind (Entity (Prefix (Expr))) =
347 N_Defining_Identifier
349 Decl := Parent (Entity (Prefix (Expr)));
352 and then Nkind (Decl) = N_Object_Declaration
353 and then not Comes_From_Source (Decl)
354 and then Constant_Present (Decl)
355 and then Present (Sinfo.Expression (Decl))
356 and then Nkind (Sinfo.Expression (Decl)) =
368 -- Start of processing for Explicit_Dereference
371 if Hide_Parameter_Blocks
372 and then Nkind (Prefix (Expr)) = N_Selected_Component
373 and then Present (Etype (Prefix (Expr)))
374 and then Is_Access_Type (Etype (Prefix (Expr)))
375 and then Is_Param_Block_Component_Type
376 (Etype (Prefix (Expr)))
378 -- Return "Foo" instead of "Parameter_Block.Foo.all"
380 return Expr_Name (Selector_Name (Prefix (Expr)));
382 elsif Take_Prefix then
383 return Expr_Name (Prefix (Expr)) & Deref_Suffix;
387 end Explicit_Dereference;
390 | N_Selected_Component
394 Expr_Name (Prefix (Expr)) & "." &
395 Expr_Name (Selector_Name (Expr));
397 return "." & Expr_Name (Selector_Name (Expr));
400 when N_Component_Association =>
403 (List => First (Choices (Expr)),
406 & " => " & Expr_Name (Expression (Expr)) & ")";
408 when N_If_Expression =>
410 N : constant Node_Id := First (Sinfo.Expressions (Expr));
413 "if " & Expr_Name (N) & " then "
414 & Expr_Name (Next (N)) & " else "
415 & Expr_Name (Next (Next (N)));
418 when N_Qualified_Expression =>
420 Mark : constant String :=
422 (Subtype_Mark (Expr), Expand_Type => False);
423 Str : constant String := Expr_Name (Expression (Expr));
425 if Str (Str'First) = '(' and then Str (Str'Last) = ')' then
426 return Mark & "'" & Str;
428 return Mark & "'(" & Str & ")";
432 when N_Expression_With_Actions
433 | N_Unchecked_Expression
435 return Expr_Name (Expression (Expr));
437 when N_Raise_Constraint_Error =>
438 if Present (Condition (Expr)) then
440 "[constraint_error when "
441 & Expr_Name (Condition (Expr)) & "]";
443 return "[constraint_error]";
446 when N_Raise_Program_Error =>
447 if Present (Condition (Expr)) then
449 "[program_error when "
450 & Expr_Name (Condition (Expr)) & "]";
452 return "[program_error]";
457 Expr_Name (Low_Bound (Expr)) & ".." &
458 Expr_Name (High_Bound (Expr));
462 Expr_Name (Prefix (Expr)) & " (" &
463 Expr_Name (Discrete_Range (Expr)) & ")";
467 Expr_Name (Left_Opnd (Expr)) & " and then " &
468 Expr_Name (Right_Opnd (Expr));
472 Expr_Name (Left_Opnd (Expr)) & " in " &
473 Expr_Name (Right_Opnd (Expr));
477 Expr_Name (Left_Opnd (Expr)) & " not in " &
478 Expr_Name (Right_Opnd (Expr));
482 Expr_Name (Left_Opnd (Expr)) & " or else " &
483 Expr_Name (Right_Opnd (Expr));
487 Expr_Name (Left_Opnd (Expr)) & " and " &
488 Expr_Name (Right_Opnd (Expr));
492 Expr_Name (Left_Opnd (Expr)) & " or " &
493 Expr_Name (Right_Opnd (Expr));
497 Expr_Name (Left_Opnd (Expr)) & " xor " &
498 Expr_Name (Right_Opnd (Expr));
502 Expr_Name (Left_Opnd (Expr)) & " = " &
503 Expr_Name (Right_Opnd (Expr));
507 Expr_Name (Left_Opnd (Expr)) & " /= " &
508 Expr_Name (Right_Opnd (Expr));
512 Expr_Name (Left_Opnd (Expr)) & " < " &
513 Expr_Name (Right_Opnd (Expr));
517 Expr_Name (Left_Opnd (Expr)) & " <= " &
518 Expr_Name (Right_Opnd (Expr));
522 Expr_Name (Left_Opnd (Expr)) & " > " &
523 Expr_Name (Right_Opnd (Expr));
527 Expr_Name (Left_Opnd (Expr)) & " >= " &
528 Expr_Name (Right_Opnd (Expr));
532 Expr_Name (Left_Opnd (Expr)) & " + " &
533 Expr_Name (Right_Opnd (Expr));
535 when N_Op_Subtract =>
537 Expr_Name (Left_Opnd (Expr)) & " - " &
538 Expr_Name (Right_Opnd (Expr));
540 when N_Op_Multiply =>
542 Expr_Name (Left_Opnd (Expr)) & " * " &
543 Expr_Name (Right_Opnd (Expr));
547 Expr_Name (Left_Opnd (Expr)) & " / " &
548 Expr_Name (Right_Opnd (Expr));
552 Expr_Name (Left_Opnd (Expr)) & " mod " &
553 Expr_Name (Right_Opnd (Expr));
557 Expr_Name (Left_Opnd (Expr)) & " rem " &
558 Expr_Name (Right_Opnd (Expr));
562 Expr_Name (Left_Opnd (Expr)) & " ** " &
563 Expr_Name (Right_Opnd (Expr));
565 when N_Op_Shift_Left =>
567 Expr_Name (Left_Opnd (Expr)) & " << " &
568 Expr_Name (Right_Opnd (Expr));
570 when N_Op_Shift_Right | N_Op_Shift_Right_Arithmetic =>
572 Expr_Name (Left_Opnd (Expr)) & " >> " &
573 Expr_Name (Right_Opnd (Expr));
577 Expr_Name (Left_Opnd (Expr)) & " & " &
578 Expr_Name (Right_Opnd (Expr));
581 return "+" & Expr_Name (Right_Opnd (Expr));
584 return "-" & Expr_Name (Right_Opnd (Expr));
587 return "abs " & Expr_Name (Right_Opnd (Expr));
590 return "not (" & Expr_Name (Right_Opnd (Expr)) & ")";
592 when N_Parameter_Association =>
593 return Expr_Name (Explicit_Actual_Parameter (Expr));
595 when N_Type_Conversion =>
597 -- Most conversions are not very interesting (used inside
598 -- expanded checks to convert to larger ranges), so skip them.
600 return Expr_Name (Expression (Expr));
602 when N_Unchecked_Type_Conversion =>
604 -- Only keep the type conversion in complex cases
606 if not Is_Scalar_Type (Etype (Expr))
607 or else not Is_Scalar_Type (Etype (Expression (Expr)))
608 or else Is_Modular_Integer_Type (Etype (Expr)) /=
609 Is_Modular_Integer_Type (Etype (Expression (Expr)))
611 return Expr_Name (Subtype_Mark (Expr)) &
612 "(" & Expr_Name (Expression (Expr)) & ")";
614 return Expr_Name (Expression (Expr));
617 when N_Indexed_Component =>
620 Expr_Name (Prefix (Expr))
621 & List_Name (First (Sinfo.Expressions (Expr)));
623 return List_Name (First (Sinfo.Expressions (Expr)));
626 when N_Function_Call =>
628 -- If Default = "", it means we're expanding the name of
629 -- a gnat temporary (and not really a function call), so add
630 -- parentheses around function call to mark it specially.
634 & Expr_Name (Name (Expr))
635 & List_Name (First (Sinfo.Parameter_Associations (Expr)))
639 Expr_Name (Name (Expr))
641 (First (Sinfo.Parameter_Associations (Expr)));
647 when N_Others_Choice =>
655 -- Start of processing for Expression_Name
658 if not From_Source then
660 S : constant String := Expr_Name (Expr);
670 -- Compute left (start) and right (end) slocs for the expression
671 -- Consider using Sinput.Sloc_Range instead, except that it does not
672 -- work properly currently???
681 Left := Original_Node (Left_Opnd (Left));
683 when N_Attribute_Reference
685 | N_Explicit_Dereference
686 | N_Indexed_Component
688 | N_Selected_Component
691 Left := Original_Node (Prefix (Left));
693 when N_Defining_Program_Unit_Name
697 Left := Original_Node (Name (Left));
700 Left := Original_Node (Low_Bound (Left));
702 when N_Type_Conversion =>
703 Left := Original_Node (Subtype_Mark (Left));
705 -- For any other item, quit loop
713 case Nkind (Right) is
719 Right := Original_Node (Right_Opnd (Right));
722 | N_Selected_Component
724 Right := Original_Node (Selector_Name (Right));
727 Right := Original_Node (Identifier (Right));
729 when N_Defining_Program_Unit_Name =>
730 Right := Original_Node (Defining_Identifier (Right));
733 Right := Original_Node (High_Bound (Right));
735 when N_Parameter_Association =>
736 Right := Original_Node (Explicit_Actual_Parameter (Right));
738 when N_Indexed_Component =>
739 Right := Original_Node (Last (Sinfo.Expressions (Right)));
740 Append_Paren := True;
742 when N_Function_Call =>
743 if Present (Sinfo.Parameter_Associations (Right)) then
749 -- Avoid source position confusion associated with
750 -- parameters for which Comes_From_Source is False.
752 Rover := First (Sinfo.Parameter_Associations (Right));
754 while Present (Rover) loop
755 if Comes_From_Source (Original_Node (Rover)) then
756 Right := Original_Node (Rover);
757 Append_Paren := True;
764 -- Quit loop if no Comes_From_Source parameters
769 -- Quit loop if no parameters
775 when N_Quantified_Expression =>
776 Right := Original_Node (Condition (Right));
778 -- For all other items, quit the loop
786 Scn : Source_Ptr := Original_Location (Sloc (Left));
787 End_Sloc : constant Source_Ptr :=
788 Original_Location (Sloc (Right));
789 Src : constant Source_Buffer_Ptr :=
790 Source_Text (Get_Source_File_Index (Scn));
793 if Scn > End_Sloc then
798 Buffer : String (1 .. Natural (End_Sloc - Scn));
799 Index : Natural := 0;
800 Skipping_Comment : Boolean := False;
801 Underscore : Boolean := False;
804 if Right /= Expr then
805 while Scn < End_Sloc loop
810 if not Skipping_Comment and then not Underscore then
813 Buffer (Index) := ' ';
816 -- CR/LF/FF is the end of any comment
822 Skipping_Comment := False;
827 if not Skipping_Comment then
831 if Src (Scn) = '-' and then Src (Scn + 1) = '-' then
832 Skipping_Comment := True;
836 Buffer (Index) := Src (Scn);
847 S : constant String := Expr_Name (Right);
856 elsif Append_Paren then
857 return Buffer (1 .. Index) & Expr_Name (Right, False) & ')';
860 return Buffer (1 .. Index) & Expr_Name (Right, False);
864 end Expression_Image;