summaryrefslogtreecommitdiff
path: root/gcc/ada/par_sco.adb
diff options
context:
space:
mode:
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2012-07-12 10:49:10 +0000
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2012-07-12 10:49:10 +0000
commitaee191caa038c79baa7fafea4ae2516312ae508e (patch)
tree9754099aee8625dc123639e1fe1bb60689179ee3 /gcc/ada/par_sco.adb
parentda2e82e93b2eea1ceb9313addf4168df97736c6c (diff)
downloadgcc-aee191caa038c79baa7fafea4ae2516312ae508e.tar.gz
2012-07-12 Robert Dewar <dewar@adacore.com>
* s-atopri.adb, s-atopri.ads: Minor reformatting. 2012-07-12 Robert Dewar <dewar@adacore.com> * ali.adb: Add circuitry to read new named form of restrictions lines. * debug.adb: Add doc for new -gnatd.R switch (used positional notation for output of restrictions data in ali file). * lib-writ.adb: Implement new named format for restrictions lines. * lib-writ.ads: Add documentation for new named format for restrictions in ali files. * restrict.adb, restrict.ads, sem_prag.adb: Update comments. * rident.ads: Go back to withing System.Rident * s-rident.ads: Add extensive comment on dealing with consistency checking. 2012-07-12 Thomas Quinot <quinot@adacore.com> * par_sco.adb, scos.ads: Emit detailed SCOs for SELECT statements. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@189438 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada/par_sco.adb')
-rw-r--r--gcc/ada/par_sco.adb851
1 files changed, 498 insertions, 353 deletions
diff --git a/gcc/ada/par_sco.adb b/gcc/ada/par_sco.adb
index 28fa18681ce..766621ada52 100644
--- a/gcc/ada/par_sco.adb
+++ b/gcc/ada/par_sco.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2009-2011, Free Software Foundation, Inc. --
+-- Copyright (C) 2009-2012, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -69,9 +69,9 @@ package body Par_SCO is
-- We need to be able to get to conditions quickly for handling the calls
-- to Set_SCO_Condition efficiently, and similarly to get to pragmas to
- -- handle calls to Set_SCO_Pragma_Enabled. For this purpose we identify
- -- the conditions and pragmas in the table by their starting sloc, and use
- -- this hash table to map from these sloc values to SCO_Table indexes.
+ -- handle calls to Set_SCO_Pragma_Enabled. For this purpose we identify the
+ -- conditions and pragmas in the table by their starting sloc, and use this
+ -- hash table to map from these sloc values to SCO_Table indexes.
type Header_Num is new Integer range 0 .. 996;
-- Type for hash table headers
@@ -133,13 +133,16 @@ package body Par_SCO is
-- F/T/S/E for a valid dominance marker, or ' ' for no dominant
N : Node_Id;
- -- Node providing the sloc(s) for the dominance marker
+ -- Node providing the Sloc(s) for the dominance marker
end record;
No_Dominant : constant Dominant_Info := (' ', Empty);
procedure Traverse_Declarations_Or_Statements
(L : List_Id;
- D : Dominant_Info := No_Dominant);
+ D : Dominant_Info := No_Dominant;
+ P : Node_Id := Empty);
+ -- Process L, a list of statements or declarations dominated by D.
+ -- If P is present, it is processed as though it had been prepended to L.
procedure Traverse_Generic_Instantiation (N : Node_Id);
procedure Traverse_Generic_Package_Declaration (N : Node_Id);
@@ -328,9 +331,7 @@ package body Par_SCO is
function Is_Logical_Operator (N : Node_Id) return Boolean is
begin
- return Nkind_In (N, N_Op_Not,
- N_And_Then,
- N_Or_Else);
+ return Nkind_In (N, N_Op_Not, N_And_Then, N_Or_Else);
end Is_Logical_Operator;
-----------------------
@@ -475,7 +476,7 @@ package body Par_SCO is
procedure Output_Header (T : Character) is
Loc : Source_Ptr := No_Location;
- -- Node whose sloc is used for the decision
+ -- Node whose Sloc is used for the decision
begin
case T is
@@ -488,13 +489,22 @@ package body Par_SCO is
when 'G' | 'P' =>
- -- For entry, the token sloc is from the N_Entry_Body. For
- -- PRAGMA, we must get the location from the pragma node.
+ -- For entry guard, the token sloc is from the N_Entry_Body.
+ -- For PRAGMA, we must get the location from the pragma node.
-- Argument N is the pragma argument, and we have to go up two
-- levels (through the pragma argument association) to get to
- -- the pragma node itself.
-
- Loc := Sloc (Parent (Parent (N)));
+ -- the pragma node itself. For the guard on a select
+ -- alternative, we do not have access to the token location
+ -- for the WHEN, so we use the sloc of the condition itself.
+
+ if Nkind_In (Parent (N), N_Accept_Alternative,
+ N_Delay_Alternative,
+ N_Terminate_Alternative)
+ then
+ Loc := Sloc (N);
+ else
+ Loc := Sloc (Parent (Parent (N)));
+ end if;
when 'X' =>
@@ -547,10 +557,7 @@ package body Par_SCO is
-- Logical operators, output table entries and then process
-- operands recursively to deal with nested conditions.
- when N_And_Then |
- N_Or_Else |
- N_Op_Not =>
-
+ when N_And_Then | N_Or_Else | N_Op_Not =>
declare
T : Character;
@@ -1036,7 +1043,8 @@ package body Par_SCO is
procedure Traverse_Declarations_Or_Statements
(L : List_Id;
- D : Dominant_Info := No_Dominant)
+ D : Dominant_Info := No_Dominant;
+ P : Node_Id := Empty)
is
Current_Dominant : Dominant_Info := D;
-- Dominance information for the current basic block
@@ -1044,8 +1052,7 @@ package body Par_SCO is
Current_Test : Node_Id;
-- Conditional node (N_If_Statement or N_Elsiif being processed
- N : Node_Id;
- Dummy : Source_Ptr;
+ N : Node_Id;
SC_First : constant Nat := SC.Last + 1;
SD_First : constant Nat := SD.Last + 1;
@@ -1056,15 +1063,6 @@ package body Par_SCO is
-- is the letter that identifies the type of statement/declaration that
-- is being added to the sequence.
- procedure Extend_Statement_Sequence
- (From : Node_Id;
- To : Node_Id;
- Typ : Character);
- -- This version extends the current statement sequence with an entry
- -- that starts with the first token of From, and ends with the last
- -- token of To. It is used for example in a CASE statement to cover
- -- the range from the CASE token to the last token of the expression.
-
procedure Set_Statement_Entry;
-- Output CS entries for all statements saved in table SC, and end the
-- current CS sequence.
@@ -1080,6 +1078,9 @@ package body Par_SCO is
pragma Inline (Process_Decisions_Defer);
-- Same case for list arguments, deferred call to Process_Decisions
+ procedure Traverse_One (N : Node_Id);
+ -- Traverse one declaration or statement
+
-------------------------
-- Set_Statement_Entry --
-------------------------
@@ -1180,24 +1181,50 @@ package body Par_SCO is
-------------------------------
procedure Extend_Statement_Sequence (N : Node_Id; Typ : Character) is
- F : Source_Ptr;
- T : Source_Ptr;
+ F : Source_Ptr;
+ T : Source_Ptr;
+ Dummy : Source_Ptr;
+ To_Node : Node_Id := Empty;
+
begin
Sloc_Range (N, F, T);
- SC.Append ((N, F, T, Typ));
- end Extend_Statement_Sequence;
- procedure Extend_Statement_Sequence
- (From : Node_Id;
- To : Node_Id;
- Typ : Character)
- is
- F : Source_Ptr;
- T : Source_Ptr;
- begin
- Sloc_Range (From, F, Dummy);
- Sloc_Range (To, Dummy, T);
- SC.Append ((From, F, T, Typ));
+ case Nkind (N) is
+ when N_Accept_Statement =>
+ if Present (Parameter_Specifications (N)) then
+ To_Node := Last (Parameter_Specifications (N));
+ elsif Present (Entry_Index (N)) then
+ To_Node := Entry_Index (N);
+ end if;
+
+ when N_Case_Statement =>
+ To_Node := Expression (N);
+
+ when N_If_Statement | N_Elsif_Part =>
+ To_Node := Condition (N);
+
+ when N_Extended_Return_Statement =>
+ To_Node := Last (Return_Object_Declarations (N));
+
+ when N_Loop_Statement =>
+ To_Node := Iteration_Scheme (N);
+
+ when N_Selective_Accept |
+ N_Timed_Entry_Call |
+ N_Conditional_Entry_Call |
+ N_Asynchronous_Select =>
+ T := F;
+
+ when others =>
+ null;
+
+ end case;
+
+ if Present (To_Node) then
+ Sloc_Range (To_Node, Dummy, T);
+ end if;
+
+ SC.Append ((N, F, T, Typ));
end Extend_Statement_Sequence;
-----------------------------
@@ -1214,430 +1241,548 @@ package body Par_SCO is
SD.Append ((Empty, L, T, Current_Pragma_Sloc));
end Process_Decisions_Defer;
- -- Start of processing for Traverse_Declarations_Or_Statements
+ ------------------
+ -- Traverse_One --
+ ------------------
- begin
- if Is_Non_Empty_List (L) then
+ procedure Traverse_One (N : Node_Id) is
+ begin
+ -- Initialize or extend current statement sequence. Note that for
+ -- special cases such as IF and Case statements we will modify
+ -- the range to exclude internal statements that should not be
+ -- counted as part of the current statement sequence.
- -- Loop through statements or declarations
+ case Nkind (N) is
- N := First (L);
- while Present (N) loop
+ -- Package declaration
- -- Initialize or extend current statement sequence. Note that for
- -- special cases such as IF and Case statements we will modify
- -- the range to exclude internal statements that should not be
- -- counted as part of the current statement sequence.
+ when N_Package_Declaration =>
+ Set_Statement_Entry;
+ Traverse_Package_Declaration (N);
- case Nkind (N) is
+ -- Generic package declaration
- -- Package declaration
+ when N_Generic_Package_Declaration =>
+ Set_Statement_Entry;
+ Traverse_Generic_Package_Declaration (N);
- when N_Package_Declaration =>
- Set_Statement_Entry;
- Traverse_Package_Declaration (N);
+ -- Package body
- -- Generic package declaration
+ when N_Package_Body =>
+ Set_Statement_Entry;
+ Traverse_Package_Body (N);
- when N_Generic_Package_Declaration =>
- Set_Statement_Entry;
- Traverse_Generic_Package_Declaration (N);
+ -- Subprogram declaration
- -- Package body
+ when N_Subprogram_Declaration =>
+ Process_Decisions_Defer
+ (Parameter_Specifications (Specification (N)), 'X');
- when N_Package_Body =>
- Set_Statement_Entry;
- Traverse_Package_Body (N);
+ -- Generic subprogram declaration
+
+ when N_Generic_Subprogram_Declaration =>
+ Process_Decisions_Defer
+ (Generic_Formal_Declarations (N), 'X');
+ Process_Decisions_Defer
+ (Parameter_Specifications (Specification (N)), 'X');
- -- Subprogram declaration
+ -- Task or subprogram body
- when N_Subprogram_Declaration =>
- Process_Decisions_Defer
- (Parameter_Specifications (Specification (N)), 'X');
+ when N_Task_Body | N_Subprogram_Body =>
+ Set_Statement_Entry;
+ Traverse_Subprogram_Or_Task_Body (N);
- -- Generic subprogram declaration
+ -- Entry body
- when N_Generic_Subprogram_Declaration =>
- Process_Decisions_Defer
- (Generic_Formal_Declarations (N), 'X');
- Process_Decisions_Defer
- (Parameter_Specifications (Specification (N)), 'X');
+ when N_Entry_Body =>
+ declare
+ Cond : constant Node_Id :=
+ Condition (Entry_Body_Formal_Part (N));
- -- Task or subprogram body
+ Inner_Dominant : Dominant_Info := No_Dominant;
- when N_Task_Body | N_Subprogram_Body =>
+ begin
Set_Statement_Entry;
- Traverse_Subprogram_Or_Task_Body (N);
- -- Entry body
+ if Present (Cond) then
+ Process_Decisions_Defer (Cond, 'G');
+
+ -- For an entry body with a barrier, the entry body
+ -- is dominanted by a True evaluation of the barrier.
- when N_Entry_Body =>
+ Inner_Dominant := ('T', N);
+ end if;
+
+ Traverse_Subprogram_Or_Task_Body (N, Inner_Dominant);
+ end;
+
+ -- Protected body
+
+ when N_Protected_Body =>
+ Set_Statement_Entry;
+ Traverse_Protected_Body (N);
+
+ -- Exit statement, which is an exit statement in the SCO sense,
+ -- so it is included in the current statement sequence, but
+ -- then it terminates this sequence. We also have to process
+ -- any decisions in the exit statement expression.
+
+ when N_Exit_Statement =>
+ Extend_Statement_Sequence (N, ' ');
+ Process_Decisions_Defer (Condition (N), 'E');
+ Set_Statement_Entry;
+
+ -- If condition is present, then following statement is
+ -- only executed if the condition evaluates to False.
+
+ if Present (Condition (N)) then
+ Current_Dominant := ('F', N);
+ else
+ Current_Dominant := No_Dominant;
+ end if;
+
+ -- Label, which breaks the current statement sequence, but the
+ -- label itself is not included in the next statement sequence,
+ -- since it generates no code.
+
+ when N_Label =>
+ Set_Statement_Entry;
+ Current_Dominant := No_Dominant;
+
+ -- Block statement, which breaks the current statement sequence
+
+ when N_Block_Statement =>
+ Set_Statement_Entry;
+ Traverse_Declarations_Or_Statements
+ (L => Declarations (N),
+ D => Current_Dominant);
+ Traverse_Handled_Statement_Sequence
+ (N => Handled_Statement_Sequence (N),
+ D => Current_Dominant);
+
+ -- If statement, which breaks the current statement sequence,
+ -- but we include the condition in the current sequence.
+
+ when N_If_Statement =>
+ Current_Test := N;
+ Extend_Statement_Sequence (N, 'I');
+ Process_Decisions_Defer (Condition (N), 'I');
+ Set_Statement_Entry;
+
+ -- Now we traverse the statements in the THEN part
+
+ Traverse_Declarations_Or_Statements
+ (L => Then_Statements (N),
+ D => ('T', N));
+
+ -- Loop through ELSIF parts if present
+
+ if Present (Elsif_Parts (N)) then
declare
- Cond : constant Node_Id :=
- Condition (Entry_Body_Formal_Part (N));
- Inner_Dominant : Dominant_Info := No_Dominant;
- begin
- Set_Statement_Entry;
+ Saved_Dominant : constant Dominant_Info :=
+ Current_Dominant;
- if Present (Cond) then
- Process_Decisions_Defer (Cond, 'G');
+ Elif : Node_Id := First (Elsif_Parts (N));
- -- For an entry body with a barrier, the entry body
- -- is dominanted by a True evaluation of the barrier.
+ begin
+ while Present (Elif) loop
- Inner_Dominant := ('T', N);
- end if;
+ -- An Elsif is executed only if the previous test
+ -- got a FALSE outcome.
- Traverse_Subprogram_Or_Task_Body (N, Inner_Dominant);
- end;
+ Current_Dominant := ('F', Current_Test);
- -- Protected body
+ -- Now update current test information
- when N_Protected_Body =>
- Set_Statement_Entry;
- Traverse_Protected_Body (N);
+ Current_Test := Elif;
- -- Exit statement, which is an exit statement in the SCO sense,
- -- so it is included in the current statement sequence, but
- -- then it terminates this sequence. We also have to process
- -- any decisions in the exit statement expression.
+ -- We generate a statement sequence for the
+ -- construct "ELSIF condition", so that we have
+ -- a statement for the resulting decisions.
- when N_Exit_Statement =>
- Extend_Statement_Sequence (N, ' ');
- Process_Decisions_Defer (Condition (N), 'E');
- Set_Statement_Entry;
+ Extend_Statement_Sequence (Elif, 'I');
+ Process_Decisions_Defer (Condition (Elif), 'I');
+ Set_Statement_Entry;
- -- If condition is present, then following statement is
- -- only executed if the condition evaluates to False.
+ -- An ELSIF part is never guaranteed to have
+ -- been executed, following statements are only
+ -- dominated by the initial IF statement.
- if Present (Condition (N)) then
- Current_Dominant := ('F', N);
- else
- Current_Dominant := No_Dominant;
- end if;
+ Current_Dominant := Saved_Dominant;
- -- Label, which breaks the current statement sequence, but the
- -- label itself is not included in the next statement sequence,
- -- since it generates no code.
+ -- Traverse the statements in the ELSIF
- when N_Label =>
- Set_Statement_Entry;
- Current_Dominant := No_Dominant;
+ Traverse_Declarations_Or_Statements
+ (L => Then_Statements (Elif),
+ D => ('T', Elif));
+ Next (Elif);
+ end loop;
+ end;
+ end if;
- -- Block statement, which breaks the current statement sequence
+ -- Finally traverse the ELSE statements if present
- when N_Block_Statement =>
- Set_Statement_Entry;
- Traverse_Declarations_Or_Statements
- (L => Declarations (N),
- D => Current_Dominant);
- Traverse_Handled_Statement_Sequence
- (N => Handled_Statement_Sequence (N),
- D => Current_Dominant);
+ Traverse_Declarations_Or_Statements
+ (L => Else_Statements (N),
+ D => ('F', Current_Test));
- -- If statement, which breaks the current statement sequence,
- -- but we include the condition in the current sequence.
+ -- CASE statement, which breaks the current statement sequence,
+ -- but we include the expression in the current sequence.
- when N_If_Statement =>
- Current_Test := N;
- Extend_Statement_Sequence (N, Condition (N), 'I');
- Process_Decisions_Defer (Condition (N), 'I');
- Set_Statement_Entry;
+ when N_Case_Statement =>
+ Extend_Statement_Sequence (N, 'C');
+ Process_Decisions_Defer (Expression (N), 'X');
+ Set_Statement_Entry;
- -- Now we traverse the statements in the THEN part
+ -- Process case branches, all of which are dominated by the
+ -- CASE statement.
- Traverse_Declarations_Or_Statements
- (L => Then_Statements (N),
- D => ('T', N));
+ declare
+ Alt : Node_Id;
+ begin
+ Alt := First (Alternatives (N));
+ while Present (Alt) loop
+ Traverse_Declarations_Or_Statements
+ (L => Statements (Alt),
+ D => Current_Dominant);
+ Next (Alt);
+ end loop;
+ end;
- -- Loop through ELSIF parts if present
+ -- ACCEPT statement
- if Present (Elsif_Parts (N)) then
- declare
- Saved_Dominant : constant Dominant_Info :=
- Current_Dominant;
- Elif : Node_Id := First (Elsif_Parts (N));
+ when N_Accept_Statement =>
+ Extend_Statement_Sequence (N, 'A');
+ Set_Statement_Entry;
- begin
- while Present (Elif) loop
+ -- Process sequence of statements, dominant is the ACCEPT
+ -- statement.
- -- An Elsif is executed only if the previous test
- -- got a FALSE outcome.
+ Traverse_Handled_Statement_Sequence
+ (N => Handled_Statement_Sequence (N),
+ D => Current_Dominant);
- Current_Dominant := ('F', Current_Test);
+ -- SELECT
- -- Now update current test information
+ when N_Selective_Accept =>
+ Extend_Statement_Sequence (N, 'S');
+ Set_Statement_Entry;
- Current_Test := Elif;
+ -- Process alternatives
- -- We generate a statement sequence for the
- -- construct "ELSIF condition", so that we have
- -- a statement for the resulting decisions.
+ declare
+ Alt : Node_Id;
+ Guard : Node_Id;
+ S_Dom : Dominant_Info;
+
+ begin
+ Alt := First (Select_Alternatives (N));
+ while Present (Alt) loop
+ S_Dom := Current_Dominant;
+ Guard := Condition (Alt);
+
+ if Present (Guard) then
+ Process_Decisions
+ (Guard,
+ 'G',
+ Pragma_Sloc => No_Location);
+ Current_Dominant := ('T', Guard);
+ end if;
- Extend_Statement_Sequence
- (Elif, Condition (Elif), 'I');
- Process_Decisions_Defer (Condition (Elif), 'I');
- Set_Statement_Entry;
+ Traverse_One (Alt);
- -- An ELSIF part is never guaranteed to have
- -- been executed, following statements are only
- -- dominated by the initial IF statement.
+ Current_Dominant := S_Dom;
+ Next (Alt);
+ end loop;
+ end;
- Current_Dominant := Saved_Dominant;
+ Traverse_Declarations_Or_Statements
+ (L => Else_Statements (N),
+ D => Current_Dominant);
- -- Traverse the statements in the ELSIF
+ when N_Timed_Entry_Call | N_Conditional_Entry_Call =>
+ Extend_Statement_Sequence (N, 'S');
+ Set_Statement_Entry;
- Traverse_Declarations_Or_Statements
- (L => Then_Statements (Elif),
- D => ('T', Elif));
- Next (Elif);
- end loop;
- end;
- end if;
+ -- Process alternatives
- -- Finally traverse the ELSE statements if present
+ Traverse_One (Entry_Call_Alternative (N));
+ if Nkind (N) = N_Timed_Entry_Call then
+ Traverse_One (Delay_Alternative (N));
+ else
Traverse_Declarations_Or_Statements
(L => Else_Statements (N),
- D => ('F', Current_Test));
+ D => Current_Dominant);
+ end if;
- -- Case statement, which breaks the current statement sequence,
- -- but we include the expression in the current sequence.
+ when N_Asynchronous_Select =>
+ Extend_Statement_Sequence (N, 'S');
+ Set_Statement_Entry;
- when N_Case_Statement =>
- Extend_Statement_Sequence (N, Expression (N), 'C');
- Process_Decisions_Defer (Expression (N), 'X');
- Set_Statement_Entry;
+ Traverse_One (Triggering_Alternative (N));
+ Traverse_Declarations_Or_Statements
+ (L => Statements (Abortable_Part (N)),
+ D => Current_Dominant);
- -- Process case branches, all of which are dominated by the
- -- CASE statement.
+ when N_Accept_Alternative =>
+ Traverse_Declarations_Or_Statements
+ (L => Statements (N),
+ D => Current_Dominant,
+ P => Accept_Statement (N));
- declare
- Alt : Node_Id;
- begin
- Alt := First (Alternatives (N));
- while Present (Alt) loop
- Traverse_Declarations_Or_Statements
- (L => Statements (Alt),
- D => Current_Dominant);
- Next (Alt);
- end loop;
- end;
+ when N_Entry_Call_Alternative =>
+ Traverse_Declarations_Or_Statements
+ (L => Statements (N),
+ D => Current_Dominant,
+ P => Entry_Call_Statement (N));
+
+ when N_Delay_Alternative =>
+ Traverse_Declarations_Or_Statements
+ (L => Statements (N),
+ D => Current_Dominant,
+ P => Delay_Statement (N));
- -- Unconditional exit points, which are included in the current
- -- statement sequence, but then terminate it
+ when N_Triggering_Alternative =>
+ Traverse_Declarations_Or_Statements
+ (L => Statements (N),
+ D => Current_Dominant,
+ P => Triggering_Statement (N));
- when N_Requeue_Statement |
- N_Goto_Statement |
- N_Raise_Statement =>
- Extend_Statement_Sequence (N, ' ');
- Set_Statement_Entry;
- Current_Dominant := No_Dominant;
+ when N_Terminate_Alternative =>
+ Extend_Statement_Sequence (N, ' ');
+ Set_Statement_Entry;
- -- Simple return statement. which is an exit point, but we
- -- have to process the return expression for decisions.
+ -- Unconditional exit points, which are included in the current
+ -- statement sequence, but then terminate it
- when N_Simple_Return_Statement =>
- Extend_Statement_Sequence (N, ' ');
- Process_Decisions_Defer (Expression (N), 'X');
- Set_Statement_Entry;
- Current_Dominant := No_Dominant;
+ when N_Requeue_Statement |
+ N_Goto_Statement |
+ N_Raise_Statement =>
+ Extend_Statement_Sequence (N, ' ');
+ Set_Statement_Entry;
+ Current_Dominant := No_Dominant;
- -- Extended return statement
+ -- Simple return statement. which is an exit point, but we
+ -- have to process the return expression for decisions.
- when N_Extended_Return_Statement =>
- Extend_Statement_Sequence
- (N, Last (Return_Object_Declarations (N)), 'R');
- Process_Decisions_Defer
- (Return_Object_Declarations (N), 'X');
- Set_Statement_Entry;
+ when N_Simple_Return_Statement =>
+ Extend_Statement_Sequence (N, ' ');
+ Process_Decisions_Defer (Expression (N), 'X');
+ Set_Statement_Entry;
+ Current_Dominant := No_Dominant;
- Traverse_Handled_Statement_Sequence
- (N => Handled_Statement_Sequence (N),
- D => Current_Dominant);
+ -- Extended return statement
- Current_Dominant := No_Dominant;
+ when N_Extended_Return_Statement =>
+ Extend_Statement_Sequence (N, 'R');
+ Process_Decisions_Defer
+ (Return_Object_Declarations (N), 'X');
+ Set_Statement_Entry;
- -- Loop ends the current statement sequence, but we include
- -- the iteration scheme if present in the current sequence.
- -- But the body of the loop starts a new sequence, since it
- -- may not be executed as part of the current sequence.
+ Traverse_Handled_Statement_Sequence
+ (N => Handled_Statement_Sequence (N),
+ D => Current_Dominant);
- when N_Loop_Statement =>
- declare
- ISC : constant Node_Id := Iteration_Scheme (N);
- Inner_Dominant : Dominant_Info := No_Dominant;
+ Current_Dominant := No_Dominant;
- begin
- if Present (ISC) then
+ -- Loop ends the current statement sequence, but we include
+ -- the iteration scheme if present in the current sequence.
+ -- But the body of the loop starts a new sequence, since it
+ -- may not be executed as part of the current sequence.
- -- If iteration scheme present, extend the current
- -- statement sequence to include the iteration scheme
- -- and process any decisions it contains.
+ when N_Loop_Statement =>
+ declare
+ ISC : constant Node_Id := Iteration_Scheme (N);
+ Inner_Dominant : Dominant_Info := No_Dominant;
- -- While loop
+ begin
+ if Present (ISC) then
- if Present (Condition (ISC)) then
- Extend_Statement_Sequence (N, ISC, 'W');
- Process_Decisions_Defer (Condition (ISC), 'W');
+ -- If iteration scheme present, extend the current
+ -- statement sequence to include the iteration scheme
+ -- and process any decisions it contains.
- -- Set more specific dominant for inner statements
- -- (the control sloc for the decision is that of
- -- the WHILE token).
+ -- While loop
- Inner_Dominant := ('T', ISC);
+ if Present (Condition (ISC)) then
+ Extend_Statement_Sequence (N, 'W');
+ Process_Decisions_Defer (Condition (ISC), 'W');
- -- For loop
+ -- Set more specific dominant for inner statements
+ -- (the control sloc for the decision is that of
+ -- the WHILE token).
- else
- Extend_Statement_Sequence (N, ISC, 'F');
- Process_Decisions_Defer
- (Loop_Parameter_Specification (ISC), 'X');
- end if;
- end if;
+ Inner_Dominant := ('T', ISC);
- Set_Statement_Entry;
+ -- For loop
- if Inner_Dominant = No_Dominant then
- Inner_Dominant := Current_Dominant;
+ else
+ Extend_Statement_Sequence (N, 'F');
+ Process_Decisions_Defer
+ (Loop_Parameter_Specification (ISC), 'X');
end if;
+ end if;
- Traverse_Declarations_Or_Statements
- (L => Statements (N),
- D => Inner_Dominant);
- end;
+ Set_Statement_Entry;
- -- Pragma
+ if Inner_Dominant = No_Dominant then
+ Inner_Dominant := Current_Dominant;
+ end if;
- when N_Pragma =>
+ Traverse_Declarations_Or_Statements
+ (L => Statements (N),
+ D => Inner_Dominant);
+ end;
- -- Record sloc of pragma (pragmas don't nest)
+ -- Pragma
- pragma Assert (Current_Pragma_Sloc = No_Location);
- Current_Pragma_Sloc := Sloc (N);
+ when N_Pragma =>
- -- Processing depends on the kind of pragma
+ -- Record sloc of pragma (pragmas don't nest)
- declare
- Nam : constant Name_Id := Pragma_Name (N);
- Arg : Node_Id := First (Pragma_Argument_Associations (N));
- Typ : Character;
+ pragma Assert (Current_Pragma_Sloc = No_Location);
+ Current_Pragma_Sloc := Sloc (N);
- begin
- case Nam is
- when Name_Assert |
- Name_Check |
- Name_Precondition |
- Name_Postcondition =>
-
- -- For Assert/Check/Precondition/Postcondition, we
- -- must generate a P entry for the decision. Note
- -- that this is done unconditionally at this stage.
- -- Output for disabled pragmas is suppressed later
- -- on when we output the decision line in Put_SCOs,
- -- depending on setting by Set_SCO_Pragma_Enabled.
-
- if Nam = Name_Check then
- Next (Arg);
- end if;
+ -- Processing depends on the kind of pragma
- Process_Decisions_Defer (Expression (Arg), 'P');
- Typ := 'p';
+ declare
+ Nam : constant Name_Id := Pragma_Name (N);
+ Arg : Node_Id :=
+ First (Pragma_Argument_Associations (N));
+ Typ : Character;
- when Name_Debug =>
- if Present (Arg) and then Present (Next (Arg)) then
+ begin
+ case Nam is
+ when Name_Assert |
+ Name_Check |
+ Name_Precondition |
+ Name_Postcondition =>
+
+ -- For Assert/Check/Precondition/Postcondition, we
+ -- must generate a P entry for the decision. Note
+ -- that this is done unconditionally at this stage.
+ -- Output for disabled pragmas is suppressed later
+ -- on when we output the decision line in Put_SCOs,
+ -- depending on setting by Set_SCO_Pragma_Enabled.
+
+ if Nam = Name_Check then
+ Next (Arg);
+ end if;
- -- Case of a dyadic pragma Debug: first argument
- -- is a P decision, any nested decision in the
- -- second argument is an X decision.
+ Process_Decisions_Defer (Expression (Arg), 'P');
+ Typ := 'p';
- Process_Decisions_Defer (Expression (Arg), 'P');
- Next (Arg);
- end if;
+ when Name_Debug =>
+ if Present (Arg) and then Present (Next (Arg)) then
- Process_Decisions_Defer (Expression (Arg), 'X');
- Typ := 'p';
+ -- Case of a dyadic pragma Debug: first argument
+ -- is a P decision, any nested decision in the
+ -- second argument is an X decision.
- -- For all other pragmas, we generate decision entries
- -- for any embedded expressions, and the pragma is
- -- never disabled.
+ Process_Decisions_Defer (Expression (Arg), 'P');
+ Next (Arg);
+ end if;
- when others =>
- Process_Decisions_Defer (N, 'X');
- Typ := 'P';
- end case;
+ Process_Decisions_Defer (Expression (Arg), 'X');
+ Typ := 'p';
- -- Add statement SCO
+ -- For all other pragmas, we generate decision entries
+ -- for any embedded expressions, and the pragma is
+ -- never disabled.
- Extend_Statement_Sequence (N, Typ);
+ when others =>
+ Process_Decisions_Defer (N, 'X');
+ Typ := 'P';
+ end case;
- Current_Pragma_Sloc := No_Location;
- end;
+ -- Add statement SCO
- -- Object declaration. Ignored if Prev_Ids is set, since the
- -- parser generates multiple instances of the whole declaration
- -- if there is more than one identifier declared, and we only
- -- want one entry in the SCO's, so we take the first, for which
- -- Prev_Ids is False.
+ Extend_Statement_Sequence (N, Typ);
- when N_Object_Declaration =>
- if not Prev_Ids (N) then
- Extend_Statement_Sequence (N, 'o');
+ Current_Pragma_Sloc := No_Location;
+ end;
- if Has_Decision (N) then
- Process_Decisions_Defer (N, 'X');
- end if;
- end if;
+ -- Object declaration. Ignored if Prev_Ids is set, since the
+ -- parser generates multiple instances of the whole declaration
+ -- if there is more than one identifier declared, and we only
+ -- want one entry in the SCO's, so we take the first, for which
+ -- Prev_Ids is False.
- -- All other cases, which extend the current statement sequence
- -- but do not terminate it, even if they have nested decisions.
+ when N_Object_Declaration =>
+ if not Prev_Ids (N) then
+ Extend_Statement_Sequence (N, 'o');
- when others =>
+ if Has_Decision (N) then
+ Process_Decisions_Defer (N, 'X');
+ end if;
+ end if;
- -- Determine required type character code, or ASCII.NUL if
- -- no SCO should be generated for this node.
+ -- All other cases, which extend the current statement sequence
+ -- but do not terminate it, even if they have nested decisions.
- declare
- Typ : Character;
+ when others =>
- begin
- case Nkind (N) is
- when N_Full_Type_Declaration |
- N_Incomplete_Type_Declaration |
- N_Private_Type_Declaration |
- N_Private_Extension_Declaration =>
- Typ := 't';
+ -- Determine required type character code, or ASCII.NUL if
+ -- no SCO should be generated for this node.
- when N_Subtype_Declaration =>
- Typ := 's';
+ declare
+ Typ : Character;
- when N_Renaming_Declaration =>
- Typ := 'r';
+ begin
+ case Nkind (N) is
+ when N_Full_Type_Declaration |
+ N_Incomplete_Type_Declaration |
+ N_Private_Type_Declaration |
+ N_Private_Extension_Declaration =>
+ Typ := 't';
- when N_Generic_Instantiation =>
- Typ := 'i';
+ when N_Subtype_Declaration =>
+ Typ := 's';
- when N_Representation_Clause |
- N_Use_Package_Clause |
- N_Use_Type_Clause =>
- Typ := ASCII.NUL;
+ when N_Renaming_Declaration =>
+ Typ := 'r';
- when others =>
- Typ := ' ';
- end case;
+ when N_Generic_Instantiation =>
+ Typ := 'i';
- if Typ /= ASCII.NUL then
- Extend_Statement_Sequence (N, Typ);
- end if;
- end;
+ when N_Representation_Clause |
+ N_Use_Package_Clause |
+ N_Use_Type_Clause =>
+ Typ := ASCII.NUL;
- -- Process any embedded decisions
+ when others =>
+ Typ := ' ';
+ end case;
- if Has_Decision (N) then
- Process_Decisions_Defer (N, 'X');
+ if Typ /= ASCII.NUL then
+ Extend_Statement_Sequence (N, Typ);
end if;
- end case;
+ end;
+
+ -- Process any embedded decisions
+
+ if Has_Decision (N) then
+ Process_Decisions_Defer (N, 'X');
+ end if;
+ end case;
+
+ end Traverse_One;
+ -- Start of processing for Traverse_Declarations_Or_Statements
+
+ begin
+ if Present (P) then
+ Traverse_One (P);
+ end if;
+
+ if Is_Non_Empty_List (L) then
+
+ -- Loop through statements or declarations
+
+ N := First (L);
+ while Present (N) loop
+ Traverse_One (N);
Next (N);
end loop;