Commit 25adc5fb by Arnaud Charlet Committed by Arnaud Charlet

get_scos.adb, [...]: Code clean up, update documentation.

	* get_scos.adb, par_sco.adb, par_sco.ads, put_scos.adb, scos.adb,
	scos.ads, exp_ch4.adb, sem_warn.adb: Code clean up, update
	documentation.

From-SVN: r160849
parent e1578ff3
2010-06-16 Arnaud Charlet <charlet@adacore.com>
* get_scos.adb, par_sco.adb, par_sco.ads, put_scos.adb, scos.adb,
scos.ads, exp_ch4.adb, sem_warn.adb: Code clean up, update
documentation.
2010-06-16 Javier Miranda <miranda@adacore.com> 2010-06-16 Javier Miranda <miranda@adacore.com>
* exp_disp.adb (Expand_Dispatching_Call): Adjust the decoration of the * exp_disp.adb (Expand_Dispatching_Call): Adjust the decoration of the
......
...@@ -47,6 +47,7 @@ with Namet; use Namet; ...@@ -47,6 +47,7 @@ with Namet; use Namet;
with Nlists; use Nlists; with Nlists; use Nlists;
with Nmake; use Nmake; with Nmake; use Nmake;
with Opt; use Opt; with Opt; use Opt;
with Par_SCO; use Par_SCO;
with Restrict; use Restrict; with Restrict; use Restrict;
with Rident; use Rident; with Rident; use Rident;
with Rtsfind; use Rtsfind; with Rtsfind; use Rtsfind;
...@@ -8676,7 +8677,6 @@ package body Exp_Ch4 is ...@@ -8676,7 +8677,6 @@ package body Exp_Ch4 is
Result := New_Reference_To (Standard_True, Loc); Result := New_Reference_To (Standard_True, Loc);
C := Suitable_Element (First_Entity (Typ)); C := Suitable_Element (First_Entity (Typ));
while Present (C) loop while Present (C) loop
declare declare
New_Lhs : Node_Id; New_Lhs : Node_Id;
...@@ -8745,7 +8745,28 @@ package body Exp_Ch4 is ...@@ -8745,7 +8745,28 @@ package body Exp_Ch4 is
Shortcut_Ent : constant Entity_Id := Boolean_Literals (Shortcut_Value); Shortcut_Ent : constant Entity_Id := Boolean_Literals (Shortcut_Value);
-- If Left = Shortcut_Value then Right need not be evaluated -- If Left = Shortcut_Value then Right need not be evaluated
Expr_If_Left_True, Expr_If_Left_False : Node_Id; function Make_Test_Expr (Opnd : Node_Id) return Node_Id;
-- For Opnd a boolean expression, return a Boolean expression equivalent
-- to Opnd /= Shortcut_Value.
--------------------
-- Make_Test_Expr --
--------------------
function Make_Test_Expr (Opnd : Node_Id) return Node_Id is
begin
if Shortcut_Value then
return Make_Op_Not (Sloc (Opnd), Opnd);
else
return Opnd;
end if;
end Make_Test_Expr;
Op_Var : Entity_Id;
-- Entity for a temporary variable holding the value of the operator,
-- used for expansion in the case where actions are present.
-- Start of processing for Expand_Short_Circuit_Operator
begin begin
-- Deal with non-standard booleans -- Deal with non-standard booleans
...@@ -8759,6 +8780,13 @@ package body Exp_Ch4 is ...@@ -8759,6 +8780,13 @@ package body Exp_Ch4 is
-- Check for cases where left argument is known to be True or False -- Check for cases where left argument is known to be True or False
if Compile_Time_Known_Value (Left) then if Compile_Time_Known_Value (Left) then
-- Mark SCO for left condition as compile time known
if Generate_SCO and then Comes_From_Source (Left) then
Set_SCO_Condition (Left, Expr_Value_E (Left) = Standard_True);
end if;
-- Rewrite True AND THEN Right / False OR ELSE Right to Right. -- Rewrite True AND THEN Right / False OR ELSE Right to Right.
-- Any actions associated with Right will be executed unconditionally -- Any actions associated with Right will be executed unconditionally
-- and can thus be inserted into the tree unconditionally. -- and can thus be inserted into the tree unconditionally.
...@@ -8787,40 +8815,60 @@ package body Exp_Ch4 is ...@@ -8787,40 +8815,60 @@ package body Exp_Ch4 is
-- If Actions are present, we expand -- If Actions are present, we expand
-- left AND THEN right -- left AND THEN right
-- left OR ELSE right
-- into -- into
-- if left then right else false end -- C : Boolean := False;
-- if left then true else right end -- IF left THEN
-- Actions;
-- IF right THEN
-- C := True;
-- END IF;
-- END IF;
-- and finally rewrite the operator into a reference to C. Similarly
-- for left OR ELSE right, with negated values. Note that this rewriting
-- preserves two invariants that traces-based coverage analysis depends
-- upon:
-- with the actions for the right operand being transferred to the -- - there is exactly one conditional jump for each operand;
-- approriate actions list of the conditional expression. This
-- conditional expression is then further expanded (and will eventually -- - for each possible values of the expression, there is exactly
-- disappear). -- one location in the generated code that is branched to
-- (the inner assignment in one case, the point just past the
-- outer END IF; in the other case).
if Present (Actions (N)) then if Present (Actions (N)) then
Actlist := Actions (N); Actlist := Actions (N);
if Kind = N_And_Then then Op_Var := Make_Temporary (Loc, 'C', Related_Node => N);
Expr_If_Left_True := Right;
Expr_If_Left_False := New_Occurrence_Of (Standard_False, Loc);
else Insert_Action (N,
Expr_If_Left_True := New_Occurrence_Of (Standard_True, Loc); Make_Object_Declaration (Loc,
Expr_If_Left_False := Right; Defining_Identifier =>
end if; Op_Var,
Object_Definition =>
New_Occurrence_Of (Standard_Boolean, Loc),
Expression =>
New_Occurrence_Of (Shortcut_Ent, Loc)));
Rewrite (N, Append_To (Actlist,
Make_Conditional_Expression (Loc, Make_Implicit_If_Statement (Right,
Expressions => New_List ( Condition => Make_Test_Expr (Right),
Left, Then_Statements => New_List (
Expr_If_Left_True, Make_Assignment_Statement (Sloc (Right),
Expr_If_Left_False))); Name =>
New_Occurrence_Of (Op_Var, Sloc (Right)),
Expression =>
New_Occurrence_Of
(Boolean_Literals (not Shortcut_Value), Sloc (Right))))));
-- If the right part of an AND THEN is a function call then it can Insert_Action (N,
-- be part of the expansion of the predefined equality operator of a Make_Implicit_If_Statement (Left,
-- tagged type and we may need to adjust its SCIL dispatching node. Condition => Make_Test_Expr (Left),
Then_Statements => Actlist));
Rewrite (N, New_Occurrence_Of (Op_Var, Loc));
if Generate_SCIL if Generate_SCIL
and then Kind = N_And_Then and then Kind = N_And_Then
...@@ -8829,12 +8877,6 @@ package body Exp_Ch4 is ...@@ -8829,12 +8877,6 @@ package body Exp_Ch4 is
Adjust_SCIL_Node (N, Right); Adjust_SCIL_Node (N, Right);
end if; end if;
if Kind = N_And_Then then
Set_Then_Actions (N, Actlist);
else
Set_Else_Actions (N, Actlist);
end if;
Analyze_And_Resolve (N, Standard_Boolean); Analyze_And_Resolve (N, Standard_Boolean);
Adjust_Result_Type (N, Typ); Adjust_Result_Type (N, Typ);
return; return;
...@@ -8843,6 +8885,13 @@ package body Exp_Ch4 is ...@@ -8843,6 +8885,13 @@ package body Exp_Ch4 is
-- No actions present, check for cases of right argument True/False -- No actions present, check for cases of right argument True/False
if Compile_Time_Known_Value (Right) then if Compile_Time_Known_Value (Right) then
-- Mark SCO for left condition as compile time known
if Generate_SCO and then Comes_From_Source (Right) then
Set_SCO_Condition (Right, Expr_Value_E (Right) = Standard_True);
end if;
-- Change (Left and then True), (Left or else False) to Left. -- Change (Left and then True), (Left or else False) to Left.
-- Note that we know there are no actions associated with the right -- Note that we know there are no actions associated with the right
-- operand, since we just checked for this case above. -- operand, since we just checked for this case above.
......
...@@ -54,7 +54,12 @@ procedure Get_SCOs is ...@@ -54,7 +54,12 @@ procedure Get_SCOs is
-- value read. Data_Error is raised for overflow (value greater than -- value read. Data_Error is raised for overflow (value greater than
-- Int'Last), or if the initial character is not a digit. -- Int'Last), or if the initial character is not a digit.
procedure Get_Sloc_Range (Loc1, Loc2 : out Source_Location); procedure Get_Source_Location (Loc : out Source_Location);
-- Reads a source location in the form line:col and places the source
-- location in Loc. Raises Data_Error if the format does not match this
-- requirement. Note that initial spaces are not skipped.
procedure Get_Source_Location_Range (Loc1, Loc2 : out Source_Location);
-- Skips initial spaces, then reads a source location range in the form -- Skips initial spaces, then reads a source location range in the form
-- line:col-line:col and places the two source locations in Loc1 and Loc2. -- line:col-line:col and places the two source locations in Loc1 and Loc2.
-- Raises Data_Error if format does not match this requirement. -- Raises Data_Error if format does not match this requirement.
...@@ -129,31 +134,32 @@ procedure Get_SCOs is ...@@ -129,31 +134,32 @@ procedure Get_SCOs is
raise Data_Error; raise Data_Error;
end Get_Int; end Get_Int;
-------------------- -------------------------
-- Get_Sloc_Range -- -- Get_Source_Location --
-------------------- -------------------------
procedure Get_Sloc_Range (Loc1, Loc2 : out Source_Location) is procedure Get_Source_Location (Loc : out Source_Location) is
pragma Unsuppress (Range_Check); pragma Unsuppress (Range_Check);
begin begin
Skip_Spaces; Loc.Line := Logical_Line_Number (Get_Int);
Loc1.Line := Logical_Line_Number (Get_Int);
Check (':');
Loc1.Col := Column_Number (Get_Int);
Check ('-');
Loc2.Line := Logical_Line_Number (Get_Int);
Check (':'); Check (':');
Loc2.Col := Column_Number (Get_Int); Loc.Col := Column_Number (Get_Int);
exception exception
when Constraint_Error => when Constraint_Error =>
raise Data_Error; raise Data_Error;
end Get_Sloc_Range; end Get_Source_Location;
-------------------------------
-- Get_Source_Location_Range --
-------------------------------
procedure Get_Source_Location_Range (Loc1, Loc2 : out Source_Location) is
begin
Skip_Spaces;
Get_Source_Location (Loc1);
Check ('-');
Get_Source_Location (Loc2);
end Get_Source_Location_Range;
-------------- --------------
-- Skip_EOL -- -- Skip_EOL --
-------------- --------------
...@@ -250,14 +256,31 @@ begin ...@@ -250,14 +256,31 @@ begin
-- Statement entry -- Statement entry
when 'S' => when 'S' | 's' =>
declare declare
Typ : Character; Typ : Character;
Key : Character; Key : Character;
begin begin
Skip_Spaces; -- If continuation, reset Last indication in last entry
-- stored for previous CS or cs line, and start with key
-- set to s for continuations.
if C = 's' then
SCO_Table.Table (SCO_Table.Last).Last := False;
Key := 's';
-- CS case (first line, so start with key set to S)
else
Key := 'S'; Key := 'S';
end if;
-- Initialize to scan items on one line
Skip_Spaces;
-- Loop through items on one line
loop loop
Typ := Nextc; Typ := Nextc;
...@@ -268,7 +291,7 @@ begin ...@@ -268,7 +291,7 @@ begin
Skipc; Skipc;
end if; end if;
Get_Sloc_Range (Loc1, Loc2); Get_Source_Location_Range (Loc1, Loc2);
Add_SCO Add_SCO
(C1 => Key, (C1 => Key,
...@@ -287,32 +310,37 @@ begin ...@@ -287,32 +310,37 @@ begin
when 'I' | 'E' | 'P' | 'W' | 'X' => when 'I' | 'E' | 'P' | 'W' | 'X' =>
Dtyp := C; Dtyp := C;
Skip_Spaces; Skip_Spaces;
C := Getc;
-- Case of simple condition -- Output header
if C = 'c' or else C = 't' or else C = 'f' then declare
Cond := C; Loc : Source_Location;
Get_Sloc_Range (Loc1, Loc2);
Add_SCO
(C1 => Dtyp,
C2 => Cond,
From => Loc1,
To => Loc2,
Last => True);
-- Complex expression begin
-- Acquire location information
if Dtyp = 'X' then
Loc := No_Source_Location;
else else
Add_SCO (C1 => Dtyp, Last => False); Get_Source_Location (Loc);
end if;
Add_SCO
(C1 => Dtyp,
C2 => ' ',
From => Loc,
To => No_Source_Location,
Last => False);
end;
-- Loop through terms in complex expression -- Loop through terms in complex expression
C := Nextc;
while C /= CR and then C /= LF loop while C /= CR and then C /= LF loop
if C = 'c' or else C = 't' or else C = 'f' then if C = 'c' or else C = 't' or else C = 'f' then
Cond := C; Cond := C;
Skipc; Skipc;
Get_Sloc_Range (Loc1, Loc2); Get_Source_Location_Range (Loc1, Loc2);
Add_SCO Add_SCO
(C2 => Cond, (C2 => Cond,
From => Loc1, From => Loc1,
...@@ -320,12 +348,17 @@ begin ...@@ -320,12 +348,17 @@ begin
Last => False); Last => False);
elsif C = '!' or else elsif C = '!' or else
C = '^' or else
C = '&' or else C = '&' or else
C = '|' C = '|'
then then
Skipc; Skipc;
Add_SCO (C1 => C, Last => False);
declare
Loc : Source_Location;
begin
Get_Source_Location (Loc);
Add_SCO (C1 => C, From => Loc, Last => False);
end;
elsif C = ' ' then elsif C = ' ' then
Skip_Spaces; Skip_Spaces;
...@@ -340,7 +373,8 @@ begin ...@@ -340,7 +373,8 @@ begin
-- Reset Last indication to True for last entry -- Reset Last indication to True for last entry
SCO_Table.Table (SCO_Table.Last).Last := True; SCO_Table.Table (SCO_Table.Last).Last := True;
end if;
-- No other SCO lines are possible
when others => when others =>
raise Data_Error; raise Data_Error;
......
...@@ -25,156 +25,12 @@ ...@@ -25,156 +25,12 @@
-- This package contains the routines used to deal with generation and output -- This package contains the routines used to deal with generation and output
-- of Soure Coverage Obligations (SCO's) used for coverage analysis purposes. -- of Soure Coverage Obligations (SCO's) used for coverage analysis purposes.
-- See package SCOs for full documentation of format of SCO information.
with Types; use Types; with Types; use Types;
package Par_SCO is package Par_SCO is
----------------
-- SCO Format --
----------------
-- Source coverage obligations are generated on a unit-by-unit basis in the
-- ALI file, using lines that start with the identifying character C. These
-- lines are generated if the -gnatC switch is set.
-- Sloc Ranges
-- In several places in the SCO lines, Sloc ranges appear. These are used
-- to indicate the first and last Sloc of some construct in the tree and
-- they have the form:
-- line:col-line:col
-- Note that SCO's are generated only for generic templates, not for
-- generic instances (since only the first are part of the source). So
-- we don't need generic instantiation stuff in these line:col items.
-- SCO File headers
-- The SCO information follows the cross-reference information, so it
-- need not be read by tools like gnatbind, gnatmake etc. The SCO output
-- is divided into sections, one section for each unit for which SCO's
-- are generated. A SCO section has a header of the form:
-- C dependency-number filename
-- This header precedes SCO information for the unit identified by
-- dependency number and file name. The dependency number is the
-- index into the generated D lines and is ones origin (i.e. 2 =
-- reference to second generated D line).
-- Note that the filename here will reflect the original name if
-- a Source_Reference pragma was encountered (since all line number
-- references will be with respect to the original file).
-- Statements
-- For the purpose of SCO generation, the notion of statement includes
-- simple statements and also the following declaration types:
-- type_declaration
-- subtype_declaration
-- object_declaration
-- renaming_declaration
-- generic_instantiation
-- Statement lines
-- These lines correspond to a sequence of one or more statements which
-- are always exeecuted in sequence, The first statement may be an entry
-- point (e.g. statement after a label), and the last statement may be
-- an exit point (e.g. an exit statement), but no other entry or exit
-- points may occur within the sequence of statements. The idea is that
-- the sequence can be treated as a single unit from a coverage point of
-- view, if any of the code for the statement sequence is executed, this
-- corresponds to coverage of the entire statement sequence. The form of
-- a statement line in the ALI file is:
-- CS sloc-range
-- Exit points
-- An exit point is a statement that causes transfer of control. Examples
-- are exit statements, raise statements and return statements. The form
-- of an exit point in the ALI file is:
-- CT sloc-range
-- Decisions
-- Decisions represent the most significant section of the SCO lines
-- Note: in the following description, logical operator includes the
-- short circuited forms (so can be any of AND, OR, XOR, NOT, AND THEN,
-- or OR ELSE).
-- Decisions are either simple or complex. A simple decision is a boolean
-- expresssion that occurs in the context of a control structure in the
-- source program, including WHILE, IF, EXIT WHEN. Note that a boolean
-- expression in any other context, e.g. on the right side of an
-- assignment, is not considered to be a decision.
-- A complex decision is an occurrence of a logical operator which is not
-- itself an operand of some other logical operator. If any operand of
-- the logical operator is itself a logical operator, this is not a
-- separate decision, it is part of the same decision.
-- So for example, if we have
-- A, B, C, D : Boolean;
-- function F (Arg : Boolean) return Boolean);
-- ...
-- A and then (B or else F (C and then D))
-- There are two (complex) decisions here:
-- 1. X and then (Y or else Z)
-- where X = A, Y = B, and Z = F (C and then D)
-- 2. C and then D
-- For each decision, a decision line is generated with the form:
-- C* expression
-- Here * is one of the following characters:
-- I decision in IF statement or conditional expression
-- E decision in EXIT WHEN statement
-- W decision in WHILE iteration scheme
-- X decision appearing in some other expression context
-- The expression is a prefix polish form indicating the structure of
-- the decision, including logical operators and short circuit forms.
-- The following is a grammar showing the structure of expression:
-- expression ::= term (if expr is not logical operator)
-- expression ::= & term term (if expr is AND THEN)
-- expression ::= | term term (if expr is OR ELSE)
-- expression ::= !term (if expr is NOT)
-- term ::= element
-- term ::= expression
-- element ::= outcome sloc-range
-- outcome is one of the following letters:
-- c condition
-- t true condition
-- f false condition
-- where t/f are used to mark a condition that has been recognized by
-- the compiler as always being true or false.
-- & indicates either AND THEN connecting two conditions
-- | indicates either OR ELSE connection two conditions
-- ! indicates NOT applied to the expression
----------------- -----------------
-- Subprograms -- -- Subprograms --
----------------- -----------------
...@@ -187,11 +43,11 @@ package Par_SCO is ...@@ -187,11 +43,11 @@ package Par_SCO is
-- internal tables recording the SCO information. Note that this is done -- internal tables recording the SCO information. Note that this is done
-- before any semantic analysis/expansion happens. -- before any semantic analysis/expansion happens.
procedure Set_SCO_Condition (First_Loc : Source_Ptr; Typ : Character); procedure Set_SCO_Condition (Cond : Node_Id; Val : Boolean);
-- This procedure is called during semantic analysis to record a condition -- This procedure is called during semantic analysis to record a condition
-- which has been identified as always True (Typ = 't') or always False -- which has been identified as always True or always False, as indicated
-- (Typ = 'f') by the compiler. The condition is identified by the -- by Val. The condition is identified by the First_Sloc value in the
-- First_Sloc value in the original tree. -- original tree associated with Cond.
procedure SCO_Output; procedure SCO_Output;
-- Outputs SCO lines for all units, with appropriate section headers, for -- Outputs SCO lines for all units, with appropriate section headers, for
...@@ -199,8 +55,8 @@ package Par_SCO is ...@@ -199,8 +55,8 @@ package Par_SCO is
-- possibly modified by calls to Set_SCO_Condition. -- possibly modified by calls to Set_SCO_Condition.
procedure dsco; procedure dsco;
-- Debug routine to dump SCO table. This is a raw format dump showing -- Debug routine to dump internal SCO table. This is a raw format dump
-- exactly what the tables contain. -- showing exactly what the table contains.
procedure pscos; procedure pscos;
-- Debugging procedure to output contents of SCO binary tables in the -- Debugging procedure to output contents of SCO binary tables in the
......
...@@ -23,9 +23,43 @@ ...@@ -23,9 +23,43 @@
-- -- -- --
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
with Atree; use Atree;
with SCOs; use SCOs; with SCOs; use SCOs;
with Sinfo; use Sinfo;
procedure Put_SCOs is procedure Put_SCOs is
Ctr : Nat;
procedure Output_Range (T : SCO_Table_Entry);
-- Outputs T.From and T.To in line:col-line:col format
procedure Output_Source_Location (Loc : Source_Location);
-- Output source location in line:col format
------------------
-- Output_Range --
------------------
procedure Output_Range (T : SCO_Table_Entry) is
begin
Output_Source_Location (T.From);
Write_Info_Char ('-');
Output_Source_Location (T.To);
end Output_Range;
----------------------------
-- Output_Source_Location --
----------------------------
procedure Output_Source_Location (Loc : Source_Location) is
begin
Write_Info_Nat (Nat (Loc.Line));
Write_Info_Char (':');
Write_Info_Nat (Nat (Loc.Col));
end Output_Source_Location;
-- Start of processing for Put_SCOs
begin begin
-- Loop through entries in SCO_Unit_Table -- Loop through entries in SCO_Unit_Table
...@@ -64,35 +98,16 @@ begin ...@@ -64,35 +98,16 @@ begin
Output_SCO_Line : declare Output_SCO_Line : declare
T : SCO_Table_Entry renames SCO_Table.Table (Start); T : SCO_Table_Entry renames SCO_Table.Table (Start);
procedure Output_Range (T : SCO_Table_Entry);
-- Outputs T.From and T.To in line:col-line:col format
------------------
-- Output_Range --
------------------
procedure Output_Range (T : SCO_Table_Entry) is
begin begin
Write_Info_Nat (Nat (T.From.Line));
Write_Info_Char (':');
Write_Info_Nat (Nat (T.From.Col));
Write_Info_Char ('-');
Write_Info_Nat (Nat (T.To.Line));
Write_Info_Char (':');
Write_Info_Nat (Nat (T.To.Col));
end Output_Range;
-- Start of processing for Output_SCO_Line
begin
Write_Info_Initiate ('C');
Write_Info_Char (T.C1);
case T.C1 is case T.C1 is
-- Statements -- Statements
when 'S' => when 'S' =>
Write_Info_Initiate ('C');
Write_Info_Char ('S');
Ctr := 0;
loop loop
Write_Info_Char (' '); Write_Info_Char (' ');
...@@ -105,6 +120,18 @@ begin ...@@ -105,6 +120,18 @@ begin
Start := Start + 1; Start := Start + 1;
pragma Assert (SCO_Table.Table (Start).C1 = 's'); pragma Assert (SCO_Table.Table (Start).C1 = 's');
Ctr := Ctr + 1;
-- Up to 6 items on a line, if more than 6 items,
-- continuation lines are marked Cs.
if Ctr = 6 then
Write_Info_Terminate;
Write_Info_Initiate ('C');
Write_Info_Char ('s');
Ctr := 0;
end if;
end loop; end loop;
-- Statement continuations should not occur since they -- Statement continuations should not occur since they
...@@ -116,25 +143,50 @@ begin ...@@ -116,25 +143,50 @@ begin
-- Decision -- Decision
when 'I' | 'E' | 'P' | 'W' | 'X' => when 'I' | 'E' | 'P' | 'W' | 'X' =>
if T.C2 = ' ' then
Start := Start + 1; Start := Start + 1;
-- For disabled pragma, skip decision output. Note that
-- if the SCO table has been populated by Get_SCOs
-- (re-reading previously generated SCO information),
-- then the Node field of pragma entries is Empty. This
-- is the only way that Node can be Empty, so if we see
-- an Empty node field, we know the pragma is enabled.
if T.C1 = 'P'
and then Present (T.Node)
and then not Pragma_Enabled (Original_Node (T.Node))
then
while not SCO_Table.Table (Start).Last loop
Start := Start + 1;
end loop;
-- For all other cases output decision line
else
Write_Info_Initiate ('C');
Write_Info_Char (T.C1);
if T.C1 /= 'X' then
Write_Info_Char (' ');
Output_Source_Location (T.From);
end if; end if;
-- Loop through table entries for this decision -- Loop through table entries for this decision
loop loop
declare declare
T : SCO_Table_Entry renames SCO_Table.Table (Start); T : SCO_Table_Entry
renames SCO_Table.Table (Start);
begin begin
Write_Info_Char (' '); Write_Info_Char (' ');
if T.C1 = '!' or else if T.C1 = '!' or else
T.C1 = '^' or else
T.C1 = '&' or else T.C1 = '&' or else
T.C1 = '|' T.C1 = '|'
then then
Write_Info_Char (T.C1); Write_Info_Char (T.C1);
Output_Source_Location (T.From);
else else
Write_Info_Char (T.C2); Write_Info_Char (T.C2);
...@@ -145,6 +197,7 @@ begin ...@@ -145,6 +197,7 @@ begin
Start := Start + 1; Start := Start + 1;
end; end;
end loop; end loop;
end if;
when others => when others =>
raise Program_Error; raise Program_Error;
......
...@@ -34,10 +34,11 @@ package body SCOs is ...@@ -34,10 +34,11 @@ package body SCOs is
To : Source_Location := No_Source_Location; To : Source_Location := No_Source_Location;
C1 : Character := ' '; C1 : Character := ' ';
C2 : Character := ' '; C2 : Character := ' ';
Node : Node_Id := Empty;
Last : Boolean := False) Last : Boolean := False)
is is
begin begin
SCO_Table.Append ((From, To, C1, C2, Last)); SCO_Table.Append ((From, To, Node, C1, C2, Last));
end Add_SCO; end Add_SCO;
---------------- ----------------
......
...@@ -148,21 +148,27 @@ package SCOs is ...@@ -148,21 +148,27 @@ package SCOs is
-- o object declaration -- o object declaration
-- r renaming declaration -- r renaming declaration
-- i generic instantiation -- i generic instantiation
-- C CASE statement (includes only the expression) -- C CASE statement (from CASE through end of expression)
-- E EXIT statement -- E EXIT statement
-- F FOR loop statement (includes only the iteration scheme) -- F FOR loop statement (from FOR through end of iteration scheme)
-- I IF statement (includes only the condition [in the RM sense, which -- I IF statement (from IF through end of condition)
-- is a decision in the SCO sense])
-- P PRAGMA -- P PRAGMA
-- R extended RETURN statement -- R extended RETURN statement
-- W WHILE loop statement (includes only the condition) -- W WHILE loop statement (from WHILE through end of condition)
-- Note: for I and W, condition above is in the RM syntax sense (this
-- condition is a decision in SCO terminology).
-- and is omitted for all other cases. -- and is omitted for all other cases.
-- Note: up to 6 entries can appear on a single CS line. If more than 6
-- entries appear in one logical statement sequence, continuation lines are
-- marked by Cs and appear immediately after the CS line they continue.
-- Decisions -- Decisions
-- Note: in the following description, logical operator includes only the -- Note: in the following description, logical operator includes only the
-- short circuited forms and NOT (so can be only NOT, AND THEN, OR ELSE). -- short-circuited forms and NOT (so can be only NOT, AND THEN, OR ELSE).
-- The reason that we can exclude AND/OR/XOR is that we expect SCO's to -- The reason that we can exclude AND/OR/XOR is that we expect SCO's to
-- be generated using the restriction No_Direct_Boolean_Operators if we -- be generated using the restriction No_Direct_Boolean_Operators if we
-- are interested in decision coverage, which does not permit the use of -- are interested in decision coverage, which does not permit the use of
...@@ -171,18 +177,27 @@ package SCOs is ...@@ -171,18 +177,27 @@ package SCOs is
-- we are generating SCO's only for simple coverage, then we are not -- we are generating SCO's only for simple coverage, then we are not
-- interested in decisions in any case. -- interested in decisions in any case.
-- Decisions are either simple or complex. A simple decision is a boolean -- Note: the reason we include NOT is for informational purposes. The
-- expresssion that occurs in the context of a control structure in the -- presence of NOT does not generate additional coverage obligations,
-- source program, including WHILE, IF, EXIT WHEN, or in an Assert, -- but if we know where the NOT's are, the coverage tool can generate
-- Check, Pre_Condition or Post_Condition pragma. For pragmas, decision -- more accurate diagnostics on uncovered tests.
-- SCOs are generated only if the corresponding pragma is enabled. Note
-- that a boolean expression in any other context, for example as right -- A top level boolean expression is a boolean expression that is not an
-- hand side of an assignment, is not considered to be a simple decision. -- operand of a logical operator.
-- Decisions are either simple or complex. A simple decision is a top
-- level boolean expresssion that has only one condition and that occurs
-- in the context of a control structure in the source program, including
-- WHILE, IF, EXIT WHEN, or in an Assert, Check, Pre_Condition or
-- Post_Condition pragma. For pragmas, decision SCOs are generated only
-- if the corresponding pragma is enabled. Note that a top level boolean
-- expression with only one condition that occurs in any other context,
-- for example as right hand side of an assignment, is not considered to
-- be a (simple) decision.
-- A complex decision is an occurrence of a logical operator which is not -- A complex decision is a top level boolean expression that has more
-- itself an operand of some other logical operator. If any operand of -- than one condition. A complex decision may occur in any boolean
-- the logical operator is itself a logical operator, this is not a -- expression context.
-- separate decision, it is part of the same decision.
-- So for example, if we have -- So for example, if we have
...@@ -201,7 +216,7 @@ package SCOs is ...@@ -201,7 +216,7 @@ package SCOs is
-- For each decision, a decision line is generated with the form: -- For each decision, a decision line is generated with the form:
-- C*sloc expression -- C* sloc expression
-- Here * is one of the following characters: -- Here * is one of the following characters:
...@@ -217,7 +232,7 @@ package SCOs is ...@@ -217,7 +232,7 @@ package SCOs is
-- For X, sloc is omitted. -- For X, sloc is omitted.
-- The expression is a prefix polish form indicating the structure of -- The expression is a prefix polish form indicating the structure of
-- the decision, including logical operators and short circuit forms. -- the decision, including logical operators and short-circuit forms.
-- The following is a grammar showing the structure of expression: -- The following is a grammar showing the structure of expression:
-- expression ::= term (if expr is not logical operator) -- expression ::= term (if expr is not logical operator)
...@@ -248,8 +263,14 @@ package SCOs is ...@@ -248,8 +263,14 @@ package SCOs is
-- ! indicates NOT applied to the expression. -- ! indicates NOT applied to the expression.
-- In the context of Couverture, the No_Direct_Boolean_Opeartors -- Note that complex decisions do NOT include non-short-circuited logical
-- restriction is assumed, and no other operator can appear. -- operators (AND/XOR/OR). In the context of existing coverage tools the
-- No_Direct_Boolean_Operators restriction is assumed, so these operators
-- cannot appear in the source in any case.
-- The SCO line for a decision always occurs after the CS line for the
-- enclosing statement. The SCO line for a nested decision always occurs
-- after the line for the enclosing decision.
--------------------------------------------------------------------- ---------------------------------------------------------------------
-- Internal table used to store Source Coverage Obligations (SCOs) -- -- Internal table used to store Source Coverage Obligations (SCOs) --
...@@ -265,6 +286,7 @@ package SCOs is ...@@ -265,6 +286,7 @@ package SCOs is
type SCO_Table_Entry is record type SCO_Table_Entry is record
From : Source_Location; From : Source_Location;
To : Source_Location; To : Source_Location;
Node : Node_Id;
C1 : Character; C1 : Character;
C2 : Character; C2 : Character;
Last : Boolean; Last : Boolean;
...@@ -284,27 +306,55 @@ package SCOs is ...@@ -284,27 +306,55 @@ package SCOs is
-- C2 = statement type code to appear on CS line (or ' ' if none) -- C2 = statement type code to appear on CS line (or ' ' if none)
-- From = starting source location -- From = starting source location
-- To = ending source location -- To = ending source location
-- Node = Empty
-- Last = False for all but the last entry, True for last entry -- Last = False for all but the last entry, True for last entry
-- Note: successive statements (possibly interspersed with entries of -- Note: successive statements (possibly interspersed with entries of
-- other kinds, that are ignored for this purpose), starting with one -- other kinds, that are ignored for this purpose), starting with one
-- labeled with C1 = 'S', up to and including the first one labeled with -- labeled with C1 = 'S', up to and including the first one labeled with
-- Last=True, indicate the sequence to be output for a sequence of -- Last = True, indicate the sequence to be output for a sequence of
-- statements on a single CS line. -- statements on a single CS line (possibly followed by Cs continuation
-- lines).
-- Decision (IF/EXIT/WHILE)
-- C1 = 'I'/'E'/'W' (for IF/EXIT/WHILE)
-- C2 = ' '
-- From = IF/EXIT/WHILE token
-- To = No_Source_Location
-- Node = Empty
-- Last = unused
-- Decision (PRAGMA)
-- C1 = 'P'
-- C2 = ' '
-- From = PRAGMA token
-- To = No_Source_Location
-- Node = N_Pragma node or Empty when reading SCO data (see below)
-- Last = unused
-- Decision -- Note: when the parse tree is first scanned, we unconditionally build
-- C1 = decision type code -- a pragma decision entry for any decision in a pragma (here as always
-- in SCO contexts, the only relevant pragmas are Assert, Check,
-- Precondition and Postcondition). Then when we output the SCO info
-- to the ALI file, we use the Node field to check the Pragma_Enabled
-- flag, and if it is False, we suppress output of the pragma decision
-- line. On reading back SCO data from an ALI file, the Node field is
-- always set to Empty.
-- Decision (Expression)
-- C1 = 'X'
-- C2 = ' ' -- C2 = ' '
-- From = location of IF/EXIT/PRAGMA/WHILE token, -- From = No_Source_Location
-- No_Source_Location for X
-- To = No_Source_Location -- To = No_Source_Location
-- Node = Empty
-- Last = unused -- Last = unused
-- Operator -- Operator
-- C1 = '!', '^', '&', '|' -- C1 = '!', '&', '|'
-- C2 = ' ' -- C2 = ' '
-- From = location of NOT/AND/OR token -- From = location of NOT/AND/OR token
-- To = No_Source_Location -- To = No_Source_Location
-- Node = Empty
-- Last = False -- Last = False
-- Element (condition) -- Element (condition)
...@@ -312,12 +362,12 @@ package SCOs is ...@@ -312,12 +362,12 @@ package SCOs is
-- C2 = 'c', 't', or 'f' (condition/true/false) -- C2 = 'c', 't', or 'f' (condition/true/false)
-- From = starting source location -- From = starting source location
-- To = ending source location -- To = ending source location
-- Node = Empty
-- Last = False for all but the last entry, True for last entry -- Last = False for all but the last entry, True for last entry
-- Note: the sequence starting with a decision, and continuing with -- Note: the sequence starting with a decision, and continuing with
-- operators and elements up to and including the first one labeled with -- operators and elements up to and including the first one labeled with
-- Last = True, indicate the sequence to be output for a complex decision -- Last = True, indicate the sequence to be output on one decision line.
-- on a single CD decision line.
---------------- ----------------
-- Unit Table -- -- Unit Table --
...@@ -365,6 +415,7 @@ package SCOs is ...@@ -365,6 +415,7 @@ package SCOs is
To : Source_Location := No_Source_Location; To : Source_Location := No_Source_Location;
C1 : Character := ' '; C1 : Character := ' ';
C2 : Character := ' '; C2 : Character := ' ';
Node : Node_Id := Empty;
Last : Boolean := False); Last : Boolean := False);
-- Adds one entry to SCO table with given field values -- Adds one entry to SCO table with given field values
......
...@@ -3507,26 +3507,16 @@ package body Sem_Warn is ...@@ -3507,26 +3507,16 @@ package body Sem_Warn is
and then Is_Known_Branch and then Is_Known_Branch
then then
declare declare
Start : Source_Ptr;
Dummy : Source_Ptr;
Typ : Character;
Atrue : Boolean; Atrue : Boolean;
begin begin
Sloc_Range (Orig, Start, Dummy);
Atrue := Test_Result; Atrue := Test_Result;
if Present (Parent (C)) and then Nkind (Parent (C)) = N_Op_Not then if Present (Parent (C)) and then Nkind (Parent (C)) = N_Op_Not then
Atrue := not Atrue; Atrue := not Atrue;
end if; end if;
if Atrue then Set_SCO_Condition (Orig, Atrue);
Typ := 't';
else
Typ := 'f';
end if;
Set_SCO_Condition (Start, Typ);
end; end;
end if; end if;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment