1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2008-2021, 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 with System.Case_Util;
38 package body Pprint is
40 List_Name_Count : Natural := 0;
41 -- Counter used to prevent infinite recursion while computing name of
42 -- complex expressions.
44 ----------------------
45 -- Expression_Image --
46 ----------------------
48 function Expression_Image
50 Default : String) return String
52 From_Source : constant Boolean :=
53 Comes_From_Source (Expr)
54 and then not Opt.Debug_Generated_Code;
55 Append_Paren : Natural := 0;
56 Left : Node_Id := Original_Node (Expr);
57 Right : Node_Id := Original_Node (Expr);
61 Take_Prefix : Boolean := True;
62 Expand_Type : Boolean := True) return String;
63 -- Return string corresponding to Expr. If no string can be extracted,
64 -- return "...". If Take_Prefix is True, go back to prefix when needed,
65 -- otherwise only consider the right-hand side of an expression. If
66 -- Expand_Type is True and Expr is a type, try to expand Expr (an
67 -- internally generated type) into a user understandable name.
69 Max_List : constant := 3;
70 -- Limit number of list elements to dump
72 Max_Expr_Elements : constant := 24;
73 -- Limit number of elements in an expression for use by Expr_Name
75 Num_Elements : Natural := 0;
76 -- Current number of elements processed by Expr_Name
80 Add_Space : Boolean := True;
81 Add_Paren : Boolean := True) return String;
82 -- Return a string corresponding to List
90 Add_Space : Boolean := True;
91 Add_Paren : Boolean := True) return String
93 function Internal_List_Name
95 First : Boolean := True;
96 Add_Space : Boolean := True;
97 Add_Paren : Boolean := True;
98 Num : Natural := 1) return String;
99 -- ??? what does this do
101 ------------------------
102 -- Internal_List_Name --
103 ------------------------
105 function Internal_List_Name
107 First : Boolean := True;
108 Add_Space : Boolean := True;
109 Add_Paren : Boolean := True;
110 Num : Natural := 1) return String
112 function Prepend (S : String) return String;
113 -- ??? what does this do
119 function Prepend (S : String) return String is
134 -- Start of processing for Internal_List_Name
137 if not Present (List) then
138 if First or else not Add_Paren then
143 elsif Num > Max_List then
151 -- ??? the Internal_List_Name calls can be factored out
154 return Prepend (Expr_Name (List)
156 (List => Next (List),
158 Add_Paren => Add_Paren,
161 return ", " & Expr_Name (List)
163 (List => Next (List),
165 Add_Paren => Add_Paren,
168 end Internal_List_Name;
170 -- Start of processing for List_Name
173 -- Prevent infinite recursion by limiting depth to 3
175 if List_Name_Count > 3 then
179 List_Name_Count := List_Name_Count + 1;
182 Result : constant String :=
185 Add_Space => Add_Space,
186 Add_Paren => Add_Paren);
188 List_Name_Count := List_Name_Count - 1;
199 Take_Prefix : Boolean := True;
200 Expand_Type : Boolean := True) return String
203 Num_Elements := Num_Elements + 1;
205 if Num_Elements > Max_Expr_Elements then
210 when N_Defining_Identifier
213 return Ident_Image (Expr, Expression_Image.Expr, Expand_Type);
215 when N_Character_Literal =>
217 Char : constant Int := UI_To_Int (Char_Literal_Value (Expr));
219 if Char in 32 .. 127 then
220 return "'" & Character'Val (Char) & "'";
222 UI_Image (Char_Literal_Value (Expr));
224 "'\" & UI_Image_Buffer (1 .. UI_Image_Length) & "'";
228 when N_Integer_Literal =>
229 return UI_Image (Intval (Expr));
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 (Expressions (Expr)) then
244 (List => First (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 (Expressions (Expr)),
270 Add_Paren => False) & ")";
272 when N_Attribute_Reference =>
275 Id : constant Attribute_Id :=
276 Get_Attribute_Id (Attribute_Name (Expr));
278 -- Always use mixed case for attributes
280 Str : constant String :=
281 Expr_Name (Prefix (Expr))
283 & System.Case_Util.To_Mixed
284 (Get_Name_String (Attribute_Name (Expr)));
290 if (Id = Attribute_First or else Id = Attribute_Last)
291 and then Str (Str'First) = '$'
293 N := Associated_Node_For_Itype (Etype (Prefix (Expr)));
296 if Nkind (N) = N_Full_Type_Declaration then
297 N := Type_Definition (N);
300 if Nkind (N) = N_Subtype_Declaration then
303 (Constraint (Subtype_Indication (N)));
305 if List_Length (Ranges) = 1
306 and then Nkind (First (Ranges)) in
308 N_Real_Range_Specification |
309 N_Signed_Integer_Type_Definition
311 if Id = Attribute_First then
314 (Low_Bound (First (Ranges)), Str);
318 (High_Bound (First (Ranges)), Str);
328 return "'" & Get_Name_String (Attribute_Name (Expr));
331 when N_Explicit_Dereference =>
332 Explicit_Dereference : declare
333 function Deref_Suffix return String;
334 -- Usually returns ".all", but will return "" if
335 -- Hide_Temp_Derefs is true and the prefix is a use of a
336 -- not-from-source object declared as
337 -- X : constant Some_Access_Type := Some_Expr'Reference;
338 -- (as is sometimes done in Exp_Util.Remove_Side_Effects).
344 function Deref_Suffix return String is
349 and then Nkind (Prefix (Expr)) = N_Identifier
350 and then Nkind (Entity (Prefix (Expr))) =
351 N_Defining_Identifier
353 Decl := Parent (Entity (Prefix (Expr)));
356 and then Nkind (Decl) = N_Object_Declaration
357 and then not Comes_From_Source (Decl)
358 and then Constant_Present (Decl)
359 and then Present (Expression (Decl))
360 and then Nkind (Expression (Decl)) = N_Reference
371 -- Start of processing for Explicit_Dereference
374 if Hide_Parameter_Blocks
375 and then Nkind (Prefix (Expr)) = N_Selected_Component
376 and then Present (Etype (Prefix (Expr)))
377 and then Is_Access_Type (Etype (Prefix (Expr)))
378 and then Is_Param_Block_Component_Type
379 (Etype (Prefix (Expr)))
381 -- Return "Foo" instead of "Parameter_Block.Foo.all"
383 return Expr_Name (Selector_Name (Prefix (Expr)));
385 elsif Take_Prefix then
386 return Expr_Name (Prefix (Expr)) & Deref_Suffix;
390 end Explicit_Dereference;
393 | N_Selected_Component
397 Expr_Name (Prefix (Expr)) & "." &
398 Expr_Name (Selector_Name (Expr));
400 return "." & Expr_Name (Selector_Name (Expr));
403 when N_Component_Association =>
406 (List => First (Choices (Expr)),
409 & " => " & Expr_Name (Expression (Expr)) & ")";
411 when N_If_Expression =>
413 Cond_Expr : constant Node_Id := First (Expressions (Expr));
414 Then_Expr : constant Node_Id := Next (Cond_Expr);
415 Else_Expr : constant Node_Id := Next (Then_Expr);
418 "if " & Expr_Name (Cond_Expr) & " then "
419 & Expr_Name (Then_Expr) & " else "
420 & Expr_Name (Else_Expr);
423 when N_Qualified_Expression =>
425 Mark : constant String :=
427 (Subtype_Mark (Expr), Expand_Type => False);
428 Str : constant String := Expr_Name (Expression (Expr));
430 if Str (Str'First) = '(' and then Str (Str'Last) = ')' then
431 return Mark & "'" & Str;
433 return Mark & "'(" & Str & ")";
437 when N_Expression_With_Actions
438 | N_Unchecked_Expression
440 return Expr_Name (Expression (Expr));
442 when N_Raise_Constraint_Error =>
443 if Present (Condition (Expr)) then
445 "[constraint_error when "
446 & Expr_Name (Condition (Expr)) & "]";
448 return "[constraint_error]";
451 when N_Raise_Program_Error =>
452 if Present (Condition (Expr)) then
454 "[program_error when "
455 & Expr_Name (Condition (Expr)) & "]";
457 return "[program_error]";
462 Expr_Name (Low_Bound (Expr)) & ".." &
463 Expr_Name (High_Bound (Expr));
467 Expr_Name (Prefix (Expr)) & " (" &
468 Expr_Name (Discrete_Range (Expr)) & ")";
472 Expr_Name (Left_Opnd (Expr)) & " and then " &
473 Expr_Name (Right_Opnd (Expr));
477 Expr_Name (Left_Opnd (Expr)) & " in " &
478 Expr_Name (Right_Opnd (Expr));
482 Expr_Name (Left_Opnd (Expr)) & " not in " &
483 Expr_Name (Right_Opnd (Expr));
487 Expr_Name (Left_Opnd (Expr)) & " or else " &
488 Expr_Name (Right_Opnd (Expr));
492 Expr_Name (Left_Opnd (Expr)) & " and " &
493 Expr_Name (Right_Opnd (Expr));
497 Expr_Name (Left_Opnd (Expr)) & " or " &
498 Expr_Name (Right_Opnd (Expr));
502 Expr_Name (Left_Opnd (Expr)) & " xor " &
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));
537 Expr_Name (Left_Opnd (Expr)) & " + " &
538 Expr_Name (Right_Opnd (Expr));
540 when N_Op_Subtract =>
542 Expr_Name (Left_Opnd (Expr)) & " - " &
543 Expr_Name (Right_Opnd (Expr));
545 when N_Op_Multiply =>
547 Expr_Name (Left_Opnd (Expr)) & " * " &
548 Expr_Name (Right_Opnd (Expr));
552 Expr_Name (Left_Opnd (Expr)) & " / " &
553 Expr_Name (Right_Opnd (Expr));
557 Expr_Name (Left_Opnd (Expr)) & " mod " &
558 Expr_Name (Right_Opnd (Expr));
562 Expr_Name (Left_Opnd (Expr)) & " rem " &
563 Expr_Name (Right_Opnd (Expr));
567 Expr_Name (Left_Opnd (Expr)) & " ** " &
568 Expr_Name (Right_Opnd (Expr));
570 when N_Op_Shift_Left =>
572 Expr_Name (Left_Opnd (Expr)) & " << " &
573 Expr_Name (Right_Opnd (Expr));
575 when N_Op_Shift_Right | N_Op_Shift_Right_Arithmetic =>
577 Expr_Name (Left_Opnd (Expr)) & " >> " &
578 Expr_Name (Right_Opnd (Expr));
582 Expr_Name (Left_Opnd (Expr)) & " & " &
583 Expr_Name (Right_Opnd (Expr));
586 return "+" & Expr_Name (Right_Opnd (Expr));
589 return "-" & Expr_Name (Right_Opnd (Expr));
592 return "abs " & Expr_Name (Right_Opnd (Expr));
595 return "not (" & Expr_Name (Right_Opnd (Expr)) & ")";
597 when N_Parameter_Association =>
598 return Expr_Name (Explicit_Actual_Parameter (Expr));
600 when N_Type_Conversion =>
602 -- Most conversions are not very interesting (used inside
603 -- expanded checks to convert to larger ranges), so skip them.
605 return Expr_Name (Expression (Expr));
607 when N_Unchecked_Type_Conversion =>
609 -- Only keep the type conversion in complex cases
611 if not Is_Scalar_Type (Etype (Expr))
612 or else not Is_Scalar_Type (Etype (Expression (Expr)))
613 or else Is_Modular_Integer_Type (Etype (Expr)) /=
614 Is_Modular_Integer_Type (Etype (Expression (Expr)))
616 return Expr_Name (Subtype_Mark (Expr)) &
617 "(" & Expr_Name (Expression (Expr)) & ")";
619 return Expr_Name (Expression (Expr));
622 when N_Indexed_Component =>
625 Expr_Name (Prefix (Expr))
626 & List_Name (First (Expressions (Expr)));
628 return List_Name (First (Expressions (Expr)));
631 when N_Function_Call =>
633 -- If Default = "", it means we're expanding the name of
634 -- a gnat temporary (and not really a function call), so add
635 -- parentheses around function call to mark it specially.
639 & Expr_Name (Name (Expr))
640 & List_Name (First (Parameter_Associations (Expr)))
644 Expr_Name (Name (Expr))
645 & List_Name (First (Parameter_Associations (Expr)));
651 when N_Others_Choice =>
659 -- Start of processing for Expression_Image
662 if not From_Source then
664 S : constant String := Expr_Name (Expr);
674 -- Reach to the underlying expression for an expression-with-actions
676 if Nkind (Expr) = N_Expression_With_Actions then
677 return Expression_Image (Expression (Expr), Default);
680 -- Compute left (start) and right (end) slocs for the expression
681 -- Consider using Sinput.Sloc_Range instead, except that it does not
682 -- work properly currently???
691 Left := Original_Node (Left_Opnd (Left));
693 when N_Attribute_Reference
695 | N_Explicit_Dereference
696 | N_Indexed_Component
698 | N_Selected_Component
701 Left := Original_Node (Prefix (Left));
703 when N_Defining_Program_Unit_Name
707 Left := Original_Node (Name (Left));
710 Left := Original_Node (Low_Bound (Left));
712 when N_Qualified_Expression
715 Left := Original_Node (Subtype_Mark (Left));
717 -- For any other item, quit loop
725 case Nkind (Right) is
731 Right := Original_Node (Right_Opnd (Right));
734 | N_Selected_Component
736 Right := Original_Node (Selector_Name (Right));
738 when N_Qualified_Expression
741 Right := Original_Node (Expression (Right));
743 -- If argument does not already account for a closing
744 -- parenthesis, count one here.
746 if Nkind (Right) not in N_Aggregate | N_Quantified_Expression
748 Append_Paren := Append_Paren + 1;
752 Right := Original_Node (Identifier (Right));
754 when N_Defining_Program_Unit_Name =>
755 Right := Original_Node (Defining_Identifier (Right));
758 Right := Original_Node (High_Bound (Right));
760 when N_Parameter_Association =>
761 Right := Original_Node (Explicit_Actual_Parameter (Right));
763 when N_Component_Association =>
764 if Present (Expression (Right)) then
765 Right := Expression (Right);
767 Right := Last (Choices (Right));
770 when N_Indexed_Component =>
771 Right := Original_Node (Last (Expressions (Right)));
772 Append_Paren := Append_Paren + 1;
774 when N_Function_Call =>
775 if Present (Parameter_Associations (Right)) then
781 -- Avoid source position confusion associated with
782 -- parameters for which Comes_From_Source is False.
784 Rover := First (Parameter_Associations (Right));
786 while Present (Rover) loop
787 if Comes_From_Source (Original_Node (Rover)) then
788 Right := Original_Node (Rover);
796 Append_Paren := Append_Paren + 1;
799 -- Quit loop if no Comes_From_Source parameters
804 -- Quit loop if no parameters
810 when N_Quantified_Expression =>
811 Right := Original_Node (Condition (Right));
812 Append_Paren := Append_Paren + 1;
816 Aggr : constant Node_Id := Right;
820 Sub := First (Expressions (Aggr));
821 while Present (Sub) loop
822 if Sloc (Sub) > Sloc (Right) then
829 Sub := First (Component_Associations (Aggr));
830 while Present (Sub) loop
831 if Sloc (Sub) > Sloc (Right) then
838 exit when Right = Aggr;
840 Append_Paren := Append_Paren + 1;
843 -- For all other items, quit the loop
851 Scn : Source_Ptr := Original_Location (Sloc (Left));
852 End_Sloc : constant Source_Ptr :=
853 Original_Location (Sloc (Right));
854 Src : constant Source_Buffer_Ptr :=
855 Source_Text (Get_Source_File_Index (Scn));
858 if Scn > End_Sloc then
863 Threshold : constant := 256;
864 Buffer : String (1 .. Natural (End_Sloc - Scn));
865 Index : Natural := 0;
866 Skipping_Comment : Boolean := False;
867 Underscore : Boolean := False;
870 if Right /= Expr then
871 while Scn < End_Sloc loop
874 -- Give up on non ASCII characters
876 when Character'Val (128) .. Character'Last =>
885 if not Skipping_Comment and then not Underscore then
888 Buffer (Index) := ' ';
891 -- CR/LF/FF is the end of any comment
897 Skipping_Comment := False;
902 if not Skipping_Comment then
906 if Src (Scn) = '-' and then Src (Scn + 1) = '-' then
907 Skipping_Comment := True;
911 Buffer (Index) := Src (Scn);
916 -- Give up on too long strings
918 if Index >= Threshold then
919 return Buffer (1 .. Index) & "...";
928 S : constant String := Expr_Name (Right);
940 & Expr_Name (Right, False)
941 & (1 .. Append_Paren => ')');
945 end Expression_Image;