Small ChangeLog tweak.
[official-gcc.git] / gcc / ada / pprint.adb
blobfcfccd316f8aa7e2d12bccab660b23b8786a9142
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- P P R I N T --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2008-2016, Free Software Foundation, Inc. --
10 -- --
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. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
23 -- --
24 ------------------------------------------------------------------------------
26 with Atree; use Atree;
27 with Einfo; use Einfo;
28 with Namet; use Namet;
29 with Nlists; use Nlists;
30 with Opt; use Opt;
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
47 (Expr : Node_Id;
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);
57 function Expr_Name
58 (Expr : Node_Id;
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
76 function List_Name
77 (List : Node_Id;
78 Add_Space : Boolean := True;
79 Add_Paren : Boolean := True) return String;
80 -- Return a string corresponding to List
82 ---------------
83 -- List_Name --
84 ---------------
86 function List_Name
87 (List : Node_Id;
88 Add_Space : Boolean := True;
89 Add_Paren : Boolean := True) return String
91 function Internal_List_Name
92 (List : Node_Id;
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
104 (List : Node_Id;
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
113 -------------
114 -- Prepend --
115 -------------
117 function Prepend (S : String) return String is
118 begin
119 if Add_Space then
120 if Add_Paren then
121 return " (" & S;
122 else
123 return ' ' & S;
124 end if;
125 elsif Add_Paren then
126 return '(' & S;
127 else
128 return S;
129 end if;
130 end Prepend;
132 -- Start of processing for Internal_List_Name
134 begin
135 if not Present (List) then
136 if First or else not Add_Paren then
137 return "";
138 else
139 return ")";
140 end if;
141 elsif Num > Max_List then
142 if Add_Paren then
143 return ", ...)";
144 else
145 return ", ...";
146 end if;
147 end if;
149 -- ??? the Internal_List_Name calls can be factored out
151 if First then
152 return Prepend (Expr_Name (List)
153 & Internal_List_Name
154 (List => Next (List),
155 First => False,
156 Add_Paren => Add_Paren,
157 Num => Num + 1));
158 else
159 return ", " & Expr_Name (List)
160 & Internal_List_Name
161 (List => Next (List),
162 First => False,
163 Add_Paren => Add_Paren,
164 Num => Num + 1);
165 end if;
166 end Internal_List_Name;
168 -- Start of processing for List_Name
170 begin
171 -- Prevent infinite recursion by limiting depth to 3
173 if List_Name_Count > 3 then
174 return "...";
175 end if;
177 List_Name_Count := List_Name_Count + 1;
179 declare
180 Result : constant String :=
181 Internal_List_Name
182 (List => List,
183 Add_Space => Add_Space,
184 Add_Paren => Add_Paren);
185 begin
186 List_Name_Count := List_Name_Count - 1;
187 return Result;
188 end;
189 end List_Name;
191 ---------------
192 -- Expr_Name --
193 ---------------
195 function Expr_Name
196 (Expr : Node_Id;
197 Take_Prefix : Boolean := True;
198 Expand_Type : Boolean := True) return String
200 begin
201 Num_Elements := Num_Elements + 1;
203 if Num_Elements > Max_Expr_Elements then
204 return "...";
205 end if;
207 case Nkind (Expr) is
208 when N_Defining_Identifier
209 | N_Identifier
211 return Ident_Image (Expr, Expression_Image.Expr, Expand_Type);
213 when N_Character_Literal =>
214 declare
215 Char : constant Int :=
216 UI_To_Int (Char_Literal_Value (Expr));
217 begin
218 if Char in 32 .. 127 then
219 return "'" & Character'Val (Char) & "'";
220 else
221 UI_Image (Char_Literal_Value (Expr));
222 return
223 "'\" & UI_Image_Buffer (1 .. UI_Image_Length) & "'";
224 end if;
225 end;
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));
237 when N_Allocator =>
238 return "new " & Expr_Name (Expression (Expr));
240 when N_Aggregate =>
241 if Present (Sinfo.Expressions (Expr)) then
242 return
243 List_Name
244 (List => First (Sinfo.Expressions (Expr)),
245 Add_Space => False);
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)))
254 then
255 return ("(null record)");
257 else
258 return
259 List_Name
260 (List => First (Component_Associations (Expr)),
261 Add_Space => False,
262 Add_Paren => False);
263 end if;
265 when N_Extension_Aggregate =>
266 return "(" & Expr_Name (Ancestor_Part (Expr)) & " with "
267 & List_Name
268 (List => First (Sinfo.Expressions (Expr)),
269 Add_Space => False,
270 Add_Paren => False) & ")";
272 when N_Attribute_Reference =>
273 if Take_Prefix then
274 declare
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));
280 N : Node_Id;
281 Ranges : List_Id;
283 begin
284 if (Id = Attribute_First or else Id = Attribute_Last)
285 and then Str (Str'First) = '$'
286 then
287 N := Associated_Node_For_Itype (Etype (Prefix (Expr)));
289 if Present (N) then
290 if Nkind (N) = N_Full_Type_Declaration then
291 N := Type_Definition (N);
292 end if;
294 if Nkind (N) = N_Subtype_Declaration then
295 Ranges :=
296 Constraints
297 (Constraint (Subtype_Indication (N)));
299 if List_Length (Ranges) = 1
300 and then
301 Nkind_In
302 (First (Ranges),
303 N_Range,
304 N_Real_Range_Specification,
305 N_Signed_Integer_Type_Definition)
306 then
307 if Id = Attribute_First then
308 return
309 Expression_Image
310 (Low_Bound (First (Ranges)), Str);
311 else
312 return
313 Expression_Image
314 (High_Bound (First (Ranges)), Str);
315 end if;
316 end if;
317 end if;
318 end if;
319 end if;
321 return Str;
322 end;
323 else
324 return "'" & Get_Name_String (Attribute_Name (Expr));
325 end if;
327 when N_Explicit_Dereference =>
329 -- Return "Foo" instead of "Parameter_Block.Foo.all"
331 if Hide_Parameter_Blocks
332 and then Nkind (Prefix (Expr)) = N_Selected_Component
333 and then Present (Etype (Prefix (Expr)))
334 and then Is_Access_Type (Etype (Prefix (Expr)))
335 and then Is_Param_Block_Component_Type (Etype (Prefix (Expr)))
336 then
337 return Expr_Name (Selector_Name (Prefix (Expr)));
339 elsif Take_Prefix then
340 return Expr_Name (Prefix (Expr)) & ".all";
341 else
342 return ".all";
343 end if;
345 when N_Expanded_Name
346 | N_Selected_Component
348 if Take_Prefix then
349 return
350 Expr_Name (Prefix (Expr)) & "." &
351 Expr_Name (Selector_Name (Expr));
352 else
353 return "." & Expr_Name (Selector_Name (Expr));
354 end if;
356 when N_Component_Association =>
357 return "("
358 & List_Name
359 (List => First (Choices (Expr)),
360 Add_Space => False,
361 Add_Paren => False)
362 & " => " & Expr_Name (Expression (Expr)) & ")";
364 when N_If_Expression =>
365 declare
366 N : constant Node_Id := First (Sinfo.Expressions (Expr));
367 begin
368 return
369 "if " & Expr_Name (N) & " then "
370 & Expr_Name (Next (N)) & " else "
371 & Expr_Name (Next (Next (N)));
372 end;
374 when N_Qualified_Expression =>
375 declare
376 Mark : constant String :=
377 Expr_Name
378 (Subtype_Mark (Expr), Expand_Type => False);
379 Str : constant String := Expr_Name (Expression (Expr));
380 begin
381 if Str (Str'First) = '(' and then Str (Str'Last) = ')' then
382 return Mark & "'" & Str;
383 else
384 return Mark & "'(" & Str & ")";
385 end if;
386 end;
388 when N_Expression_With_Actions
389 | N_Unchecked_Expression
391 return Expr_Name (Expression (Expr));
393 when N_Raise_Constraint_Error =>
394 if Present (Condition (Expr)) then
395 return
396 "[constraint_error when "
397 & Expr_Name (Condition (Expr)) & "]";
398 else
399 return "[constraint_error]";
400 end if;
402 when N_Raise_Program_Error =>
403 if Present (Condition (Expr)) then
404 return
405 "[program_error when "
406 & Expr_Name (Condition (Expr)) & "]";
407 else
408 return "[program_error]";
409 end if;
411 when N_Range =>
412 return
413 Expr_Name (Low_Bound (Expr)) & ".." &
414 Expr_Name (High_Bound (Expr));
416 when N_Slice =>
417 return
418 Expr_Name (Prefix (Expr)) & " (" &
419 Expr_Name (Discrete_Range (Expr)) & ")";
421 when N_And_Then =>
422 return
423 Expr_Name (Left_Opnd (Expr)) & " and then " &
424 Expr_Name (Right_Opnd (Expr));
426 when N_In =>
427 return
428 Expr_Name (Left_Opnd (Expr)) & " in " &
429 Expr_Name (Right_Opnd (Expr));
431 when N_Not_In =>
432 return
433 Expr_Name (Left_Opnd (Expr)) & " not in " &
434 Expr_Name (Right_Opnd (Expr));
436 when N_Or_Else =>
437 return
438 Expr_Name (Left_Opnd (Expr)) & " or else " &
439 Expr_Name (Right_Opnd (Expr));
441 when N_Op_And =>
442 return
443 Expr_Name (Left_Opnd (Expr)) & " and " &
444 Expr_Name (Right_Opnd (Expr));
446 when N_Op_Or =>
447 return
448 Expr_Name (Left_Opnd (Expr)) & " or " &
449 Expr_Name (Right_Opnd (Expr));
451 when N_Op_Xor =>
452 return
453 Expr_Name (Left_Opnd (Expr)) & " xor " &
454 Expr_Name (Right_Opnd (Expr));
456 when N_Op_Eq =>
457 return
458 Expr_Name (Left_Opnd (Expr)) & " = " &
459 Expr_Name (Right_Opnd (Expr));
461 when N_Op_Ne =>
462 return
463 Expr_Name (Left_Opnd (Expr)) & " /= " &
464 Expr_Name (Right_Opnd (Expr));
466 when N_Op_Lt =>
467 return
468 Expr_Name (Left_Opnd (Expr)) & " < " &
469 Expr_Name (Right_Opnd (Expr));
471 when N_Op_Le =>
472 return
473 Expr_Name (Left_Opnd (Expr)) & " <= " &
474 Expr_Name (Right_Opnd (Expr));
476 when N_Op_Gt =>
477 return
478 Expr_Name (Left_Opnd (Expr)) & " > " &
479 Expr_Name (Right_Opnd (Expr));
481 when N_Op_Ge =>
482 return
483 Expr_Name (Left_Opnd (Expr)) & " >= " &
484 Expr_Name (Right_Opnd (Expr));
486 when N_Op_Add =>
487 return
488 Expr_Name (Left_Opnd (Expr)) & " + " &
489 Expr_Name (Right_Opnd (Expr));
491 when N_Op_Subtract =>
492 return
493 Expr_Name (Left_Opnd (Expr)) & " - " &
494 Expr_Name (Right_Opnd (Expr));
496 when N_Op_Multiply =>
497 return
498 Expr_Name (Left_Opnd (Expr)) & " * " &
499 Expr_Name (Right_Opnd (Expr));
501 when N_Op_Divide =>
502 return
503 Expr_Name (Left_Opnd (Expr)) & " / " &
504 Expr_Name (Right_Opnd (Expr));
506 when N_Op_Mod =>
507 return
508 Expr_Name (Left_Opnd (Expr)) & " mod " &
509 Expr_Name (Right_Opnd (Expr));
511 when N_Op_Rem =>
512 return
513 Expr_Name (Left_Opnd (Expr)) & " rem " &
514 Expr_Name (Right_Opnd (Expr));
516 when N_Op_Expon =>
517 return
518 Expr_Name (Left_Opnd (Expr)) & " ** " &
519 Expr_Name (Right_Opnd (Expr));
521 when N_Op_Shift_Left =>
522 return
523 Expr_Name (Left_Opnd (Expr)) & " << " &
524 Expr_Name (Right_Opnd (Expr));
526 when N_Op_Shift_Right | N_Op_Shift_Right_Arithmetic =>
527 return
528 Expr_Name (Left_Opnd (Expr)) & " >> " &
529 Expr_Name (Right_Opnd (Expr));
531 when N_Op_Concat =>
532 return
533 Expr_Name (Left_Opnd (Expr)) & " & " &
534 Expr_Name (Right_Opnd (Expr));
536 when N_Op_Plus =>
537 return "+" & Expr_Name (Right_Opnd (Expr));
539 when N_Op_Minus =>
540 return "-" & Expr_Name (Right_Opnd (Expr));
542 when N_Op_Abs =>
543 return "abs " & Expr_Name (Right_Opnd (Expr));
545 when N_Op_Not =>
546 return "not (" & Expr_Name (Right_Opnd (Expr)) & ")";
548 when N_Parameter_Association =>
549 return Expr_Name (Explicit_Actual_Parameter (Expr));
551 when N_Type_Conversion =>
553 -- Most conversions are not very interesting (used inside
554 -- expanded checks to convert to larger ranges), so skip them.
556 return Expr_Name (Expression (Expr));
558 when N_Unchecked_Type_Conversion =>
560 -- Only keep the type conversion in complex cases
562 if not Is_Scalar_Type (Etype (Expr))
563 or else not Is_Scalar_Type (Etype (Expression (Expr)))
564 or else Is_Modular_Integer_Type (Etype (Expr)) /=
565 Is_Modular_Integer_Type (Etype (Expression (Expr)))
566 then
567 return Expr_Name (Subtype_Mark (Expr)) &
568 "(" & Expr_Name (Expression (Expr)) & ")";
569 else
570 return Expr_Name (Expression (Expr));
571 end if;
573 when N_Indexed_Component =>
574 if Take_Prefix then
575 return
576 Expr_Name (Prefix (Expr))
577 & List_Name (First (Sinfo.Expressions (Expr)));
578 else
579 return List_Name (First (Sinfo.Expressions (Expr)));
580 end if;
582 when N_Function_Call =>
584 -- If Default = "", it means we're expanding the name of
585 -- a gnat temporary (and not really a function call), so add
586 -- parentheses around function call to mark it specially.
588 if Default = "" then
589 return '('
590 & Expr_Name (Name (Expr))
591 & List_Name (First (Sinfo.Parameter_Associations (Expr)))
592 & ')';
593 else
594 return
595 Expr_Name (Name (Expr))
596 & List_Name
597 (First (Sinfo.Parameter_Associations (Expr)));
598 end if;
600 when N_Null =>
601 return "null";
603 when N_Others_Choice =>
604 return "others";
606 when others =>
607 return "...";
608 end case;
609 end Expr_Name;
611 -- Start of processing for Expression_Name
613 begin
614 if not From_Source then
615 declare
616 S : constant String := Expr_Name (Expr);
617 begin
618 if S = "..." then
619 return Default;
620 else
621 return S;
622 end if;
623 end;
624 end if;
626 -- Compute left (start) and right (end) slocs for the expression
627 -- Consider using Sinput.Sloc_Range instead, except that it does not
628 -- work properly currently???
630 loop
631 case Nkind (Left) is
632 when N_And_Then
633 | N_Binary_Op
634 | N_Membership_Test
635 | N_Or_Else
637 Left := Original_Node (Left_Opnd (Left));
639 when N_Attribute_Reference
640 | N_Expanded_Name
641 | N_Explicit_Dereference
642 | N_Indexed_Component
643 | N_Reference
644 | N_Selected_Component
645 | N_Slice
647 Left := Original_Node (Prefix (Left));
649 when N_Defining_Program_Unit_Name
650 | N_Designator
651 | N_Function_Call
653 Left := Original_Node (Name (Left));
655 when N_Range =>
656 Left := Original_Node (Low_Bound (Left));
658 when N_Type_Conversion =>
659 Left := Original_Node (Subtype_Mark (Left));
661 -- For any other item, quit loop
663 when others =>
664 exit;
665 end case;
666 end loop;
668 loop
669 case Nkind (Right) is
670 when N_And_Then
671 | N_Membership_Test
672 | N_Op
673 | N_Or_Else
675 Right := Original_Node (Right_Opnd (Right));
677 when N_Expanded_Name
678 | N_Selected_Component
680 Right := Original_Node (Selector_Name (Right));
682 when N_Designator =>
683 Right := Original_Node (Identifier (Right));
685 when N_Defining_Program_Unit_Name =>
686 Right := Original_Node (Defining_Identifier (Right));
688 when N_Range =>
689 Right := Original_Node (High_Bound (Right));
691 when N_Parameter_Association =>
692 Right := Original_Node (Explicit_Actual_Parameter (Right));
694 when N_Indexed_Component =>
695 Right := Original_Node (Last (Sinfo.Expressions (Right)));
696 Append_Paren := True;
698 when N_Function_Call =>
699 if Present (Sinfo.Parameter_Associations (Right)) then
700 declare
701 Rover : Node_Id;
702 Found : Boolean;
704 begin
705 -- Avoid source position confusion associated with
706 -- parameters for which Comes_From_Source is False.
708 Rover := First (Sinfo.Parameter_Associations (Right));
709 Found := False;
710 while Present (Rover) loop
711 if Comes_From_Source (Original_Node (Rover)) then
712 Right := Original_Node (Rover);
713 Append_Paren := True;
714 Found := True;
715 end if;
717 Next (Rover);
718 end loop;
720 -- Quit loop if no Comes_From_Source parameters
722 exit when not Found;
723 end;
725 -- Quit loop if no parameters
727 else
728 exit;
729 end if;
731 when N_Quantified_Expression =>
732 Right := Original_Node (Condition (Right));
734 -- For all other items, quit the loop
736 when others =>
737 exit;
738 end case;
739 end loop;
741 declare
742 Scn : Source_Ptr := Original_Location (Sloc (Left));
743 End_Sloc : constant Source_Ptr :=
744 Original_Location (Sloc (Right));
745 Src : constant Source_Buffer_Ptr :=
746 Source_Text (Get_Source_File_Index (Scn));
748 begin
749 if Scn > End_Sloc then
750 return Default;
751 end if;
753 declare
754 Buffer : String (1 .. Natural (End_Sloc - Scn));
755 Index : Natural := 0;
756 Skipping_Comment : Boolean := False;
757 Underscore : Boolean := False;
759 begin
760 if Right /= Expr then
761 while Scn < End_Sloc loop
762 case Src (Scn) is
763 when ' '
764 | ASCII.HT
766 if not Skipping_Comment and then not Underscore then
767 Underscore := True;
768 Index := Index + 1;
769 Buffer (Index) := ' ';
770 end if;
772 -- CR/LF/FF is the end of any comment
774 when ASCII.CR
775 | ASCII.FF
776 | ASCII.LF
778 Skipping_Comment := False;
780 when others =>
781 Underscore := False;
783 if not Skipping_Comment then
785 -- Ignore comment
787 if Src (Scn) = '-' and then Src (Scn + 1) = '-' then
788 Skipping_Comment := True;
790 else
791 Index := Index + 1;
792 Buffer (Index) := Src (Scn);
793 end if;
794 end if;
795 end case;
797 Scn := Scn + 1;
798 end loop;
799 end if;
801 if Index < 1 then
802 declare
803 S : constant String := Expr_Name (Right);
804 begin
805 if S = "..." then
806 return Default;
807 else
808 return S;
809 end if;
810 end;
812 elsif Append_Paren then
813 return Buffer (1 .. Index) & Expr_Name (Right, False) & ')';
815 else
816 return Buffer (1 .. Index) & Expr_Name (Right, False);
817 end if;
818 end;
819 end;
820 end Expression_Image;
822 end Pprint;