-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathcoverage-source.adb
3081 lines (2504 loc) · 108 KB
/
coverage-source.adb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
------------------------------------------------------------------------------
-- --
-- GNATcoverage --
-- --
-- Copyright (C) 2009-2024, AdaCore --
-- --
-- GNATcoverage is free software; you can redistribute it and/or modify it --
-- under terms of the GNU General Public License as published by the Free --
-- Software Foundation; either version 3, or (at your option) any later --
-- version. This software is distributed in the hope that it will be useful --
-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- --
-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public --
-- License for more details. You should have received a copy of the GNU --
-- General Public License distributed with this software; see file --
-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy --
-- of the license. --
------------------------------------------------------------------------------
with Ada.Containers.Vectors;
with Ada.Containers.Ordered_Sets;
with Ada.Containers.Ordered_Maps;
with Ada.Directories;
with Ada.Streams; use Ada.Streams;
with Ada.Unchecked_Deallocation;
with Interfaces;
with GNATCOLL.Projects;
with GNATCOLL.VFS;
with Binary_Files; use Binary_Files;
with Coverage.Tags; use Coverage.Tags;
with Decision_Map; use Decision_Map;
with Diagnostics; use Diagnostics;
with Elf_Disassemblers; use Elf_Disassemblers;
with MC_DC; use MC_DC;
with Outputs; use Outputs;
with Project; use Project;
with Slocs; use Slocs;
with Switches; use Switches;
with Traces_Elf; use Traces_Elf;
with Traces_Files; use Traces_Files;
with Traces_Source; use Traces_Source;
with Types;
package body Coverage.Source is
-- This unit instantiates containers and we want to avoid too much
-- performance cost when using references to their elements, so suppress
-- tampering checks.
pragma Suppress (Tampering_Check);
use Ada.Containers;
function Report_If_Excluded (SCO : SCO_Id) return Boolean;
-- If True, mention in output that SCO cannot be covered (due to absence of
-- any object code whose traces might discharge the SCO).
-- For each source coverage obligation, we maintain a corresponding source
-- coverage information record, which denotes the coverage state of the
-- SCO. Default initialization denotes a completely uncovered state.
package Evaluation_Vectors is new Ada.Containers.Vectors
(Index_Type => Natural,
Element_Type => Evaluation);
package Evaluation_Sets is new Ada.Containers.Ordered_Sets (Evaluation);
procedure Read is new Read_Set
(Element_Type => Evaluation,
Set_Type => Evaluation_Sets.Set,
Clear => Evaluation_Sets.Clear,
Insert => Evaluation_Sets.Insert,
Read_Element => Read);
procedure Write is new Write_Set
(Element_Type => Evaluation,
Set_Type => Evaluation_Sets.Set,
Cursor_Type => Evaluation_Sets.Cursor,
Length => Evaluation_Sets.Length,
Iterate => Evaluation_Sets.Iterate,
Query_Element => Evaluation_Sets.Query_Element,
Write_Element => Write);
type Outcome_Taken_Type is array (Boolean) of Boolean;
No_Outcome_Taken : constant Outcome_Taken_Type := (others => False);
Both_Outcomes_Taken : constant Outcome_Taken_Type := (others => True);
type Line_States is array (Coverage_Level) of Line_State;
type Source_Coverage_Info (Kind : SCO_Kind := Statement) is record
Tag : SC_Tag := No_SC_Tag;
-- Tag identifying one among multiple coverage analyses being performed
-- for a given SCO.
State : Line_States := (others => No_Code);
-- Line state for this SCO. The following invariant should hold:
-- At the same coverage level, a merge of all SCO's states for a given
-- line should be equal to this line's cumulative state.
case Kind is
when Statement =>
Basic_Block_Has_Code : Boolean := False;
-- Set True when code is present for this or any following SCO in
-- basic block.
Executed : Boolean := False;
-- Set True when the statement is known to have been executed
Line_Executed : Boolean := False;
-- Set True when some code on a line intersected by the statement
-- has been executed.
when Decision =>
Outcome_Taken, Known_Outcome_Taken : Outcome_Taken_Type :=
No_Outcome_Taken;
-- Each of these components is set to True when the corresponding
-- outcome has been exercised. Outcome_Taken is set depending
-- on conditional branch instructions, and might be reversed
-- (if the decision has degraded origin). Known_Outcome_Taken
-- is set from dominance information, and is always accurate when
-- set (but may be unset for an outcome that does not dominate
-- any statement).
Evaluations : Evaluation_Sets.Set;
-- Set of all distinct evaluations of this decision (computed for
-- MC/DC only).
when Fun_Call_SCO_Kind =>
Fun_Call_Executed : Boolean := False;
-- Set to True if this call or function was executed at least once
when Guarded_Expr =>
GExpr_Executed : Boolean := False;
-- Set to True if this was executed at least once
when others =>
null;
end case;
end record;
type Source_Coverage_Info_Access is access constant Source_Coverage_Info;
type RW_Source_Coverage_Info_Access is access Source_Coverage_Info;
procedure Write_SCI
(S : access Root_Stream_Type'Class;
SCI : RW_Source_Coverage_Info_Access);
-- Output SCI.all to S
for RW_Source_Coverage_Info_Access'Write use Write_SCI;
procedure Free is
new Ada.Unchecked_Deallocation
(Source_Coverage_Info, RW_Source_Coverage_Info_Access);
package SCI_Vectors is new Ada.Containers.Vectors
(Index_Type => Natural,
Element_Type => RW_Source_Coverage_Info_Access);
package SCI_Vector_Vectors is new Ada.Containers.Vectors
(Index_Type => Valid_SCO_Id,
Element_Type => SCI_Vectors.Vector,
"=" => SCI_Vectors."=");
procedure Read
(CLS : in out Checkpoint_Load_State;
Value : out RW_Source_Coverage_Info_Access);
-- Allocate a new SCI initialized from CLS
procedure Write
(CSS : in out Checkpoint_Save_State;
Value : RW_Source_Coverage_Info_Access);
-- Write a SCI to CSS
procedure Read is new Read_Vector
(Index_Type => Natural,
Element_Type => RW_Source_Coverage_Info_Access,
Vectors => SCI_Vectors,
Read_Element => Read);
procedure Write is new Write_Vector
(Index_Type => Natural,
Element_Type => RW_Source_Coverage_Info_Access,
Vectors => SCI_Vectors,
Write_Element => Write);
procedure Read is new Read_Vector
(Index_Type => Valid_SCO_Id,
Element_Type => SCI_Vectors.Vector,
"=" => SCI_Vectors."=",
Vectors => SCI_Vector_Vectors,
Read_Element => Read);
procedure Write is new Write_Vector
(Index_Type => Valid_SCO_Id,
Element_Type => SCI_Vectors.Vector,
"=" => SCI_Vectors."=",
Vectors => SCI_Vector_Vectors,
Write_Element => Write);
SCI_Vector : SCI_Vector_Vectors.Vector;
Default_SCIs : array (SCO_Kind) of Source_Coverage_Info_Access;
-- Default SCI structures returned by Get_SCI when no specific one has
-- been allocated for a given SCO.
function Get_SCI
(SCO : SCO_Id; Tag : SC_Tag) return Source_Coverage_Info_Access;
-- Return the SCI for the given SCO and tag
procedure Update_SCI
(SCO : SCO_Id;
Tag : SC_Tag;
Process : access procedure (SCI : in out Source_Coverage_Info));
-- Execute Process on the SCI for the given SCO and tag
-- MC/DC evaluation stack
Evaluation_Stack : Evaluation_Vectors.Vector;
procedure Condition_Evaluated
(Exe : Exe_File_Acc;
PC : Pc_Type;
C_SCO : SCO_Id;
C_Value : Boolean);
-- Record evaluation of condition C_SCO with the given C_Value in the
-- current decision evaluation.
function Compute_MCDC_State
(SCO : SCO_Id;
SCI : Source_Coverage_Info) return Line_State;
-- Compute the MC/DC state of SCO, which is already covered for DC
function Compute_ATCC_State
(SCO : SCO_Id;
SCI : Source_Coverage_Info) return Line_State;
-- Compute the ATCC state of SCO, which is already covered for ATC
function Decision_Requires_Coverage (SCO : SCO_Id) return Boolean;
-- Always True for all decisions that are part of a control structure; for
-- other decisions, True if All_Decisions is set, or if the decision is
-- complex and MC/DC is enabled. This function only checks for decisions
-- not belonging to assertions. Note: this can be True even for decisions
-- that are not Decision_Coverable.
procedure Update_State
(Prev_State : in out Line_State;
SCO : SCO_Id;
Tag : SC_Tag;
Level : Coverage_Level;
State : Line_State);
-- Merge State into Prev_State and record State as the coverage state of
-- SCO for Level.
procedure Update_Line_State
(Line : Line_Info_Access;
SCO : SCO_Id;
Tag : SC_Tag;
Level : Coverage_Level;
State : Line_State);
-- Merge State into Line's state for Level, and update SCO's state for
-- the same level so that Source_Coverage_Info.State's invariant holds.
procedure Merge_Checkpoint_SCI
(SCO : SCO_Id;
Tag : SC_Tag;
CP_SCI : Source_Coverage_Info;
Relocs : Checkpoint_Relocations);
-- Merge the given checkpointed coverage information with current coverage
-- info for SCO.
Unit_List_Invalidated : Boolean := False;
-- Keeps track of whether Invalidate_Unit_List was called
Unit_List : Unit_Sets.Set;
-- List of names for units of interest. Store it as an ordered set so that
-- the order of dump depends on its content, not on the way it was created.
package Unit_To_Ignored_Maps is new Ada.Containers.Ordered_Maps
(Key_Type => Compilation_Unit,
Element_Type => Ignored_Sources_Vector_Access);
Ignored_SF_Map : Unit_To_Ignored_Maps.Map;
-- Map units of interest to the list of associated ignored source files
--------------------------
-- Basic_Block_Has_Code --
--------------------------
function Basic_Block_Has_Code (SCO : SCO_Id; Tag : SC_Tag) return Boolean is
begin
return Get_SCI (SCO, Tag).Basic_Block_Has_Code;
end Basic_Block_Has_Code;
------------------------
-- Unit_List_Is_Valid --
------------------------
function Unit_List_Is_Valid return Boolean is
begin
return not Unit_List_Invalidated;
end Unit_List_Is_Valid;
--------------------------
-- Invalidate_Unit_List --
--------------------------
procedure Invalidate_Unit_List (Reason : String) is
begin
-- Log that we can't dump the list of units of interest only the first
-- time.
if Dump_Units and then not Unit_List_Invalidated then
Put_Line
("We will not be able to dump the list of units of interest: "
& Reason);
end if;
Unit_List_Invalidated := True;
Unit_List := Unit_Sets.Empty_Set;
end Invalidate_Unit_List;
--------------
-- Add_Unit --
--------------
procedure Add_Unit (Unit : Compilation_Unit) is
begin
if not Unit_List_Invalidated then
Unit_List.Include (Unit);
end if;
end Add_Unit;
-------------------------------------------
-- Compute_Unit_Name_For_Ignored_Sources --
-------------------------------------------
procedure Compute_Unit_Name_For_Ignored_Sources
is
use Types;
procedure Callback
(Project : GNATCOLL.Projects.Project_Type;
File : GNATCOLL.Projects.File_Info);
-- If the file is a (sometimes) ignored file, compute its unit name and
-- store it in the file table.
--------------
-- Callback --
--------------
procedure Callback
(Project : GNATCOLL.Projects.Project_Type;
File : GNATCOLL.Projects.File_Info)
is
pragma Unreferenced (Project);
use GNATCOLL.VFS;
SFI : constant Source_File_Index := Get_Index_From_Generic_Name
(+File.File.Full_Name, Source_File, Insert => False);
FI : constant File_Info_Access := (if SFI /= No_Source_File
then Get_File (SFI)
else null);
begin
if FI /= null and then not FI.Unit.Known then
declare
Unit : constant Compilation_Unit :=
To_Compilation_Unit (File);
begin
Consolidate_Source_File_Unit (SFI, Unit);
end;
end if;
end Callback;
-- Start of processing for Compute_Unit_Name_For_Ignored_Sources
begin
Enumerate_Sources
(Callback'Access,
Include_Stubs => True,
Language => All_Languages,
Only_UOIs => True);
end Compute_Unit_Name_For_Ignored_Sources;
-------------------------
-- Fill_Ignored_SF_Map --
-------------------------
procedure Fill_Ignored_SF_Map
is
use Unit_To_Ignored_Maps;
procedure Callback (SFI : Types.Source_File_Index);
-- If SFI is a source file that is ignored, register it in
-- Ignored_SF_Map under its unit name. Do nothing otherwise.
--------------
-- Callback --
--------------
procedure Callback (SFI : Types.Source_File_Index)
is
FI : constant File_Info_Access := Get_File (SFI);
Vec : Ignored_Sources_Vector_Access;
begin
if FI.Kind = Source_File
and then FI.Ignore_Status in Always .. Sometimes
then
if not Ignored_SF_Map.Contains (FI.Unit.Name) then
Vec := new Ignored_Sources_Vector.Vector;
Ignored_SF_Map.Insert (FI.Unit.Name, Vec);
else
Vec := Ignored_SF_Map.Element (FI.Unit.Name);
end if;
Vec.Append (FI);
end if;
end Callback;
-- Start of processing for Fill_Ignored_SF_Map
begin
Files_Table_Iterate (Callback'Access);
end Fill_Ignored_SF_Map;
--------------------------
-- Iterate_On_Unit_List --
--------------------------
procedure Iterate_On_Unit_List
(Process_Unit : not null access procedure
(Name : Compilation_Unit);
Process_Source_File : not null access procedure (FI : File_Info))
is
begin
for S of Unit_List loop
Process_Unit.all (S);
if Ignored_SF_Map.Contains (S) then
for FI of Ignored_SF_Map.Element (S).all loop
Process_Source_File (FI.all);
end loop;
end if;
end loop;
end Iterate_On_Unit_List;
------------------
-- Report_Units --
------------------
procedure Report_Units (File : File_Type) is
procedure Print_Ignored_File (FI : Files_Table.File_Info);
-- Print the name of the file and its ignore status
procedure Print_Unit_Name (Unit : Compilation_Unit);
-- Print the unit name
------------------------
-- Print_Ignored_File --
------------------------
procedure Print_Ignored_File (FI : Files_Table.File_Info) is
begin
if FI.Ignore_Status = Files_Table.Sometimes then
Put_Line (File, " " & FI.Unique_Name.all & " sometimes ignored");
elsif FI.Ignore_Status = Files_Table.Always then
Put_Line (File, " " & FI.Unique_Name.all & " always ignored");
end if;
end Print_Ignored_File;
---------------------
-- Print_Unit_Name --
---------------------
procedure Print_Unit_Name (Unit : Compilation_Unit) is
begin
case Unit.Language is
when File_Based_Language =>
Put_Line (File, Ada.Directories.Simple_Name (+Unit.Unit_Name));
when Unit_Based_Language =>
Put_Line (File, +Unit.Unit_Name);
end case;
end Print_Unit_Name;
-- Start of processing for Report_Units
begin
Iterate_On_Unit_List
(Print_Unit_Name'Access, Print_Ignored_File'Access);
end Report_Units;
---------------------
-- Checkpoint_Save --
---------------------
procedure Checkpoint_Save (CSS : access Checkpoint_Save_State) is
begin
CSS.Write_Unbounded (Tag_Provider_Name);
Write (CSS.all, SCI_Vector);
-- For checkpoints only, stream the list of names for units of interest
if CSS.Purpose = Consolidation then
CSS.Write (Unit_List_Invalidated);
if not Unit_List_Invalidated then
CSS.Write_Count (Unit_List.Length);
for N of Unit_List loop
Write (CSS.all, N);
end loop;
end if;
end if;
end Checkpoint_Save;
----------------------
-- Checkpoint_Clear --
----------------------
procedure Checkpoint_Clear is
begin
SCI_Vector.Clear;
Unit_List_Invalidated := False;
Unit_List := Unit_Sets.Empty_Set;
end Checkpoint_Clear;
---------------------
-- Checkpoint_Load --
---------------------
procedure Checkpoint_Load (CLS : in out Checkpoint_Load_State) is
use SCI_Vector_Vectors;
CP_Tag_Provider : Unbounded_String;
CP_SCI_Vector : SCI_Vector_Vectors.Vector;
Relocs : Checkpoint_Relocations renames CLS.Relocations;
Do_Merge : Boolean := True;
begin
-- Checkpointed coverage information can only be loaded if the current
-- tag provider is the default (i.e. no coverage separation), or same
-- as checkpoint.
CP_Tag_Provider := CLS.Read_Unbounded_String;
if Tag_Provider.all not in Default_Tag_Provider_Type
and then Tag_Provider_Name /= +CP_Tag_Provider
then
Warn ("cannot merge coverage information from "
& (+CLS.Filename)
& " as it is separated by " & (+CP_Tag_Provider));
Do_Merge := False;
end if;
-- Extend SCI vector to accomodate any supplementary SCOs loaded from
-- the checkpoint.
Initialize_SCI;
-- Even if we cannot merge coverage information, we must read it in
-- order to be able to decode the rest of the checkpoint.
Read (CLS, CP_SCI_Vector);
if not Do_Merge then
return;
end if;
for SCO_Cur in CP_SCI_Vector.Iterate loop
Process_One_SCO : declare
CP_SCO : constant SCO_Id := To_Index (SCO_Cur);
Removed : constant Boolean := SCO_Ignored (Relocs, CP_SCO);
SCO : constant SCO_Id :=
(if Removed then No_SCO_Id else Remap_SCO_Id (Relocs, CP_SCO));
procedure Insert_Extra_Decision_SCI
(S_Eval : Static_Decision_Evaluation_Sets.Set);
-- Add a set of static evaluations to the rest of the Decision's
-- evaluation set.
procedure Insert_Extra_Decision_SCI
(S_Eval : Static_Decision_Evaluation_Sets.Set)
is
Inserted_SCI : Source_Coverage_Info :=
(Kind => Decision, others => <>);
function To_Evaluation
(SCO : SCO_Id; Static_Eval : Static_Decision_Evaluation)
return Evaluation;
-- Create an `Evaluation` entry from a
-- Static_Decision_Evaluation.
function To_Evaluation
(SCO : SCO_Id; Static_Eval : Static_Decision_Evaluation)
return Evaluation
is
Eval : Evaluation :=
(Decision => SCO,
Outcome => To_Tristate (Static_Eval.Outcome),
Values => Condition_Evaluation_Vectors.Empty,
Next_Condition => No_Condition_Index);
begin
Populate_From_Static_Eval_Vector
(SCO, Static_Eval.Values, Eval.Values);
return Eval;
end To_Evaluation;
begin
if Kind (SCO) /= Decision then
raise Program_Error with "Unexpected " & Kind (SCO)'Image
& " SCO kind registered as a static"
& " decision.";
end if;
SCOs_Trace.Trace ("Inserting "
& S_Eval.Length'Image
& " static SCOs for "
& Image (CP_SCO));
for J in S_Eval.Iterate loop
declare
Eval : Static_Decision_Evaluation renames
S_Eval.Element (J);
begin
Inserted_SCI.Evaluations.Include
(To_Evaluation (CP_SCO, Eval));
Inserted_SCI.Known_Outcome_Taken (Eval.Outcome) := True;
end;
end loop;
Merge_Checkpoint_SCI
(SCO,
Tag_Provider.Map_Tag (Relocs, Inserted_SCI.Tag),
Inserted_SCI,
Relocs);
end Insert_Extra_Decision_SCI;
begin
if CLS.Static_Decision_Evaluations.Contains (CP_SCO) then
-- Check if the current SCO has static evaluations, and
-- merge them as an extra SCI if yes.
Insert_Extra_Decision_SCI
(CLS.Static_Decision_Evaluations.Element (CP_SCO));
end if;
if not Removed then
for CP_SCI of Element (SCO_Cur) loop
if CP_SCI /= null then
Merge_Checkpoint_SCI
(SCO,
Tag_Provider.Map_Tag (Relocs, CP_SCI.Tag),
CP_SCI.all,
Relocs);
end if;
end loop;
end if;
-- Deallocate checkpoint SCIs for this SCO once they have been
-- merged into the main SCI vector.
declare
SCIV : SCI_Vectors.Vector renames
CP_SCI_Vector.Reference (SCO_Cur);
begin
for CP_SCI of SCIV loop
Free (CP_SCI);
end loop;
end;
end Process_One_SCO;
end loop;
-- For checkpoints only (not SID files), load the list of names for
-- units of interest.
if CLS.Purpose = Consolidation then
declare
Invalidated : constant Boolean := CLS.Read_Boolean;
Dummy : Unbounded_String;
begin
if Invalidated then
Invalidate_Unit_List
(+CLS.Filename
& " does not contain the list of units (produced with"
& " --scos or --sid)");
else
for I in 1 .. CLS.Read_Integer loop
Unit_List.Include (CLS.Read_Compilation_Unit);
end loop;
end if;
end;
end if;
end Checkpoint_Load;
------------------------
-- Compute_Line_State --
------------------------
procedure Compute_Line_State
(Line_Num : Positive;
Line_Info : Line_Info_Access;
ST : in out Scope_Traversal_Type)
is
procedure Compute_Condition_Level_Line_State
(SCO : SCO_Id;
SCO_State : Line_State;
Line_Info : Line_Info_Access;
SCI : RW_Source_Coverage_Info_Access;
Level : Coverage_Level)
with Pre => Level in MCDC | UC_MCDC | ATCC;
-- Complete computation of Level coverage state if SCO is covered for
-- the previous less strict coverage level. The coverage status for
-- decision coverage is SCO_State.
--
-- This function is useful for the levels that require to compute
-- the coverage of conditions, namely MCDC and ATCC. Their previous
-- less strict coverage levels are respectively Decision and ATC.
procedure Report_Insufficiently_Instrumented
(SCO : SCO_Id;
Level : Coverage_Level;
Line_Info : Line_Info_Access;
SCI : RW_Source_Coverage_Info_Access);
-- Appropriately report the case in which a SCO is not sufficiently
-- instrumented to compute its coverage for MCDC or ATCC level.
----------------------------------------
-- Compute_Condition_Level_Line_State --
----------------------------------------
procedure Compute_Condition_Level_Line_State
(SCO : SCO_Id;
SCO_State : Line_State;
Line_Info : Line_Info_Access;
SCI : RW_Source_Coverage_Info_Access;
Level : Coverage_Level)
is
begin
if SCO_State = Covered then
-- Complete computation of MC/DC/ATCC coverage state if SCO
-- is covered for decision/ATC coverage.
if not Decision_SCO_Instrumented_For_MCDC (SCO) then
Report_Insufficiently_Instrumented (SCO, Level, Line_Info, SCI);
else
Update_Line_State
(Line_Info,
SCO,
SCI.Tag,
Level,
(if Level in MCDC_Coverage_Level
then Compute_MCDC_State (SCO, SCI.all)
else Compute_ATCC_State (SCO, SCI.all)));
end if;
elsif SCO_State not in No_Code | Undetermined_Coverage then
-- Case of MC/DC or ATCC enabled, and decision / ATC is coverable
-- but at least one outcome was never taken: do not report details
-- regarding MC/DC / ATCC coverage, just record that MC/DC / ATCC
-- is not achieved.
Update_Line_State (Line_Info, SCO, SCI.Tag, Level, Not_Covered);
end if;
end Compute_Condition_Level_Line_State;
-------------------------------------
-- Check_Sufficiently_Instrumented --
-------------------------------------
procedure Report_Insufficiently_Instrumented
(SCO : SCO_Id;
Level : Coverage_Level;
Line_Info : Line_Info_Access;
SCI : RW_Source_Coverage_Info_Access)
is
begin
-- This decision was not instrumented for Level, so report only
-- once for the whole decision, but still mark each condition
-- as not instrumented.
for Cond_Index in 0 .. Last_Cond_Index (SCO) loop
Update_Line_State
(Line_Info,
Condition (SCO, Cond_Index),
SCI.Tag,
Level,
Undetermined_Coverage);
end loop;
Update_Line_State (Line_Info, SCO, SCI.Tag, Level, Covered);
Report_Coverage
(SCO,
SCI.Tag,
"was not instrumented for " & Image (Level),
Undetermined_Cov);
end Report_Insufficiently_Instrumented;
-- Local variables
Multiple_Statements_Reported : Boolean := False;
-- Set True when a diagnosis has been emitted for multiple statements
-- Start of processing for Compute_Line_State
begin
if Line_Info.Coverage_Processed then
-- Recomputing the coverage state for this line has no influence over
-- the resulting coverage state, but will lead to eventual violation
-- messages being emitted multiple times.
return;
end if;
if Line_Info.SCOs = null then
-- No SCOs associated with this source line
-- ??? Have a debug mode to warn if there is object code with
-- this line ?
-- Record that this line has been processed
Line_Info.Coverage_Processed := True;
return;
end if;
-- Examine each SCO associated with line
for SCO of Line_Info.SCOs.all loop
-- Skip the discarded SCOs and those not in a subprogram of interest
if Kind (SCO) = Removed
or else (not Subps_Of_Interest.Is_Empty
and then not In_Scope_Of_Interest (ST, SCO))
then
goto Next_SCO;
end if;
SCOs_Of_Line : declare
SCO_State : Line_State := No_Code;
begin
-- Make sure we have at least one SCI for this SCO
declare
SCIV : SCI_Vectors.Vector renames SCI_Vector.Reference (SCO);
begin
if SCIV.Length = 0 then
SCIV.Append (new Source_Coverage_Info (Kind => Kind (SCO)));
end if;
end;
-- Iterate over all SCIs for this SCO
for SCI of SCI_Vector.Element (SCO) loop
if Kind (SCO) = Statement then
-- Statement coverage: line is covered if any associated
-- statement is executed.
if Ignore_SCO (SCO) then
-- They are neither covered nor not-covered, and need
-- not be reported as bona fide statements excluded from
-- coverage analysis either (see below case).
null;
elsif Unit_Has_Code (SCO)
and then not Basic_Block_Has_Code (SCO, SCI.Tag)
then
-- If a unit has any code at all, then a SCO is marked
-- as covered or not covered if there is code for it, or
-- for a subsequent SCO in the same basic block, else
-- we leave it as No_Code because it won't ever possibly
-- be covered anyway, so that a line ends up marked as
-- No_Code only if no code execution can ever cause it
-- to be marked as covered. However, if no code at all
-- has been seen for the entire unit, this means that
-- the user probably omitted required tests for that
-- unit, so in that case we do not enter this branch
-- (because Unit_Has_Code is False), and so we end up
-- conservatively marking all statements in the unit as
-- not covered (on the basis that they might end up
-- having code, and be marked as not covered, when the
-- code for the unit is actually loaded).
--
-- The distinction of the two cases of no code being
-- present for a SCO is that in the first case, the
-- code for the surrounding unit is present, so we know
-- the compiler definitely did not generate code for
-- that SCO, whereas in the second case the entire object
-- for the unit was generated by the compiler but then
-- omitted at link time, so we don't know for sure
-- whether or not the compiler emitted code for that SCO,
-- so we conservatively assume that it might have.
--
-- Stmt_SCO_Instrumented (SCO) returns false iff the
-- unit was instrumented, but not the particular SCO.
-- In that case, report the SCO as undetermined coverage.
if not Stmt_SCO_Instrumented (SCO)
and then S_Kind (SCO) in Ada_Statement_Kind
then
SCO_State := Undetermined_Coverage;
Report_Coverage
(SCO,
SCI.Tag,
"was not instrumented",
Kind => Undetermined_Cov);
elsif Report_If_Excluded (SCO) then
SCO_State := Not_Coverable;
Report_Exclusion (SCO, SCI.Tag, "has no object code");
end if;
elsif SCI.Executed then
SCO_State := Covered;
elsif SCI.Line_Executed then
if Is_Multistatement_Line (Line_Info.all) then
-- There is more than one statement SCO for this line.
-- When statements do not have full column numbers in
-- debug information, one cannot discriminate between
-- code for multiple statement SCOs on the same line.
-- We therefore conservatively mark each SCO (and
-- hence the complete line) as partially, rather than
-- fully, covered, and we report a coverage violation
-- on the first SCO on the line.
if not Multiple_Statements_Reported then
Multiple_Statements_Reported := True;
Report_Violation
(SCO,
SCI.Tag,
Msg => "^multiple statements on line, unable to "
& "establish full statement coverage");
end if;
SCO_State := Partially_Covered;
else
-- There is just one statement for this line, so we
-- know for certain that it has been executed.
-- Note: Ensure_SCI above guarantees that SCI is an
-- actual specific SCI, not one of the default ones.
SCI.Executed := True;
SCO_State := Covered;
end if;
else
SCO_State := Not_Covered;
-- Generate violation message on first line of SCO
if Line_Num = First_Sloc (SCO).L.Line then
Report_Violation (SCO, SCI.Tag, "not executed");
end if;
end if;
Update_Line_State (Line_Info, SCO, SCI.Tag, Stmt, SCO_State);
elsif Kind (SCO) = Decision
and then First_Sloc (SCO).L.Line /= Line_Num
then
-- For a decision that spans multiple lines, SCO state is
-- computed for the first line, and then cached in the SCI
-- and reused for subsequent lines.
if Decision_Requires_Assertion_Coverage (SCO) then
SCO_State := SCI.State (ATC);
Update_Line_State
(Line_Info, SCO, SCI.Tag, ATC, SCO_State);
if Assertion_Condition_Coverage_Enabled then
SCO_State := SCI.State (ATCC);
Update_Line_State
(Line_Info, SCO, SCI.Tag, ATCC, SCO_State);
end if;
else
if Enabled (Decision) then
SCO_State := SCI.State (Decision);
Update_Line_State
(Line_Info, SCO, SCI.Tag, Decision, SCO_State);
end if;
if MCDC_Coverage_Enabled then
SCO_State := SCI.State (MCDC_Level);
Update_Line_State
(Line_Info, SCO, SCI.Tag, MCDC_Level, SCO_State);
end if;
end if;
elsif Kind (SCO) = Decision
and then ((Decision_Requires_Coverage (SCO)
and then (Enabled (Decision)
or else MCDC_Coverage_Enabled))
or else Decision_Requires_Assertion_Coverage (SCO))
then
-- Compute decision coverage state for this decision. Note