1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2009-2011, 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 Debug; use Debug;
29 with Lib.Util; use Lib.Util;
30 with Namet; use Namet;
31 with Nlists; use Nlists;
33 with Output; use Output;
36 with Sinfo; use Sinfo;
37 with Sinput; use Sinput;
38 with Snames; use Snames;
41 with GNAT.HTable; use GNAT.HTable;
42 with GNAT.Heap_Sort_G;
44 package body Par_SCO is
46 -----------------------
47 -- Unit Number Table --
48 -----------------------
50 -- This table parallels the SCO_Unit_Table, keeping track of the unit
51 -- numbers corresponding to the entries made in this table, so that before
52 -- writing out the SCO information to the ALI file, we can fill in the
53 -- proper dependency numbers and file names.
55 -- Note that the zero'th entry is here for convenience in sorting the
56 -- table, the real lower bound is 1.
58 package SCO_Unit_Number_Table is new Table.Table (
59 Table_Component_Type => Unit_Number_Type,
60 Table_Index_Type => SCO_Unit_Index,
61 Table_Low_Bound => 0, -- see note above on sort
63 Table_Increment => 200,
64 Table_Name => "SCO_Unit_Number_Entry");
66 ---------------------------------
67 -- Condition/Pragma Hash Table --
68 ---------------------------------
70 -- We need to be able to get to conditions quickly for handling the calls
71 -- to Set_SCO_Condition efficiently, and similarly to get to pragmas to
72 -- handle calls to Set_SCO_Pragma_Enabled. For this purpose we identify the
73 -- conditions and pragmas in the table by their starting sloc, and use this
74 -- hash table to map from these starting sloc values to SCO_Table indexes.
76 type Header_Num is new Integer range 0 .. 996;
77 -- Type for hash table headers
79 function Hash (F : Source_Ptr) return Header_Num;
80 -- Function to Hash source pointer value
82 function Equal (F1, F2 : Source_Ptr) return Boolean;
83 -- Function to test two keys for equality
85 package Condition_Pragma_Hash_Table is new Simple_HTable
86 (Header_Num, Int, 0, Source_Ptr, Hash, Equal);
87 -- The actual hash table
89 --------------------------
90 -- Internal Subprograms --
91 --------------------------
93 function Has_Decision (N : Node_Id) return Boolean;
94 -- N is the node for a subexpression. Returns True if the subexpression
95 -- contains a nested decision (i.e. either is a logical operator, or
96 -- contains a logical operator in its subtree).
98 function Is_Logical_Operator (N : Node_Id) return Boolean;
99 -- N is the node for a subexpression. This procedure just tests N to see
100 -- if it is a logical operator (including short circuit conditions, but
101 -- excluding OR and AND) and returns True if so, False otherwise, it does
102 -- no other processing.
104 procedure Process_Decisions (N : Node_Id; T : Character);
105 -- If N is Empty, has no effect. Otherwise scans the tree for the node N,
106 -- to output any decisions it contains. T is one of IEPWX (for context of
107 -- expression: if/exit when/pragma/while/expression). If T is other than X,
108 -- the node N is the conditional expression involved, and a decision is
109 -- always present (at the very least a simple decision is present at the
112 procedure Process_Decisions (L : List_Id; T : Character);
113 -- Calls above procedure for each element of the list L
115 procedure Set_Table_Entry
121 -- Append an entry to SCO_Table with fields set as per arguments
123 procedure Traverse_Declarations_Or_Statements (L : List_Id);
124 procedure Traverse_Generic_Instantiation (N : Node_Id);
125 procedure Traverse_Generic_Package_Declaration (N : Node_Id);
126 procedure Traverse_Handled_Statement_Sequence (N : Node_Id);
127 procedure Traverse_Package_Body (N : Node_Id);
128 procedure Traverse_Package_Declaration (N : Node_Id);
129 procedure Traverse_Protected_Body (N : Node_Id);
130 procedure Traverse_Subprogram_Or_Task_Body (N : Node_Id);
131 procedure Traverse_Subprogram_Declaration (N : Node_Id);
132 -- Traverse the corresponding construct, generating SCO table entries
134 procedure Write_SCOs_To_ALI_File is new Put_SCOs;
135 -- Write SCO information to the ALI file using routines in Lib.Util
143 -- Dump SCO unit table
145 Write_Line ("SCO Unit Table");
146 Write_Line ("--------------");
148 for Index in 1 .. SCO_Unit_Table.Last loop
150 UTE : SCO_Unit_Table_Entry renames SCO_Unit_Table.Table (Index);
154 Write_Int (Int (Index));
155 Write_Str (". Dep_Num = ");
156 Write_Int (Int (UTE.Dep_Num));
157 Write_Str (" From = ");
158 Write_Int (Int (UTE.From));
159 Write_Str (" To = ");
160 Write_Int (Int (UTE.To));
162 Write_Str (" File_Name = """);
164 if UTE.File_Name /= null then
165 Write_Str (UTE.File_Name.all);
173 -- Dump SCO Unit number table if it contains any entries
175 if SCO_Unit_Number_Table.Last >= 1 then
177 Write_Line ("SCO Unit Number Table");
178 Write_Line ("---------------------");
180 for Index in 1 .. SCO_Unit_Number_Table.Last loop
182 Write_Int (Int (Index));
183 Write_Str (". Unit_Number = ");
184 Write_Int (Int (SCO_Unit_Number_Table.Table (Index)));
189 -- Dump SCO table itself
192 Write_Line ("SCO Table");
193 Write_Line ("---------");
195 for Index in 1 .. SCO_Table.Last loop
197 T : SCO_Table_Entry renames SCO_Table.Table (Index);
205 Write_Str (" C1 = '");
211 Write_Str (" C2 = '");
216 if T.From /= No_Source_Location then
217 Write_Str (" From = ");
218 Write_Int (Int (T.From.Line));
220 Write_Int (Int (T.From.Col));
223 if T.To /= No_Source_Location then
224 Write_Str (" To = ");
225 Write_Int (Int (T.To.Line));
227 Write_Int (Int (T.To.Col));
233 Write_Str (" False");
245 function Equal (F1, F2 : Source_Ptr) return Boolean is
254 function Has_Decision (N : Node_Id) return Boolean is
256 function Check_Node (N : Node_Id) return Traverse_Result;
262 function Check_Node (N : Node_Id) return Traverse_Result is
264 if Is_Logical_Operator (N) then
271 function Traverse is new Traverse_Func (Check_Node);
273 -- Start of processing for Has_Decision
276 return Traverse (N) = Abandon;
283 function Hash (F : Source_Ptr) return Header_Num is
285 return Header_Num (Nat (F) mod 997);
292 procedure Initialize is
294 SCO_Unit_Number_Table.Init;
296 -- Set dummy 0'th entry in place for sort
298 SCO_Unit_Number_Table.Increment_Last;
301 -------------------------
302 -- Is_Logical_Operator --
303 -------------------------
305 function Is_Logical_Operator (N : Node_Id) return Boolean is
307 return Nkind_In (N, N_Op_Not,
310 end Is_Logical_Operator;
312 -----------------------
313 -- Process_Decisions --
314 -----------------------
316 -- Version taking a list
318 procedure Process_Decisions (L : List_Id; T : Character) is
323 while Present (N) loop
324 Process_Decisions (N, T);
328 end Process_Decisions;
330 -- Version taking a node
332 procedure Process_Decisions (N : Node_Id; T : Character) is
335 -- This is used to mark the location of a decision sequence in the SCO
336 -- table. We use it for backing out a simple decision in an expression
337 -- context that contains only NOT operators.
339 X_Not_Decision : Boolean;
340 -- This flag keeps track of whether a decision sequence in the SCO table
341 -- contains only NOT operators, and is for an expression context (T=X).
342 -- The flag will be set False if T is other than X, or if an operator
343 -- other than NOT is in the sequence.
345 function Process_Node (N : Node_Id) return Traverse_Result;
346 -- Processes one node in the traversal, looking for logical operators,
347 -- and if one is found, outputs the appropriate table entries.
349 procedure Output_Decision_Operand (N : Node_Id);
350 -- The node N is the top level logical operator of a decision, or it is
351 -- one of the operands of a logical operator belonging to a single
352 -- complex decision. This routine outputs the sequence of table entries
353 -- corresponding to the node. Note that we do not process the sub-
354 -- operands to look for further decisions, that processing is done in
355 -- Process_Decision_Operand, because we can't get decisions mixed up in
356 -- the global table. Call has no effect if N is Empty.
358 procedure Output_Element (N : Node_Id);
359 -- Node N is an operand of a logical operator that is not itself a
360 -- logical operator, or it is a simple decision. This routine outputs
361 -- the table entry for the element, with C1 set to ' '. Last is set
362 -- False, and an entry is made in the condition hash table.
364 procedure Output_Header (T : Character);
365 -- Outputs a decision header node. T is I/W/E/P for IF/WHILE/EXIT WHEN/
366 -- PRAGMA, and 'X' for the expression case.
368 procedure Process_Decision_Operand (N : Node_Id);
369 -- This is called on node N, the top level node of a decision, or on one
370 -- of its operands or suboperands after generating the full output for
371 -- the complex decision. It process the suboperands of the decision
372 -- looking for nested decisions.
374 -----------------------------
375 -- Output_Decision_Operand --
376 -----------------------------
378 procedure Output_Decision_Operand (N : Node_Id) is
388 elsif Is_Logical_Operator (N) then
389 if Nkind (N) = N_Op_Not then
396 if Nkind_In (N, N_Op_Or, N_Or_Else) then
410 Output_Decision_Operand (L);
411 Output_Decision_Operand (Right_Opnd (N));
413 -- Not a logical operator
418 end Output_Decision_Operand;
424 procedure Output_Element (N : Node_Id) is
428 Sloc_Range (N, FSloc, LSloc);
435 Condition_Pragma_Hash_Table.Set (FSloc, SCO_Table.Last);
442 procedure Output_Header (T : Character) is
443 Loc : Source_Ptr := No_Location;
444 -- Node whose sloc is used for the decision
448 when 'I' | 'E' | 'W' =>
450 -- For IF, EXIT, WHILE, the token SLOC can be found from
451 -- the SLOC of the parent of the expression.
453 Loc := Sloc (Parent (N));
457 -- For entry, the token sloc is from the N_Entry_Body. For
458 -- PRAGMA, we must get the location from the pragma node.
459 -- Argument N is the pragma argument, and we have to go up two
460 -- levels (through the pragma argument association) to get to
461 -- the pragma node itself.
463 Loc := Sloc (Parent (Parent (N)));
467 -- For an expression, no Sloc
471 -- No other possibilities
486 -- For pragmas we also must make an entry in the hash table for
487 -- later access by Set_SCO_Pragma_Enabled. We set the pragma as
488 -- disabled now, the call will change C2 to 'e' to enable the
489 -- pragma header entry.
491 SCO_Table.Table (SCO_Table.Last).C2 := 'd';
492 Condition_Pragma_Hash_Table.Set (Loc, SCO_Table.Last);
497 ------------------------------
498 -- Process_Decision_Operand --
499 ------------------------------
501 procedure Process_Decision_Operand (N : Node_Id) is
503 if Is_Logical_Operator (N) then
504 if Nkind (N) /= N_Op_Not then
505 Process_Decision_Operand (Left_Opnd (N));
506 X_Not_Decision := False;
509 Process_Decision_Operand (Right_Opnd (N));
512 Process_Decisions (N, 'X');
514 end Process_Decision_Operand;
520 function Process_Node (N : Node_Id) return Traverse_Result is
524 -- Logical operators, output table entries and then process
525 -- operands recursively to deal with nested conditions.
535 -- If outer level, then type comes from call, otherwise it
536 -- is more deeply nested and counts as X for expression.
538 if N = Process_Decisions.N then
539 T := Process_Decisions.T;
544 -- Output header for sequence
546 X_Not_Decision := T = 'X' and then Nkind (N) = N_Op_Not;
547 Mark := SCO_Table.Last;
550 -- Output the decision
552 Output_Decision_Operand (N);
554 -- If the decision was in an expression context (T = 'X')
555 -- and contained only NOT operators, then we don't output
558 if X_Not_Decision then
559 SCO_Table.Set_Last (Mark);
561 -- Otherwise, set Last in last table entry to mark end
564 SCO_Table.Table (SCO_Table.Last).Last := True;
567 -- Process any embedded decisions
569 Process_Decision_Operand (N);
575 when N_Case_Expression =>
578 -- Conditional expression, processed like an if statement
580 when N_Conditional_Expression =>
582 Cond : constant Node_Id := First (Expressions (N));
583 Thnx : constant Node_Id := Next (Cond);
584 Elsx : constant Node_Id := Next (Thnx);
586 Process_Decisions (Cond, 'I');
587 Process_Decisions (Thnx, 'X');
588 Process_Decisions (Elsx, 'X');
592 -- All other cases, continue scan
600 procedure Traverse is new Traverse_Proc (Process_Node);
602 -- Start of processing for Process_Decisions
609 -- See if we have simple decision at outer level and if so then
610 -- generate the decision entry for this simple decision. A simple
611 -- decision is a boolean expression (which is not a logical operator
612 -- or short circuit form) appearing as the operand of an IF, WHILE,
613 -- EXIT WHEN, or special PRAGMA construct.
615 if T /= 'X' and then not Is_Logical_Operator (N) then
619 -- Change Last in last table entry to True to mark end of
620 -- sequence, which is this case is only one element long.
622 SCO_Table.Table (SCO_Table.Last).Last := True;
626 end Process_Decisions;
634 procedure Write_Info_Char (C : Character) renames Write_Char;
635 -- Write one character;
637 procedure Write_Info_Initiate (Key : Character) renames Write_Char;
638 -- Start new one and write one character;
640 procedure Write_Info_Nat (N : Nat);
643 procedure Write_Info_Terminate renames Write_Eol;
644 -- Terminate current line
650 procedure Write_Info_Nat (N : Nat) is
655 procedure Debug_Put_SCOs is new Put_SCOs;
657 -- Start of processing for pscos
667 procedure SCO_Output is
669 if Debug_Flag_Dot_OO then
673 -- Sort the unit tables based on dependency numbers
675 Unit_Table_Sort : declare
677 function Lt (Op1, Op2 : Natural) return Boolean;
678 -- Comparison routine for sort call
680 procedure Move (From : Natural; To : Natural);
681 -- Move routine for sort call
687 function Lt (Op1, Op2 : Natural) return Boolean is
691 (SCO_Unit_Number_Table.Table (SCO_Unit_Index (Op1)))
694 (SCO_Unit_Number_Table.Table (SCO_Unit_Index (Op2)));
701 procedure Move (From : Natural; To : Natural) is
703 SCO_Unit_Table.Table (SCO_Unit_Index (To)) :=
704 SCO_Unit_Table.Table (SCO_Unit_Index (From));
705 SCO_Unit_Number_Table.Table (SCO_Unit_Index (To)) :=
706 SCO_Unit_Number_Table.Table (SCO_Unit_Index (From));
709 package Sorting is new GNAT.Heap_Sort_G (Move, Lt);
711 -- Start of processing for Unit_Table_Sort
714 Sorting.Sort (Integer (SCO_Unit_Table.Last));
717 -- Loop through entries in the unit table to set file name and
718 -- dependency number entries.
720 for J in 1 .. SCO_Unit_Table.Last loop
722 U : constant Unit_Number_Type := SCO_Unit_Number_Table.Table (J);
723 UTE : SCO_Unit_Table_Entry renames SCO_Unit_Table.Table (J);
725 Get_Name_String (Reference_Name (Source_Index (U)));
726 UTE.File_Name := new String'(Name_Buffer (1 .. Name_Len));
727 UTE.Dep_Num := Dependency_Num (U);
731 -- Now the tables are all setup for output to the ALI file
733 Write_SCOs_To_ALI_File;
740 procedure SCO_Record (U : Unit_Number_Type) is
745 -- Ignore call if not generating code and generating SCO's
747 if not (Generate_SCO and then Operating_Mode = Generate_Code) then
751 -- Ignore call if this unit already recorded
753 for J in 1 .. SCO_Unit_Number_Table.Last loop
754 if U = SCO_Unit_Number_Table.Table (J) then
759 -- Otherwise record starting entry
761 From := SCO_Table.Last + 1;
763 -- Get Unit (checking case of subunit)
765 Lu := Unit (Cunit (U));
767 if Nkind (Lu) = N_Subunit then
768 Lu := Proper_Body (Lu);
774 when N_Protected_Body =>
775 Traverse_Protected_Body (Lu);
777 when N_Subprogram_Body | N_Task_Body =>
778 Traverse_Subprogram_Or_Task_Body (Lu);
780 when N_Subprogram_Declaration =>
781 Traverse_Subprogram_Declaration (Lu);
783 when N_Package_Declaration =>
784 Traverse_Package_Declaration (Lu);
786 when N_Package_Body =>
787 Traverse_Package_Body (Lu);
789 when N_Generic_Package_Declaration =>
790 Traverse_Generic_Package_Declaration (Lu);
792 when N_Generic_Instantiation =>
793 Traverse_Generic_Instantiation (Lu);
797 -- All other cases of compilation units (e.g. renamings), generate
798 -- no SCO information.
803 -- Make entry for new unit in unit tables, we will fill in the file
804 -- name and dependency numbers later.
806 SCO_Unit_Table.Append (
810 To => SCO_Table.Last));
812 SCO_Unit_Number_Table.Append (U);
815 -----------------------
816 -- Set_SCO_Condition --
817 -----------------------
819 procedure Set_SCO_Condition (Cond : Node_Id; Val : Boolean) is
820 Orig : constant Node_Id := Original_Node (Cond);
825 Constant_Condition_Code : constant array (Boolean) of Character :=
826 (False => 'f', True => 't');
828 Sloc_Range (Orig, Start, Dummy);
829 Index := Condition_Pragma_Hash_Table.Get (Start);
831 -- The test here for zero is to deal with possible previous errors
834 pragma Assert (SCO_Table.Table (Index).C1 = ' ');
835 SCO_Table.Table (Index).C2 := Constant_Condition_Code (Val);
837 end Set_SCO_Condition;
839 ----------------------------
840 -- Set_SCO_Pragma_Enabled --
841 ----------------------------
843 procedure Set_SCO_Pragma_Enabled (Loc : Source_Ptr) is
847 -- Note: the reason we use the Sloc value as the key is that in the
848 -- generic case, the call to this procedure is made on a copy of the
849 -- original node, so we can't use the Node_Id value.
851 Index := Condition_Pragma_Hash_Table.Get (Loc);
853 -- The test here for zero is to deal with possible previous errors
856 pragma Assert (SCO_Table.Table (Index).C1 = 'P');
857 SCO_Table.Table (Index).C2 := 'e';
859 end Set_SCO_Pragma_Enabled;
861 ---------------------
862 -- Set_Table_Entry --
863 ---------------------
865 procedure Set_Table_Entry
872 function To_Source_Location (S : Source_Ptr) return Source_Location;
873 -- Converts Source_Ptr value to Source_Location (line/col) format
875 ------------------------
876 -- To_Source_Location --
877 ------------------------
879 function To_Source_Location (S : Source_Ptr) return Source_Location is
881 if S = No_Location then
882 return No_Source_Location;
885 (Line => Get_Logical_Line_Number (S),
886 Col => Get_Column_Number (S));
888 end To_Source_Location;
890 -- Start of processing for Set_Table_Entry
896 From => To_Source_Location (From),
897 To => To_Source_Location (To),
901 -----------------------------------------
902 -- Traverse_Declarations_Or_Statements --
903 -----------------------------------------
905 -- Tables used by Traverse_Declarations_Or_Statements for temporarily
906 -- holding statement and decision entries. These are declared globally
907 -- since they are shared by recursive calls to this procedure.
909 type SC_Entry is record
914 -- Used to store a single entry in the following table, From:To represents
915 -- the range of entries in the CS line entry, and typ is the type, with
916 -- space meaning that no type letter will accompany the entry.
918 package SC is new Table.Table (
919 Table_Component_Type => SC_Entry,
920 Table_Index_Type => Nat,
921 Table_Low_Bound => 1,
922 Table_Initial => 1000,
923 Table_Increment => 200,
924 Table_Name => "SCO_SC");
925 -- Used to store statement components for a CS entry to be output
926 -- as a result of the call to this procedure. SC.Last is the last
927 -- entry stored, so the current statement sequence is represented
928 -- by SC_Array (SC_First .. SC.Last), where SC_First is saved on
929 -- entry to each recursive call to the routine.
931 -- Extend_Statement_Sequence adds an entry to this array, and then
932 -- Set_Statement_Entry clears the entries starting with SC_First,
933 -- copying these entries to the main SCO output table. The reason that
934 -- we do the temporary caching of results in this array is that we want
935 -- the SCO table entries for a given CS line to be contiguous, and the
936 -- processing may output intermediate entries such as decision entries.
938 type SD_Entry is record
943 -- Used to store a single entry in the following table. Nod is the node to
944 -- be searched for decisions for the case of Process_Decisions_Defer with a
945 -- node argument (with Lst set to No_List. Lst is the list to be searched
946 -- for decisions for the case of Process_Decisions_Defer with a List
947 -- argument (in which case Nod is set to Empty).
949 package SD is new Table.Table (
950 Table_Component_Type => SD_Entry,
951 Table_Index_Type => Nat,
952 Table_Low_Bound => 1,
953 Table_Initial => 1000,
954 Table_Increment => 200,
955 Table_Name => "SCO_SD");
956 -- Used to store possible decision information. Instead of calling the
957 -- Process_Decisions procedures directly, we call Process_Decisions_Defer,
958 -- which simply stores the arguments in this table. Then when we clear
959 -- out a statement sequence using Set_Statement_Entry, after generating
960 -- the CS lines for the statements, the entries in this table result in
961 -- calls to Process_Decision. The reason for doing things this way is to
962 -- ensure that decisions are output after the CS line for the statements
963 -- in which the decisions occur.
965 procedure Traverse_Declarations_Or_Statements (L : List_Id) is
969 SC_First : constant Nat := SC.Last + 1;
970 SD_First : constant Nat := SD.Last + 1;
971 -- Record first entries used in SC/SD at this recursive level
973 procedure Extend_Statement_Sequence (N : Node_Id; Typ : Character);
974 -- Extend the current statement sequence to encompass the node N. Typ
975 -- is the letter that identifies the type of statement/declaration that
976 -- is being added to the sequence.
978 procedure Extend_Statement_Sequence
982 -- This version extends the current statement sequence with an entry
983 -- that starts with the first token of From, and ends with the last
984 -- token of To. It is used for example in a CASE statement to cover
985 -- the range from the CASE token to the last token of the expression.
987 procedure Set_Statement_Entry;
988 -- If Start is No_Location, does nothing, otherwise outputs a SCO_Table
989 -- statement entry for the range Start-Stop and then sets both Start
990 -- and Stop to No_Location.
991 -- What are Start and Stop??? This comment seems completely unrelated
992 -- to the implementation!???
993 -- Unconditionally sets Term to True. What is Term???
994 -- This is called when we find a statement or declaration that generates
995 -- its own table entry, so that we must end the current statement
998 procedure Process_Decisions_Defer (N : Node_Id; T : Character);
999 pragma Inline (Process_Decisions_Defer);
1000 -- This routine is logically the same as Process_Decisions, except that
1001 -- the arguments are saved in the SD table, for later processing when
1002 -- Set_Statement_Entry is called, which goes through the saved entries
1003 -- making the corresponding calls to Process_Decision.
1005 procedure Process_Decisions_Defer (L : List_Id; T : Character);
1006 pragma Inline (Process_Decisions_Defer);
1007 -- Same case for list arguments, deferred call to Process_Decisions
1009 -------------------------
1010 -- Set_Statement_Entry --
1011 -------------------------
1013 procedure Set_Statement_Entry is
1015 SC_Last : constant Int := SC.Last;
1016 SD_Last : constant Int := SD.Last;
1019 -- Output statement entries from saved entries in SC table
1021 for J in SC_First .. SC_Last loop
1022 if J = SC_First then
1029 SCE : SC_Entry renames SC.Table (J);
1036 Last => (J = SC_Last));
1040 -- Clear out used section of SC table
1042 SC.Set_Last (SC_First - 1);
1044 -- Output any embedded decisions
1046 for J in SD_First .. SD_Last loop
1048 SDE : SD_Entry renames SD.Table (J);
1050 if Present (SDE.Nod) then
1051 Process_Decisions (SDE.Nod, SDE.Typ);
1053 Process_Decisions (SDE.Lst, SDE.Typ);
1058 -- Clear out used section of SD table
1060 SD.Set_Last (SD_First - 1);
1061 end Set_Statement_Entry;
1063 -------------------------------
1064 -- Extend_Statement_Sequence --
1065 -------------------------------
1067 procedure Extend_Statement_Sequence (N : Node_Id; Typ : Character) is
1071 Sloc_Range (N, F, T);
1072 SC.Append ((F, T, Typ));
1073 end Extend_Statement_Sequence;
1075 procedure Extend_Statement_Sequence
1083 Sloc_Range (From, F, Dummy);
1084 Sloc_Range (To, Dummy, T);
1085 SC.Append ((F, T, Typ));
1086 end Extend_Statement_Sequence;
1088 -----------------------------
1089 -- Process_Decisions_Defer --
1090 -----------------------------
1092 procedure Process_Decisions_Defer (N : Node_Id; T : Character) is
1094 SD.Append ((N, No_List, T));
1095 end Process_Decisions_Defer;
1097 procedure Process_Decisions_Defer (L : List_Id; T : Character) is
1099 SD.Append ((Empty, L, T));
1100 end Process_Decisions_Defer;
1102 -- Start of processing for Traverse_Declarations_Or_Statements
1105 if Is_Non_Empty_List (L) then
1107 -- Loop through statements or declarations
1110 while Present (N) loop
1112 -- Initialize or extend current statement sequence. Note that for
1113 -- special cases such as IF and Case statements we will modify
1114 -- the range to exclude internal statements that should not be
1115 -- counted as part of the current statement sequence.
1119 -- Package declaration
1121 when N_Package_Declaration =>
1122 Set_Statement_Entry;
1123 Traverse_Package_Declaration (N);
1125 -- Generic package declaration
1127 when N_Generic_Package_Declaration =>
1128 Set_Statement_Entry;
1129 Traverse_Generic_Package_Declaration (N);
1133 when N_Package_Body =>
1134 Set_Statement_Entry;
1135 Traverse_Package_Body (N);
1137 -- Subprogram declaration
1139 when N_Subprogram_Declaration =>
1140 Process_Decisions_Defer
1141 (Parameter_Specifications (Specification (N)), 'X');
1142 Set_Statement_Entry;
1144 -- Generic subprogram declaration
1146 when N_Generic_Subprogram_Declaration =>
1147 Process_Decisions_Defer
1148 (Generic_Formal_Declarations (N), 'X');
1149 Process_Decisions_Defer
1150 (Parameter_Specifications (Specification (N)), 'X');
1151 Set_Statement_Entry;
1153 -- Task or subprogram body
1155 when N_Task_Body | N_Subprogram_Body =>
1156 Set_Statement_Entry;
1157 Traverse_Subprogram_Or_Task_Body (N);
1161 when N_Entry_Body =>
1163 Cond : constant Node_Id :=
1164 Condition (Entry_Body_Formal_Part (N));
1167 Set_Statement_Entry;
1169 if Present (Cond) then
1170 Process_Decisions_Defer (Cond, 'G');
1173 Traverse_Subprogram_Or_Task_Body (N);
1178 when N_Protected_Body =>
1179 Set_Statement_Entry;
1180 Traverse_Protected_Body (N);
1182 -- Exit statement, which is an exit statement in the SCO sense,
1183 -- so it is included in the current statement sequence, but
1184 -- then it terminates this sequence. We also have to process
1185 -- any decisions in the exit statement expression.
1187 when N_Exit_Statement =>
1188 Extend_Statement_Sequence (N, ' ');
1189 Process_Decisions_Defer (Condition (N), 'E');
1190 Set_Statement_Entry;
1192 -- Label, which breaks the current statement sequence, but the
1193 -- label itself is not included in the next statement sequence,
1194 -- since it generates no code.
1197 Set_Statement_Entry;
1199 -- Block statement, which breaks the current statement sequence
1201 when N_Block_Statement =>
1202 Set_Statement_Entry;
1203 Traverse_Declarations_Or_Statements (Declarations (N));
1204 Traverse_Handled_Statement_Sequence
1205 (Handled_Statement_Sequence (N));
1207 -- If statement, which breaks the current statement sequence,
1208 -- but we include the condition in the current sequence.
1210 when N_If_Statement =>
1211 Extend_Statement_Sequence (N, Condition (N), 'I');
1212 Process_Decisions_Defer (Condition (N), 'I');
1213 Set_Statement_Entry;
1215 -- Now we traverse the statements in the THEN part
1217 Traverse_Declarations_Or_Statements (Then_Statements (N));
1219 -- Loop through ELSIF parts if present
1221 if Present (Elsif_Parts (N)) then
1223 Elif : Node_Id := First (Elsif_Parts (N));
1226 while Present (Elif) loop
1228 -- We generate a statement sequence for the
1229 -- construct "ELSIF condition", so that we have
1230 -- a statement for the resulting decisions.
1232 Extend_Statement_Sequence
1233 (Elif, Condition (Elif), 'I');
1234 Process_Decisions_Defer (Condition (Elif), 'I');
1235 Set_Statement_Entry;
1237 -- Traverse the statements in the ELSIF
1239 Traverse_Declarations_Or_Statements
1240 (Then_Statements (Elif));
1246 -- Finally traverse the ELSE statements if present
1248 Traverse_Declarations_Or_Statements (Else_Statements (N));
1250 -- Case statement, which breaks the current statement sequence,
1251 -- but we include the expression in the current sequence.
1253 when N_Case_Statement =>
1254 Extend_Statement_Sequence (N, Expression (N), 'C');
1255 Process_Decisions_Defer (Expression (N), 'X');
1256 Set_Statement_Entry;
1258 -- Process case branches
1263 Alt := First (Alternatives (N));
1264 while Present (Alt) loop
1265 Traverse_Declarations_Or_Statements (Statements (Alt));
1270 -- Unconditional exit points, which are included in the current
1271 -- statement sequence, but then terminate it
1273 when N_Requeue_Statement |
1275 N_Raise_Statement =>
1276 Extend_Statement_Sequence (N, ' ');
1277 Set_Statement_Entry;
1279 -- Simple return statement. which is an exit point, but we
1280 -- have to process the return expression for decisions.
1282 when N_Simple_Return_Statement =>
1283 Extend_Statement_Sequence (N, ' ');
1284 Process_Decisions_Defer (Expression (N), 'X');
1285 Set_Statement_Entry;
1287 -- Extended return statement
1289 when N_Extended_Return_Statement =>
1290 Extend_Statement_Sequence
1291 (N, Last (Return_Object_Declarations (N)), 'R');
1292 Process_Decisions_Defer
1293 (Return_Object_Declarations (N), 'X');
1294 Set_Statement_Entry;
1296 Traverse_Handled_Statement_Sequence
1297 (Handled_Statement_Sequence (N));
1299 -- Loop ends the current statement sequence, but we include
1300 -- the iteration scheme if present in the current sequence.
1301 -- But the body of the loop starts a new sequence, since it
1302 -- may not be executed as part of the current sequence.
1304 when N_Loop_Statement =>
1305 if Present (Iteration_Scheme (N)) then
1307 -- If iteration scheme present, extend the current
1308 -- statement sequence to include the iteration scheme
1309 -- and process any decisions it contains.
1312 ISC : constant Node_Id := Iteration_Scheme (N);
1317 if Present (Condition (ISC)) then
1318 Extend_Statement_Sequence (N, ISC, 'W');
1319 Process_Decisions_Defer (Condition (ISC), 'W');
1324 Extend_Statement_Sequence (N, ISC, 'F');
1325 Process_Decisions_Defer
1326 (Loop_Parameter_Specification (ISC), 'X');
1331 Set_Statement_Entry;
1332 Traverse_Declarations_Or_Statements (Statements (N));
1337 Extend_Statement_Sequence (N, 'P');
1339 -- Processing depends on the kind of pragma
1341 case Pragma_Name (N) is
1345 Name_Postcondition =>
1347 -- For Assert/Check/Precondition/Postcondition, we
1348 -- must generate a P entry for the decision. Note that
1349 -- this is done unconditionally at this stage. Output
1350 -- for disabled pragmas is suppressed later on, when
1351 -- we output the decision line in Put_SCOs.
1354 Nam : constant Name_Id :=
1355 Chars (Pragma_Identifier (N));
1357 First (Pragma_Argument_Associations (N));
1360 if Nam = Name_Check then
1364 Process_Decisions_Defer (Expression (Arg), 'P');
1367 -- For all other pragmas, we generate decision entries
1368 -- for any embedded expressions.
1371 Process_Decisions_Defer (N, 'X');
1374 -- Object declaration. Ignored if Prev_Ids is set, since the
1375 -- parser generates multiple instances of the whole declaration
1376 -- if there is more than one identifier declared, and we only
1377 -- want one entry in the SCO's, so we take the first, for which
1378 -- Prev_Ids is False.
1380 when N_Object_Declaration =>
1381 if not Prev_Ids (N) then
1382 Extend_Statement_Sequence (N, 'o');
1384 if Has_Decision (N) then
1385 Process_Decisions_Defer (N, 'X');
1389 -- All other cases, which extend the current statement sequence
1390 -- but do not terminate it, even if they have nested decisions.
1394 -- Determine required type character code
1401 when N_Full_Type_Declaration |
1402 N_Incomplete_Type_Declaration |
1403 N_Private_Type_Declaration |
1404 N_Private_Extension_Declaration =>
1407 when N_Subtype_Declaration =>
1410 when N_Renaming_Declaration =>
1413 when N_Generic_Instantiation =>
1420 Extend_Statement_Sequence (N, Typ);
1423 -- Process any embedded decisions
1425 if Has_Decision (N) then
1426 Process_Decisions_Defer (N, 'X');
1433 Set_Statement_Entry;
1435 end Traverse_Declarations_Or_Statements;
1437 ------------------------------------
1438 -- Traverse_Generic_Instantiation --
1439 ------------------------------------
1441 procedure Traverse_Generic_Instantiation (N : Node_Id) is
1446 -- First we need a statement entry to cover the instantiation
1448 Sloc_Range (N, First, Last);
1456 -- Now output any embedded decisions
1458 Process_Decisions (N, 'X');
1459 end Traverse_Generic_Instantiation;
1461 ------------------------------------------
1462 -- Traverse_Generic_Package_Declaration --
1463 ------------------------------------------
1465 procedure Traverse_Generic_Package_Declaration (N : Node_Id) is
1467 Process_Decisions (Generic_Formal_Declarations (N), 'X');
1468 Traverse_Package_Declaration (N);
1469 end Traverse_Generic_Package_Declaration;
1471 -----------------------------------------
1472 -- Traverse_Handled_Statement_Sequence --
1473 -----------------------------------------
1475 procedure Traverse_Handled_Statement_Sequence (N : Node_Id) is
1479 -- For package bodies without a statement part, the parser adds an empty
1480 -- one, to normalize the representation. The null statement therein,
1481 -- which does not come from source, does not get a SCO.
1483 if Present (N) and then Comes_From_Source (N) then
1484 Traverse_Declarations_Or_Statements (Statements (N));
1486 if Present (Exception_Handlers (N)) then
1487 Handler := First (Exception_Handlers (N));
1488 while Present (Handler) loop
1489 Traverse_Declarations_Or_Statements (Statements (Handler));
1494 end Traverse_Handled_Statement_Sequence;
1496 ---------------------------
1497 -- Traverse_Package_Body --
1498 ---------------------------
1500 procedure Traverse_Package_Body (N : Node_Id) is
1502 Traverse_Declarations_Or_Statements (Declarations (N));
1503 Traverse_Handled_Statement_Sequence (Handled_Statement_Sequence (N));
1504 end Traverse_Package_Body;
1506 ----------------------------------
1507 -- Traverse_Package_Declaration --
1508 ----------------------------------
1510 procedure Traverse_Package_Declaration (N : Node_Id) is
1511 Spec : constant Node_Id := Specification (N);
1513 Traverse_Declarations_Or_Statements (Visible_Declarations (Spec));
1514 Traverse_Declarations_Or_Statements (Private_Declarations (Spec));
1515 end Traverse_Package_Declaration;
1517 -----------------------------
1518 -- Traverse_Protected_Body --
1519 -----------------------------
1521 procedure Traverse_Protected_Body (N : Node_Id) is
1523 Traverse_Declarations_Or_Statements (Declarations (N));
1524 end Traverse_Protected_Body;
1526 --------------------------------------
1527 -- Traverse_Subprogram_Or_Task_Body --
1528 --------------------------------------
1530 procedure Traverse_Subprogram_Or_Task_Body (N : Node_Id) is
1532 Traverse_Declarations_Or_Statements (Declarations (N));
1533 Traverse_Handled_Statement_Sequence (Handled_Statement_Sequence (N));
1534 end Traverse_Subprogram_Or_Task_Body;
1536 -------------------------------------
1537 -- Traverse_Subprogram_Declaration --
1538 -------------------------------------
1540 procedure Traverse_Subprogram_Declaration (N : Node_Id) is
1541 ADN : constant Node_Id := Aux_Decls_Node (Parent (N));
1543 Traverse_Declarations_Or_Statements (Config_Pragmas (ADN));
1544 Traverse_Declarations_Or_Statements (Declarations (ADN));
1545 Traverse_Declarations_Or_Statements (Pragmas_After (ADN));
1546 end Traverse_Subprogram_Declaration;